0
点赞
收藏
分享

微信扫一扫

最简单片机可执行KNN算法

陌岛 2022-08-10 阅读 88


接手一个简单的水位预警项目,没使用传统规则进行判断,使用机器学习算法进行判断:

已完成代码如下,接下来就是扩大训练集,11个样本的数据肯定是不够的

每个传感器0表示未超出,1表示超出,最后也是:1表示水位预警,0表示正常工作。

每5s采集一次数据,进行判断,如果判断为水位超出液面,那就发出警报(BEEP = 1, WARNING = 1)

//头文件引入
#include<reg51.h>
#include<stdio.h>
#include<math.h>
#include<stdlib.h>
#include<string.h>

//宏定义
#define N 11 //训练集有1000组数据
#define K 5 //设置KNN临近距离为5
#define CIRCLE 5 //设置周期为5秒
#define SIZE 2 //设置通用交换函数交换字节大小

//引脚定义
sbit S1 = P0^1; //传感器1
sbit S2 = P0^2; //传感器2
sbit S3 = P0^3; //传感器3
sbit BEEP = P3^4; //蜂鸣器
sbit WARNING = P3^5; //预警引脚

//相关常量、变量定义
code unsigned char DataSet[N][16] = { //训练数据集,每组数据16个特征,对应3个传感器5秒内数据,以及对应的结果:是否溢出
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
};
unsigned int Dis[N][2]; //每组数据2个元素,对应15份传感器数据距离,以及结果

//通用交换函数
void swap(void *a, void *b) {
unsigned char buffer[SIZE];
memcpy(buffer, a, SIZE);
memcpy(a, b, SIZE);
memcpy(b, buffer, SIZE);
}

//knn算法预测结果
unsigned char KnnPredict(unsigned char *Data) {
unsigned char i, j, result;
unsigned char sum = 0;
for (i = 0; i < N; i++) {
unsigned int tmp = 0;
for (j = 0; j < 15; j++) {
tmp = tmp + (DataSet[i][j] - Data[j]) * (DataSet[i][j] - Data[j]);
}
Dis[i][0] = sqrt(tmp);
Dis[i][1] = DataSet[i][15];
}
for (i = 0; i < N - 1; i++) {
for (j = 0; j < N - i - 1; j++) {
if (Dis[j][0] > Dis[j + 1][0]) {
swap(&Dis[j][0], &Dis[j + 1][0]);
swap(&Dis[j][1], &Dis[j + 1][1]);
}
}
}
for (i = 0; i < K; i++) {
sum = sum + Dis[i][1];
}
result = sum / K;
return result;
}

//延时函数,延时t秒
void Delay(unsigned char t) {
unsigned int i, j;
for (i = 0; i < 10000 * t; i++) {
for (j = 0; j < 124; j++) {
}
}
}

//主函数
void main(){
while(1) {
unsigned char Data[15] = {0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0};//测试数据
unsigned char i;
for (i = 0; i < CIRCLE; i++) { //获取一个周期(5秒)内的所有传感器数据,3个为一组,共5组15个
Data[i * 3] = S1; //Data[0], Data[3] ... Data[12]记录1-5秒内传感器1的数据
Data[i * 3 + 1] = S2; //Data[1], Data[4] ... Data[13]记录1-5秒内传感器2的数据
Data[i * 3 + 2] = S3; //Data[2], Data[5] ... Data[14]记录1-5秒内传感器3的数据
Delay(1); //延时1秒
}
if (KnnPredict(Data) == 1) { //如果判断为水位超出
BEEP = 1; //蜂鸣器发声
WARNING = 1; //发出警报信号
}
}
}

 

举报

相关推荐

0 条评论