ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

基于STM32的人体健康监测系统:温度、心率与摔倒检测

基于STM32的人体健康监测系统:温度、心率与摔倒检测 简介综合STM32外设与多种传感器的人体健康监测工程面向嵌入式学习者、养老监护产品开发者实现体温、心率与老人跌倒检测并通过串口/UART、蓝牙或Wi-Fi上报至网关或APP。资源包共230个文件、29.37MB以C源码、H头文件、Keil工程文件uvprojx/uvoptx为主另有编译生成的axf/hex、MPU6050相关配置及图片文档便于直接查看与二次开发。已有300人学习/下载。内含完整STM32工程与MPU6050跌倒检测驱动、传感器数据处理逻辑可帮助读者理解PPG/ECG心率采集、体温阈值判断、姿态识别与异常报警流程适合作为课程设计或居家监护项目参考。 正好最近把一个基于STM32的人体健康监测项目完整做了一遍温度、心率、老人摔倒检测三个功能全部打通。做完之后最大的感触是这种健康监测类项目看着简单但把每个传感器单独调通容易放在一个系统里稳定跑起来才是真正的坎。如果你打算拿这类项目做毕设或者想快速搭一个可演示的健康监测原型这篇内容可以帮你少走很多弯路。我先说结论整个项目用STM32F103C8T6最小系统板就能搞定不需要上太高配的芯片。传感器方面温度用DS18B20心率用MAX30102摔倒检测用MPU6050再配一个0.96寸OLED显示和蜂鸣器报警。整套物料成本很低但覆盖的知识点非常全面单总线协议、I2C通信、六轴姿态解算、信号滤波、阈值判断、状态机设计基本上嵌入式开发的核心基本功都练了一遍。1. 项目定位与整体方案设计1.1 三个功能模块的核心需求先拆解一下标题里的三个关键词每一个背后对应的是完全不同的技术路线。温度检测需求是实时采集人体体温并显示。人体温度范围一般在35℃到42℃之间精度要求到小数点后一位就够。这个功能最简单用DS18B20数字温度传感器就可以单总线协议直接输出数字量不需要ADC采样也不用信号放大对于新手来说非常友好。心率检测需求是实时获取每分钟心跳次数BPM。这里有两种方案一种是光电式方案用MAX30102这种反射式血氧心率传感器通过红光和红外光照射皮肤检测血液容量变化引起的反射光强度波动再经过滤波和波峰检测算出心率另一种是电极式方案用类似心电贴片的电极采集心电信号但对模拟前端的要求高很多不适合入门项目。我选的是MAX30102理由是它自带的I2C接口和完整的寄存器库可以在STM32上快速驱动起来而且一颗芯片还能同时测血氧后续想扩展也方便。老人摔倒检测需求是在老人意外摔倒时自动识别并触发报警。这个功能对实时性和准确性的要求最高核心是靠MPU6050六轴传感器采集三轴加速度和三轴角速度数据然后通过姿态解算和阈值判断识别摔倒动作。难点在于怎么区分“正常弯腰捡东西”和“真的摔倒”单纯看加速度幅值很容易误报需要结合姿态角变化量和摔后静止状态做多级判断。1.2 为什么选STM32F103C8T6这个项目也考虑过用ESP32或者K210。ESP32的优势是自带WiFi和蓝牙省去外接无线模块但它的ADC精度和时序控制能力不如STM32稳定K210的优势是能跑轻量级AI模型可以做摔倒图像识别但对传感器数据融合来说有点大材小用而且开发门槛高不适合作为健康监测的基础平台。STM32F103C8T6的优势在于72MHz主频足够跑姿态解算和滤波算法Flash和SRAM容量也够用外设资源丰富I2C、SPI、USART、定时器一应俱全。最关键的是生态成熟遇到问题网上几乎都能找到答案HAL库和标准库的资料都很全。对于这种多传感器数据采集类项目STM32属于“不掉链子”的选择。传感器分工上DS18B20接一个普通GPIO靠单总线协议读数据MAX30102和MPU6050、OLED共用一条I2C总线通过设备地址区分MAX30102是0x57MPU6050是0x68OLED是0x3C一条总线上挂三个设备完全没有压力。蜂鸣器接一个GPIO用来报警整个系统的外设占用非常精简。2. 三个核心功能的实现原理与细节2.1 DS18B20温度采集的单总线时序DS18B20看起来简单但它用的是单总线协议一根数据线既要发指令又要读数据时序要求非常严格。单总线的本质就像两个人共用一个对讲机一次只能有一个人说话所以通信前必须有严格的握手过程。每次读取温度的完整流程是这样主机拉低总线480微秒以上产生复位脉冲然后释放总线等待DS18B20应答应答成功后再发跳过ROM命令0xCC和启动温度转换命令0x44等待温度转换完成转换时间跟分辨率有关12位分辨率下最长需要750毫秒之后再次复位、跳过ROM、发送读暂存器命令0xBE依次读出两个字节的温度数据组合成带符号的16位温度值再乘以0.0625就是实际温度。时序上有几个细节很关键复位脉冲的时间不能太短否则传感器可能不响应数据位的读写时隙最好控制在60到120微秒之间读数据时主机拉低总线后在15微秒内采样电平这个时间窗口比较苛刻所以我不建议直接用delay估算最好用定时器或者逻辑分析仪先确认时序是准确的。我实际调试时遇到过读回来的温度一直显示85℃的情况那是上电后的默认值通常是复位时序不对或者上拉电阻缺失导致的。2.2 心率检测MAX30102的信号调理与波峰识别MAX30102的原理是光电容积脉搏波描记法PPG。红光和红外光照射到皮肤上时血液对光的吸收量会随心脏搏动周期性地变化。心脏收缩时血液容量增加反射光强度变小心脏舒张时血液容量减少反射光强度变大。传感器内部的ADC把这个光强度的微小波动转换成数字信号我们就能从信号波形中找到周期性的峰谷计算相邻两个波峰之间的时间间隔再用60秒除以间隔就是心率值。但实际问题比原理看起来要复杂得多。MAX30102输出的原始信号有很强的直流分量手指的按压力度、环境光的干扰、轻微的手部抖动都会叠加在信号上直接做波峰检测会得到一堆假峰心率数值就会乱跳。我的处理思路是分三步第一步用滑动平均滤波消除高频噪声。我取最近10个采样点做平均等效于一个低通滤波器能把毛刺削掉。第二步去掉基线漂移。用连续N个采样点的平均值作为当前基线用原始值减去基线得到近似交流分量。第三步动态阈值波峰检测。信号上升超过了当前阈值的1.5倍并且下降后低于阈值记录为一个波峰然后进入一个300毫秒的不应期防止同一个波被多次检测。心率计算的稳定性还依赖于采样周期的一致性所以MAX30102的数据读取不能放在主循环里用delay模拟我用的是定时器中断设定10毫秒采一次样本保证100Hz的稳定采样率这样计算出来的BPM才有参考价值。实测下来静坐状态下测量精度可以做到±3BPM左右手部晃动时误差就会变大这也是光电式心率传感器的物理限制。2.3 摔倒检测MPU6050的数据融合与判断策略MPU6050内部集成了三轴加速度计和三轴陀螺仪加速度计可以测量物体在三个轴向上受到的加速度陀螺仪可以测量三个轴上的旋转角速度。摔倒检测最常用的算法不是姿态解算的欧拉角而是直接利用加速度幅值加姿态角变化的综合判断。算法核心公式是先计算合成加速度幅值am sqrt(ax^2 ay^2 az^2)正常站立时因为重力加速度等于1g所以合成加速度幅值大约在1g附近。人摔倒时身体会经历一个先失重后撞击的过程失重阶段合成加速度小于0.8g撞击阶段合成加速度会瞬间冲到2.5g甚至3g以上。单看这一下还不够因为老人猛地下蹲、跳起落地也可能触发这个条件。所以我的状态机分了三段第一段是“疑似摔倒”当合成加速度幅值超过3g持续20毫秒以上进入疑似状态。这个阈值要留有余量不能设得太低否则走路跺脚、关门震动都可能触发。第二段是“姿态验证”疑似状态触发后检查倾斜角是否发生了大变化。摔倒后人体大概率会从直立状态变成接近水平状态我用加速度计的静态分量计算俯仰角和横滚角判断角度变化是否超过45度。第三段是“静止确认”摔倒后老人通常不会立刻站起来会有一段静止期所以触发疑似后如果在1到2秒内合成加速度幅值持续在0.8g到1.2g之间说明人已经躺平不动了这时候才判定为摔倒并触发蜂鸣器报警。这个三段式判断实测效果很好快速蹲下、弯腰系鞋带、正常走路这些动作基本都能过滤掉。调参的时候要注意阈值和持续时间不是固定的跟传感器的安装位置、佩戴方式都有关系最稳妥的办法是在同一佩戴姿势下采集几组正常动作和摔倒动作的数据再回头定阈值。3. 系统搭建、代码实现与联调3.1 硬件接线和工程搭建要点硬件接线是整个系统里最简单的部分。DS18B20的数据引脚接PB1注意数据线上需要接一个4.7k欧姆上拉电阻到3.3V如果直接买DS18B20模块模块上一般已经带了上拉电阻。MAX30102、MPU6050和OLED都挂到STM32的I2C1上SCL接PB6SDA接PB7三个设备共用一个I2C总线用各自的地址区分。蜂鸣器接PA8通过三极管驱动不要直接用GPIO推蜂鸣器电流不够。外设接口引脚备注DS18B20单总线PB1需要4.7k上拉电阻MAX30102I2C1PB6/PB7设备地址0x57MPU6050I2C1PB6/PB7设备地址0x68OLED 0.96寸I2C1PB6/PB7设备地址0x3C蜂鸣器GPIO推挽输出PA8三级管驱动工程搭建上我建议直接在STM32CubeMX里生成HAL库工程勾选I2C、定时器、GPIO就可以省去手动建库的很多麻烦。如果你习惯标准库也没问题但需要注意“keil5兼容c51和stm32安装”这个坑Keil MDK和Keil C51是两个独立的工具链安装到同一目录下可能会互相覆盖所以装的时候建议分开两个目录然后用Pack Installer安装对应的STM32F1系列器件支持包。工程里如果要建标准库模板记得把启动文件startup_stm32f10x_hd.s和系统文件system_stm32f10x.c都加进工程这是很多人新建工程失败的原因。下载程序的时候需要注意BOOT0引脚的启动模式设置。BOOT0接地时从主Flash启动这是正常运行模式BOOT0接高电平时从系统存储器启动用于串口下载。用ST-Link下载时BOOT0保持接地就行但如果下载失败可以先检查启动模式是不是被拉到了高电平另外确认“stm32启动模式与存储器重映射”对应关系没问题也检查ST-Link驱动是否识别到了芯片。3.2 核心代码实现与参数调优代码的核心逻辑是“主循环定时器中断”的结构。主循环负责处理显示和报警状态定时器中断负责传感器的数据采集这样的好处是采样时间严格可控不会因为OLED刷新慢而影响心率数据的稳定性。温度读取的代码逻辑很直接复位、发命令、读数据、计算温度温度转换期间不能让出总线等待时必须严格按照手册的时间延时。主循环里我每隔1秒读一次温度这个频率对体温监测来说完全够用。心率检测的代码核心是波峰检测函数。我用一个环形缓冲区存最近20秒的波峰间隔时间每次检测到新波峰就把当前时间和上次波峰时间做差得到本次心跳间隔然后取最近5个间隔的中位数作为稳定心率。这里有两个细节值得注意第一是取中位数而不是平均值因为偶发的假波峰会拉高平均值中位数对离群值更鲁棒第二是每次检测到波峰后要清除信号的不应期标志否则会把下一次心跳当成同一波漏掉。摔倒检测的状态机是独立的一个模块每50毫秒读取一次MPU6050的加速度和陀螺仪数据。合成加速度的计算用到了sqrt和powSTM32F103的浮点运算能力虽然一般但这里只是简单的乘法和开方主频72MHz下没有任何压力。角度计算我用的是加速度计静态解算不用上卡尔曼滤波因为摔倒检测本身是瞬态事件静态解算的速度足够快而且代码简单可靠。阈值参数我最终用的是一组经验值疑似摔倒是合成加速度大于2.8g持续30毫秒姿态角变化大于50度静止确认时间是1.5秒。这几个值不是拍脑袋定的我让朋友做了10次模拟摔倒和20次日常动作弯腰、蹲下、坐下、走路的测试统计了两类动作的加速度和角度范围然后取了一个区分度最大的阈值区间。调整阈值的时候建议做成宏定义方便反复试验。4. 常见问题与排查技巧实录4.1 典型问题的排查速查表项目开发过程中踩过不少坑我把最典型的问题整理成了一张排查表后面再做同类项目可以直接对照。现象可能原因排查方法DS18B20读回85℃或-127℃上拉电阻缺失、复位时序不对、引脚配置错误检查上拉电阻到4.7k用逻辑分析仪看复位脉冲时间心率数值乱跳或为0采样率不稳定、未滤波、手指按压过轻/过重确认定时器采样频率检查原始波形是否能看到清晰波峰MPU6050读数全为0或不变I2C地址冲突、模块供电不足、SDA/SCL接反用I2C扫描程序确认总线上各设备地址蜂鸣器频繁误报加速度阈值过低、安装了传感器但未固定增大阈值或加长持续时间窗口做动作区分测试程序卡死在delay函数定时器中断里调用了阻塞延时、SysTick冲突检查中断服务函数中是否有delay调用ST-Link连接不上芯片BOOT0电平错误、驱动未装好、启动模式设置不对检查BOOT0接地、重装驱动、确认复位电路正常这里面“程序卡死在delay”这个坑很隐蔽我当时在定时器中断里写了一段测试用的delay结果主循环直接卡死后来才意识到中断里面不能调阻塞延时因为SysTick的中断优先级如果被配置得比定时器中断低主循环里的延时永远无法执行二者就死锁了。解决方法是中断服务函数里只做数据采样和数据缓存所有耗时的处理都放到主循环。4.2 联调阶段必须注意的三个细节联调时要特别注意电源稳定性。MAX30102、MPU6050、OLED、蜂鸣器同时工作的时候电流峰值可能到几百毫安如果用USB口直接供电线损和USB口的压降会导致传感器供电电压不稳反映出来的现象就是心率数据漂移、MPU6050偶尔读出全0。我给整个系统加了两个100微法钽电容和几个0.1微法瓷片电容做电源去耦问题就消失了。这种电源问题往往最难排查因为传感器报错的方式很随机。I2C总线上挂了三个设备之后总线上电容会增加如果I2C速率设得太高信号边沿会变缓导致设备偶发通信失败。这种情况下把CubeMX里I2C的时钟速率从400kHz降到100kHz通信稳定性会明显提升。反正心率采样速率100Hz也用不到400kHz的带宽不需要追求高速度。最后一个细节是传感器安装位置对算法影响很大。心率模块放指尖、手腕、耳垂因为血流灌注量不同信号幅度会差好几倍算法里的滤波参数和波峰阈值可能都要跟着调。MPU6050收到腰间和胸口的结果也不同固定的方式不牢靠的话走路时产生的噪声就会触发误报警。所以我建议在联调之前先固定传感器的安装位置再统一采集数据调参不要边调参边换佩戴方式那样永远对不上。这个项目做完之后如果想继续扩展很自然的两个方向是加ESP8266模块把温心率和摔倒报警通过WiFi上报到手机或云端这样家人不在身边也能收到告警把这套代码从标准库或HAL库移植到STM32L4低功耗系列把系统做成手环式的可穿戴产品。硬件上预留好USART接口和一对电源引脚这两个扩展随时都可以加进去。本文还有配套的精品资源点击获取
返回列表