2017年全国大学生电子设计大赛I题可见光定位问题,本方法提供一种基于位置指纹的无线定位思路,需要离线构建无线指纹库(信号强度构成的向量与对应位置标签),再用机器学习算法,例如KNN进行定位,由于比赛只允许在单片机上运行,因此针对比赛用C改写了一个可直接在单片机裸机上运行的KNN算法。
2.为什么要用C
因为诸于python等高级语言编写的机器学习代码需要有操作系统支持,而一般意义上的单片机无法运行Linux,Windows等可以支持高级语言的操作系统,因此需要使用单片机裸机或者ucOS可以支持的C 语言进行改写。
/***********************************
Author: ML_SDD
T: 2017.8.12
***********************************/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define A_L 81
//Map这个二位数组用来保存测量好的[RSS1,RSS2,RSS3,X,Y]
unsigned char Map[A_L][5] = {};
int Dis[A_L][3];//Dis的元素分别为RSS的距离,X,Y的坐标
int k = 3;//初始K=3为找最近的3个样本
unsigned char Input[3]={0};//这里是初始化,要放的是AD做完转换后的RSS数据
//全局变量用于保存x,y的数据,以便使用
unsigned char result_x = 0;
unsigned char result_y = 0;
unsigned char knn_predict(unsigned char *Input)
{
unsigned char i,j,n,p;//for循环控制变量
unsigned char temp_dis,temp_x,temp_y;//数据暂存变量,冒泡排序用
unsigned char result_sum_x = 0;
unsigned char result_sum_y = 0;
for(i=0;i<A_L;i++)
{
Dis[i][0] = sqrt((Map[i][0]-Input[0])^2 + (Map[i][1]-Input[1])^2 + (Map[i][2]-Input[2])^2);
Dis[i][1] = Map[i][3];
Dis[i][2] = Map[i][4];
}
//冒泡排序
for(j=0;j<A_L-1;j++)
{
for(n=0;n<A_L-j-1;n++)
{
if(Dis[n][0]>Dis[n+1][0])
{
temp_dis = Dis[n][0];
Dis[n][0] = Dis[n+1][0];
Dis[n+1][0] = temp_dis;
//------------------
temp_x = Dis[n][1];
Dis[n][1] = Dis[n+1][1];
Dis[n+1][1] = temp_x;
//------------------
temp_y = Dis[n][2];
Dis[n][1] = Dis[n+1][2];
Dis[n+1][2] = temp_y;
}
}
}
for(p=0;p<k;p++)
{
result_sum_x = result_sum_x + Dis[p][1];
result_sum_y = result_sum_y + Dis[p][2];
}
result_x = result_sum_x / k;
result_y = result_sum_y / k;
}