基于STM32设计的健康检测设备(测温心率计步)

发布者:lxy64420245最新更新时间:2022-10-09 来源: csdn关键字:STM32 手机看文章 扫描二维码
随时随地手机看文章

1. 项目介绍

本文介绍的项目是基于STM32设计的健康检测设备,支持体温测量,心率检测,支持运动计步(采用MPU6050陀螺仪实现),支持WIFI传输数据到手机APP打印显示。


硬件环境介绍:


MCU采用STM32F103C8T6


心率传感器采用PulseSensor


体温检测传感器采用红外测温传感器


运动计步功能采用MPU6050陀螺仪实现


OLED显示屏采用0.96寸中景园电子的OLED显示屏-SPI接口


编程软件采用:  keil5


心率传感器:

image-20211230181809837

MPU6050传感器:

image-20211230181847836

体温测温模块

image-20211230181941292

OLED显示屏:

image-20211230182017395

硬件效果图:

image-20211230180229460

image-20211230180246350

image-20211230180313959

image-20211230180519337

工程源码截图:

image-20211230181643594

项目源码下载地址: 基于STM32设计的健康检测设备(测温心率计步)源码.zip-嵌入式文档类资源-CSDN下载


视频演示地址:

基于STM32设计的健康检测设备(测温心率计步)


2. 项目源码介绍

2.1 计步功能实现代码

计步功能是通过MPU6050陀螺仪测量计算得到,下面贴出计步算法的核心实现代码.


/*******************************************************************************

文件名:         stepAlgorithm.c

描述   :        计步算法

*******************************************************************************/

#include "stepAlgorithm.h"

#include "rtc.h"

#include "math.h"

#include "mpu6050.h"

#define TRUE 1   

#define FALSE 0

#define VALUE_NUM 4

sportsInfo_t userSportsInfo;

//存放三轴数据  

float oriValues[3] = {0};    

//用于存放计算阈值的波峰波谷差值  

float tempValue[VALUE_NUM] ={0};  

int tempCount = 0;  

//是否上升的标志位  

u8 isDirectionUp = FALSE;  

//持续上升次数  

int continueUpCount = 0;  

//上一点的持续上升的次数,为了记录波峰的上升次数  

int continueUpFormerCount = 0;  

//上一点的状态,上升还是下降  

u8 lastStatus = FALSE;  

//波峰值  

float peakOfWave = 0;  

//波谷值  

float valleyOfWave = 0;  

//此次波峰的时间  

long timeOfThisPeak = 0;  

//上次波峰的时间  

long timeOfLastPeak = 0;  

//当前的时间  

long timeOfNow = 0;  

//当前传感器的值  

float gravityNew = 0;  

//上次传感器的值  

float gravityOld = 0;  

//动态阈值需要动态的数据,这个值用于这些动态数据的阈值  

float initialValue = (float) 1.3;  

//初始阈值  

float ThreadValue = (float) 2.0;

//三轴轴值

accValue_t accValue;

//行走信息:卡路里、里程、步数

static sportsInfo_t sportsInfo;

//计步缓存

static u8 stepTempCount =0;

/*******************************************************************************

* 函数名:onSensorChanged

* 功能描述: G-Sensor工作后会一直调用这个函数对三轴数据进行平方和开根号的处理  

*                   调用DetectorNewStep检测步子 

*                   

* 参数说明:  

*                 输入:

*                       pAccValue:G-sensor的原始数据

*                       timeStamp_p:动态时间戳

* 返回值说明:

* 修改记录:

*******************************************************************************/

sportsInfo_t *onSensorChanged(accValue_t *pAccValue,timeStamp_t *timeStamp_p,personInfo_t * personInfo) 

{  

  accValue_t *p = pAccValue;

  personInfo_t *userInfo = personInfo;

  timeStamp_t *time_p = timeStamp_p;

  oriValues[0] = p->accX;

  oriValues[1] = p->accY;

  oriValues[2] = p->accZ;

  //对三轴数据进行平方和开根号的处理 

  gravityNew = (float) sqrt(oriValues[0] * oriValues[0]+ oriValues[1] * oriValues[1] + oriValues[2] * oriValues[2]);  

  //检测步子

  return DetectorNewStep(gravityNew,time_p,userInfo); 

}  

/*******************************************************************************

* 函数名:DetectorNewStep

* 功能描述: 

*         步伐更新:如果检测到了波峰,并且符合时间差以及阈值的条件,则判定为1步       

*         阀值更新:符合时间差条件,波峰波谷差值大于initialValue,则将该差值纳入阈值的计算中       

* 参数说明:  

输入:

values:经过处理的G-sensor数据

timeStamp_p:时间戳

* 返回值说明:

* 修改记录:sportsInfo_t *onSensorChanged(accValue_t *pAccValue,timeStamp_t *timeStamp_p,personInfo_t * personInfo)

*******************************************************************************/

sportsInfo_t *DetectorNewStep(float values,timeStamp_t *timeStamp_p,personInfo_t * personInfo) 

