概述
硬件上使用STM32F4+MPU9150实现的神经网络识别手势,不过没有用IMU的地磁数据,只用了三轴加速度计和三轴陀螺仪的数据,板子是自己画的主要参照了意法官方的开发板的原理图(人生画的第一个板子还没有错误哈,容小逗比高兴一下。。。)。MPU9150的驱动是用的InvenSense提供的eMPL硬件抽象层,虽然这个driver配置imu内置DMP比较方便,但感觉这个bias矫正和姿态解算做的并不是很好,而且源码没公开不好改。不过识别部分用的是原始数据没用融合出的姿态数据,(姿态用在另一个功能上了)。考虑到单片机的计算性能不高(其实是训练部分不好移植^_^)于是把网络的训练部分放在在matlab上做的,然后把训练完的网络的阈值和权值导出来,放到单片机里。这里涉及到了单片机采集的数据怎么发给matlab的问题,幸好高版本的matlab对硬件的支持有大幅提升,可以通过串口来收数据。网络在单片机上的识别过程计算量还是挺大的,原始的imu数据(6Dof)经过一个巴特沃斯低通滤波器后放到一个类似于FIFO的数据结构中,从这个FIFO中首先进行间隔取数(间隔根据手势动作时间计算),并对取出的数进行归一化,然后将这些数据传给网络进行识别。过程中的滤波、归一化和网络计算都要进行大量的浮点运算,于是把logsig函数由泰勒展开改成了查表,还开了FPU,用了CMSIS-DSP。
Matlab串口接收
下面是创建串口obj的脚本
try
try
obj=serial('COM15','baudrate',115200,'parity','none','databits',8,'stopbits',1);
flag_fetch=1;
catch
fprintf('Create Obj Error');
end
obj.BytesAvailableFcnMode = 'terminator';
obj.Terminator = 'c';
obj.BytesAvailableFcn =@serial_nn_callback;
try
fopen(obj);
catch
fprintf('Open Error\n');
break;
end
pause;
flag_fetch=0;
catch
fprintf('Serial Read Error!\n');
end
fclose(obj);
delete(obj);
clear obj;
下位机将imu数据以数据帧的形式发送上来,数据帧自定义协议,帧以字符’c’结尾,这里将串口配置为terminator模式,设置terminator=’c’,这样该模式下接收到字符’c’就调用一次回调函数”serial_nn_callback”
下面是回调函数的框架:
function [c]= serial_nn_callback(obj, ~)
% var start
...
% var end
try
n = get(obj, 'BytesAvailable');
if n>20&& (flag_fetch==1)
a = fread(obj, 29, 'uchar');%数据帧长度
if a(1)~='A'
fscanf(obj) ;
end
% 协议解析 start
% 协议解析 end
end
catch
end
这里读取之后要首先判断数据帧头是否吻合,如果不吻合立即调用 fscanf(obj) 清除串口的缓存,否则的话接收到的数据都是串的。这样就可以成功的接收到下位机发送的数据。 |