前言

电源方向资料免费开源到QQ群1:280730348QQ群2:725438563QQ群3:961600221QQ群4:961951045QQ群5:966375130QQ群6:1065090414

嵌入式方向资料免费开源到QQ群1:976387827QQ群2:418493877

博客地址edadong.com,博文同步发布在知乎、bilibili,其中bilibili主要以视频为主。对开源项目的疑惑请尽量在b站下方留言,其次在群内商讨,所有开源项目均自己设计验证过。

由于个人精力有限,以后不做私聊问题回答,但B站我会做最快的响应回答,此初衷主要是想更多人看到问题的解决方法或者开源项目这么做的意义,在B站解答大家都能看得到,私人解答就丢失了开源解答的优势了。

更详细的讲解请移步Bilibili:EDAdong。

设计目标和方案

常见智能健康监测

关键代码及原理图

姿态检测:

    //姿态变动算法检测,1s进行一次计算		
		norm = sqrt(aacx*aacx + aacy*aacy + aacz*aacz);//姿态解算
		ax = (float)aacx / norm; 
		ay =  (float)aacy / norm; 
		az =  (float)aacz / norm; 	
		if(DIE_count==1)
		{
			ay_1=ay;
			ax_1=ax;
		}
		else if(DIE_count==100)
		{
			ay_2=ay;
			ax_2=ax;
			error_y=ay_1-ay_2;
			error_x=ax_1-ax_2;
		  if(error_y>0.3||error_y<-0.3||error_x>0.3||error_x<-0.3&&(TimeData.hour>=time_shangxian_yuzhi||TimeData.hour<=time_xiaxian_yuzhi))
		  {
				if(zitai_valid==0)
			    diedao_count=diedao_count+1;
				else
			    diedao_count=diedao_count;					
				zitai_valid=1;
		  }
			DIE_count=0;
		}		
		if(zitai_valid)
		{
			zitai_count++;
			if(zitai_count>=1000)//10s有效一次检测
			{
				zitai_count=0;
				zitai_valid=0;
			}
		}
		if((heart_data<40||heart_data>180)&&(TimeData.hour>=time_shangxian_yuzhi||TimeData.hour<=time_xiaxian_yuzhi))
		{
      if(hheart_valid==0)
			    hbodong_count=hbodong_count+1;
				else
			    hbodong_count=hbodong_count;					
				hheart_valid=1;
		}
		if(hheart_valid)
		{
			hheart_count++;
			if(hheart_count>=1000)//10s有效一次检测
			{
				hheart_count=0;
				hheart_valid=0;
			}
		}

心率监测:

u16 PreReadData;
u16 ReadData;
u16 data[50];
u16 max;
u16 min;
u16 mid;
u8 heart_valid;
u8 pre_heart_valid;
u8 heart_count;
u16 time_count;
u16 firsttime;
u16 secondtime;
u16 IBI;
u8 BPM;

uint16_t FindMin(uint16_t arr[], uint8_t len) {
    uint16_t min = arr[0];
    for (uint8_t i = 1; i < len; i++) {
        if (arr[i] < min) {
            min = arr[i];
        }
    }
    return min;
}
 
uint16_t FindMax(uint16_t arr[], uint8_t len) {
    uint16_t max = arr[0];
    for (uint8_t i = 1; i < len; i++) {
        if (arr[i] > max) {
            max = arr[i];
        }
    }
    return max;
}
void heart_test(u16 heart_datain,u8 index)
{
	PreReadData = ReadData;
	ReadData = heart_datain;
  if((ReadData - PreReadData) < 1000)    // 滤除突变噪声信号干扰
    data[index] = ReadData;	// 填充缓存数组	
  if(index >= 49)
  {			
    // 通过缓存数组获取脉冲信号的波峰、波谷值,并计算中间值作为判定参考阈值
    max = FindMax(data, 50);
    min = FindMin(data, 50);
    mid = (max + min)/2;
  }	
	pre_heart_valid = heart_valid;
	heart_valid = (ReadData>mid) ? 1 : 0;
	if(pre_heart_valid == 0 && heart_valid == 1)
	{
		heart_count++;
		heart_count%=2;
		if(heart_count==1)
		{
			firsttime = time_count;
		}
		if(heart_count==0)
		{
			secondtime = time_count;
			time_count=0;
      if((secondtime > firsttime))
      {
        IBI = (secondtime - firsttime) * 20;	// 计算相邻两次脉搏的时间,得到 IBI
        BPM = 60000 / IBI;  // 通过 IBI 得到心率值 BPM  
        if (BPM > 200)    //限制BPM最高显示值
          heart_data = 200;	 				
        else if (BPM < 30)    //限制BPM最低显示值
          heart_data=30;
				else 
					heart_data=BPM;
      }
		}
	}
}	
    
 
    //心率检测算法
		heart_co++;
		if(heart_co==2)
		{
			heart_co=0;
		  time_count++;
		
	    ADC_ConvertedValueLocal=ADC_ConvertedValue[0];
      heart_test(ADC_ConvertedValueLocal,HEART_count);
		  HEART_count++;
		  if(HEART_count>=50)HEART_count=0;
		}

image-20251008232120708

总结

通过网盘分享的文件:post30常用跌倒检测及心率测量 链接: https://pan.baidu.com/s/1eTpVTw-tOFfQYvNetHt3yw?pwd=uvhj 提取码: uvhj —来自百度网盘超级会员v6的分享