{  

  static u32 time_old;

  personInfo_t *userInfo = personInfo;

  static u32 step_per_2_second;  //每两秒所走的步数

  float step_lenth,walk_speed,walk_distance,Calories;//步长

  u32 time_now;

  timeStamp_t *time_p = timeStamp_p;

  if (gravityOld == 0) 

  {  

    gravityOld = values;  

  } 

  else 

  {  

    if (DetectorPeak(values, gravityOld))//检测到波峰

    {  

      timeOfLastPeak = timeOfThisPeak;//更新上次波峰的时间  

      //将时间戳转换为以毫秒ms为单位

      time_now = timeOfNow = ((time_p->hour*60+time_p->minute)*60+time_p->second)*1000+time_p->twentyMsCount*20; //获取时间 ,并转化为毫秒

      //如果检测到了波峰,并且符合时间差以及阈值的条件,则判定为1步 

      if (  (timeOfNow - timeOfLastPeak >= 250 )//Jahol Fan 修改为300,防止轻微动都也会检测步子

          //&& (timeOfNow - timeOfLastPeak <= 2000)

          &&(peakOfWave - valleyOfWave >= ThreadValue)

            )

      {  

        timeOfThisPeak = timeOfNow; //更新此次波峰时间 

        

        

        stepTempCount++;//Jahol:加1为两步

        step_per_2_second ++;

        //Jahol:这样计算卡路里,不能滤除人为的误操作,导致的结果是:里程和卡路里偏大

        if((time_now - time_old) >= 2000 )    //如果时间过了2秒

        {

          if( 1 == step_per_2_second )                 

          {

            step_lenth = userInfo->height/5;

          }

          else if( 2 == step_per_2_second )

          {

            step_lenth = userInfo->height/4;

          }

          else if( 3 == step_per_2_second )

          {

            step_lenth = userInfo->height/3;

          }

          else if( 4 == step_per_2_second )

          {

            step_lenth = userInfo->height/2;

          }

          else if(5 == step_per_2_second)             //Jahol:为了使计步准确,设置上限值为5步,牺牲卡路里准确性

          {

            step_lenth = userInfo->height/1.2f;

          }

          else if( 7 == step_per_2_second )

          {

            step_lenth = userInfo->height;

          }

          else if(step_per_2_second >= 8)               //      step_diff>8

          {

            step_lenth = userInfo->height*1.2f;

          }

          else 

          {

            step_lenth = 0;

          }

          walk_speed = step_per_2_second*step_lenth/2;   //速度 ,单位:米/秒

          walk_distance  = step_per_2_second*step_lenth; //行走距离,单位:米

          Calories = 4.5f*walk_speed*(userInfo->weight/2)/1800;  //Jahol:weight是以kg为单位

          sportsInfo.calories  += Calories;

          sportsInfo.distance  += walk_distance;        

          time_old = time_now;         //更新时间

          step_per_2_second = 0;

          

        }   

        else 

        {

          //do nothing

        }       

        /* 

        * 处理无效运动: 

        * 1.连续记录5才开始计步 

        * 2.例如记录的步用户停住超过3秒,则前面的记录失效,下次从头开始 

        * 3.连续4记录了步用户还在运动,之前的数据才有效 

        * */                

        if ((stepTempCount< 5 )&&(timeOfNow - timeOfLastPeak >= 3000))          

        {

          stepTempCount = 0;

        }

        else if((stepTempCount>= 5)&&(timeOfNow - timeOfLastPeak <= 3000))

        {

          sportsInfo.stepCount += stepTempCount;          

          stepTempCount         = 0;                

        }

        else

        {

          //do nothing

        }

        

        

      }  

      //Jahol:更新阀值,问题:阀值不会一直变大,不能变小?

      if (timeOfNow - timeOfLastPeak >= 250  

          && (peakOfWave - valleyOfWave >= initialValue)) 

      {  

        timeOfThisPeak = timeOfNow;  

        ThreadValue = Peak_Valley_Thread(peakOfWave - valleyOfWave);//更新阀值  

[1] [2] [3]
关键字:STM32 引用地址:基于STM32设计的健康检测设备(测温心率计步)

上一篇:基于STM32+ESP8266+华为云IoT设计的云端绿化管理系统
下一篇:基于STM32设计的数字电子秤

小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
  • 学习ARM开发(16)
    ARM有很多东西要学习,那么中断,就肯定是需要学习的东西。自从CPU引入中断以来,才真正地进入多任务系统工作,并且大大提高了工作效率。采 ...
  • 学习ARM开发(17)
    因为嵌入式系统里全部要使用中断的,那么我的S3C44B0怎么样中断流程呢?那我就需要了解整个流程了。要深入了解,最好的方法,就是去写程序 ...
  • 学习ARM开发(18)
    上一次已经了解ARM的中断处理过程,并且可以设置中断函数,那么它这样就可以工作了吗?答案是否定的。因为S3C44B0还有好几个寄存器是控制中 ...
  • 嵌入式系统调试仿真工具
    嵌入式硬件系统设计出来后就要进行调试,不管是硬件调试还是软件调试或者程序固化,都需要用到调试仿真工具。 随着处理器新品种、新 ...
  • 最近困扰在心中的一个小疑问终于解惑了~~
    最近在驱动方面一直在概念上不能很好的理解 有时候结合别人写的一点usb的例子能有点感觉,但是因为arm体系里面没有像单片机那样直接讲解引脚 ...
  • 学习ARM开发(1)
  • 学习ARM开发(2)
  • 学习ARM开发(4)
  • 学习ARM开发(6)
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved