STM32与ADS1292R在心率与体温检测中的LMT70应用与跌到检测解析
实验目的:
以stm32f103c8t6为主控,实时检测心率,体温以及防摔检测,并通过OLED实时显示心率、体温,通过UI制作的小人站立和跌到状态,同时会有蜂鸣器报警警报。
显示效果:
通过我们自研的心电发生器产生固定心率,在oled上显示
硬件器材:
1、ads1292R 心电采集模块。
2、LMT70温度检测传感器。
3、mpu6050陀螺仪。
4、四线 IIC 0.96 OLED。
5、stm32f103c8t6控制板。
6、蜂鸣器跌到报警。
ads1292R从某宝购买,可以显示心电图和心率,这里只需要用到心率,因此将心率显示在OLED上,程序上不是很难,spi通信,但是跟其他模块一起工作时有一个时序问题,我在调试的时候就出现了,显示温度不能显示心率,显示心率则不能显示温度的问题,后来是时序的问题。
LMT70没有买模块,这个温度传感器程序很好实现,通过stm32自带的adc,只需要配置ad采样即可,LMT70输出的是模拟量,根据模拟量还换算温度,有一个温度换算公式,我会在下面写出。
难点在于焊接上,BGA封装,看起来就像一个芝麻大小,四个引脚,不容易焊接,我这种焊接技能满级的选手都打怵,大家还是老实买个模块吧。电路刚开始加了一个运放做跟随器,但是调试的时候发现,温度会乱跳,把电压跟随器摘掉后,温度便恢复正常。
MPU6050主要是用来检测人体跌到的,跌到的部分也是很容易实现,这个模块的难点在于DMP初始化的时候有一个self_detect,也就是第8步的自检,你实际做的时候就会遇到我说的这个问题。解决方法可以参考网上的方法,还有一个难点是,不同家买的模块,解决方法不一样。。。。
检测跌到主要从两个方面,一个是检测加速度,一个是检测倾斜角度,可以都使用,也可以只使用一种方法,但是我发现实际检测的时候加速度很灵敏,我的鼠标在桌子上震动一下,就会提示摔倒,然后我就把这个方法给去掉了,只保留了检测倾斜角度,设置的角度是60度,但是我发现实际的角度快有90度了,这个误差没有影响,60度和90度都可以作为摔倒的检测条件。
检测摔倒用了一个“小人”的图标来表示站立和跌到。
另外加了蜂鸣器,跌到的时候会蜂鸣提示声音,滴滴滴。
软件:
软件很简单了,主要是检测心率,温度,跌到和OLED显示。
LMT70温度检测部分,LMT70传感器有一个算法, 需要将ADC采集的模拟量进行计算,就可以得到实际的温度,我跟实际室温比较了一下,感觉温度没有什么问题。
if(sys_tick - lmt70_tick > 100)
{
lmt70_tick = sys_tick;
AD_value=get_adc();
adc_v=(float)AD_value*3320/4096;
Temp = -1.809628E-09*adc_v*adc_v*adc_v -3.325395E-06*adc_v*adc_v -1.814103E-01*adc_v + 2.055894E+02;
T_sum += Temp;
T_sum_count++;
if(T_sum_count >= 20) //2s计算一次
{
Temp_real = T_sum/T_sum_count; //计算平均温度
T_sum_count = 0;
T_sum = 0;
}
}
OLED_ShowNum(2,7,Temp_real,2); //显示温度数值
printf("Temp=%.1f \r\n",Temp_real);
跌到检测函数,本来想通过加速度和倾斜角度一起来检测,用两个flag,但是发现加速度过于灵敏了,我的鼠标在桌子上震一下,就会触发摔倒检测,后来就用了倾斜角度来做检测,当角度大于80度的时候,便会产生警报,角度也可以设置的小一些,大家可以自行修改。
if(mpu_dmp_get_data(&pitch,&roll,&yaw)==0)
{
// temp=MPU_Get_Temperature(); //得到温度值
MPU_Get_Accelerometer(&aacx,&aacy,&aacz); //得到加速度传感器数据
SVM = sqrt(pow(aacx,2)+ pow(aacy,2) + pow(aacz,2));
//printf("pitch:%0.1f roll:%0.1f yaw:%0.1f SVM:%u\r\n",fabs(pitch),fabs(roll),fabs(yaw),SVM);
//分析x、y、z角度的异常判断
if( fabs(pitch)>60 || fabs(roll)>60 )//倾斜大于60°即认为摔倒
//fabs函数主要用于对浮点数或者整数类型取绝对值
{
mpu_1_flag = 1;
}
else
{
mpu_1_flag = 0;
}
//分析加速度SVM的异常判断
// if( SVM>23000 || SVM<12000 )
// i = 0; //瞬时速度总值
// i++;
// if( i<=10 )
// {
// mpu_2_flag = 1;
// }
// else
// {
// i = 10;
// mpu_2_flag = 0;
// }
//综合欧拉角、SVM异常判断异常
if( mpu_2_flag || mpu_1_flag ){
//跌倒函数
OLED_ShowChinese(4,5,4);
Buzzer_OFF;
Delay_1ms(200);
//Delay_1ms(100);
Buzzer_ON;
//
// Delay_1ms(200);
//Delay_1ms(200);
//mpu_1_flag = 0;
//mpu_1_flag = 0;
}else {
//非跌倒函数
OLED_ShowChinese(4,5,5);
}
}
心率部分比较容易实现了,我们自己的模块就有配套的源码,移植过来就可以直接使用。
Input_data2=(float32_t)(ch2_data^0x800000);
// 实现FIR滤波
arm_fir_f32(&S2, &Input_data2, &Output_data2, blockSize);
// 比较大小
if(min[1]>Output_data2)
min[1]=Output_data2;
if(max[1]<Output_data2)
max[1]=Output_data2;
BPM_LH[0]=BPM_LH[1];
BPM_LH[1]=BPM_LH[2];
BPM_LH[2]=Output_data2;
if((BPM_LH[0]<BPM_LH[1])&(BPM_LH[1]>max[0]-Peak/3)&(BPM_LH[2]<BPM_LH[1]))
{
BPM=(float)60000.0/(point_cnt*4);
point_cnt=0;
}
// 每隔2000个点重新测量一次最大最小值
p_num++;;
if(p_num>2000)
{
min[0]=min[1];
max[0]=max[1];
min[1]=0xFFFFFFFF;
max[1]=0;
Peak=max[0]-min[0];
p_num=0;
}
// 数据:呼吸波、心电信号、心率
//printf("B: %8d",(u32)Output_data1);
//printf("A: %8d",((u32)Output_data2));
// printf("C: %6.2f",(BPM));
OLED_ShowNum(1,7,BPM,3); //显示心率数值
实物视频 :
跌倒检测视屏
作者:沉醉不知归路1