1. 项目概述:基于STM32的远程生命体征监测系统
这个项目是我去年为社区养老院开发的一套远程监护系统,核心功能是通过STM32单片机实时采集老人的心率、体温和位置信息,再通过GPRS网络上传到云端服务器。在实际部署中,这套系统成功帮助护理人员及时发现了几次老人突发的心率异常情况,验证了方案的可行性。
系统硬件架构主要包含五个部分:STM32F103ZET6主控板作为处理核心,DS18B20数字温度传感器负责环境温度采集,PulseSensor光电心率传感器监测心率,NEO-7N GPS模块获取位置信息,以及SIM800C GPRS模块实现数据上传。软件层面采用Keil MDK开发环境,使用C语言编写,通过模块化设计实现了各功能的解耦。
特别说明:心率监测部分需要特别注意信号滤波处理,我们实际测试发现老年人手臂轻微颤抖会产生干扰信号,后来增加了软件滤波算法才解决这个问题。
2. 硬件设计与选型考量
2.1 主控制器选型
选择STM32F103ZET6主要基于三点考虑:
- 丰富的片上资源:512KB Flash+64KB RAM,完全满足系统需求
- 多个USART接口:同时连接GPS和SIM800C模块
- 成本优势:相比F4系列价格更低,批量采购单价不到30元
实际使用中,这款MCU的性能完全够用,即使在开启所有外设时CPU占用率也不超过60%。我们保留了USART3作为调试接口,这在后期故障排查时发挥了重要作用。
2.2 传感器模块选型对比
2.2.1 温度传感器
对比了三种方案:
- LM35(模拟输出):需要额外ADC,精度±0.5℃
- DHT11(数字输出):仅整数温度值,响应慢
- DS18B20(最终选择):0.1℃分辨率,单总线节省IO
实际部署中发现DS18B20的防水型号更适合老人佩戴,普通型号在洗手时容易受潮损坏。接线时注意上拉电阻(4.7KΩ)必须靠近传感器放置。
2.2.2 心率传感器
测试了两种方案:
- 手指夹式光电传感器:佩戴不适,老人抗拒使用
- PulseSensor Amped(最终选择):耳夹式设计,自带信号调理电路
心率采集的关键是消除运动伪影,我们通过实验确定了最优的安装位置是耳垂而不是手腕。信号处理方面,采用滑动窗口平均算法,窗口大小设置为8个采样点效果最佳。
2.3 通信模块配置
2.3.1 SIM800C模块
选择SIM800C而非更新的SIM900主要考虑:
- 更成熟的GPRS支持
- 更低的功耗(待机电流<1mA)
- 内置TCP/IP协议栈
实际使用中需要注意:
- 天线必须使用合格产品,我们曾因劣质天线导致信号差
- 电源必须能提供2A峰值电流
- 建议添加TVS二极管保护电路
2.3.2 GPS模块
NEO-7N相比6系列的主要优势:
- 更快的冷启动时间(29秒 vs 35秒)
- 更高的灵敏度(-162dBm vs -161dBm)
- 支持GLONASS双模定位
安装时应注意:
- 天线朝向天空,远离金属物体
- 室外使用时加装防水外壳
- 定期检查天线连接可靠性
3. 软件架构设计
3.1 系统任务划分
采用时间片轮询架构,主要任务及优先级如下:
| 任务名称 | 执行周期 | 优先级 | 备注 |
|---|---|---|---|
| 心率采集 | 20ms | 高 | 外部中断触发 |
| 温度采集 | 5s | 中 | 单总线协议 |
| GPS数据处理 | 1s | 中 | 串口中断接收 |
| 数据上传 | 30s | 低 | GPRS发送 |
| 状态监测 | 60s | 低 | LED指示灯控制 |
3.2 关键算法实现
3.2.1 心率计算算法
c复制#define SAMPLE_WINDOW 8
static uint16_t pulseBuffer[SAMPLE_WINDOW];
static uint8_t bufferIndex = 0;
void EXTI0_IRQHandler(void) {
static uint32_t lastTime = 0;
uint32_t currentTime = SysTick->VAL;
if(lastTime != 0) {
uint32_t interval = lastTime - currentTime;
if(interval > 30000) { // 滤波:排除<30ms的干扰信号
pulseBuffer[bufferIndex++] = interval;
if(bufferIndex >= SAMPLE_WINDOW) {
bufferIndex = 0;
uint32_t sum = 0;
for(uint8_t i=0; i<SAMPLE_WINDOW; i++) {
sum += pulseBuffer[i];
}
uint16_t avgInterval = sum / SAMPLE_WINDOW;
xinLv = 60000 / avgInterval; // 转换为bpm
}
}
}
lastTime = currentTime;
EXTI_ClearITPendingBit(EXTI_Line0);
}
3.2.2 温度补偿算法
由于发现DS18B20测量体表温度比实际体温低1-2℃,我们增加了环境温度补偿:
c复制float getCompensatedTemp(float skinTemp, float envTemp) {
// 经验公式:实际体温 = 体表温度 + (环境温度<25℃时的补偿值)
if(envTemp < 25.0f) {
return skinTemp + (25.0f - envTemp)*0.15f;
}
return skinTemp;
}
3.3 数据协议设计
上传到OneNET平台的数据采用JSON格式,示例:
json复制{
"devid": "DEV_01",
"temp": 36.5,
"hr": 72,
"gps": {
"lat": 39.9042,
"lon": 116.4074,
"alt": 43.5
},
"alert": 0
}
报警标志位定义:
- 0:正常
- 1:心率异常(<50或>120bpm)
- 2:体温异常(<35或>38℃)
- 3:位置异常(离开预设区域)
4. 系统集成与调试
4.1 硬件组装要点
-
PCB布局建议:
- SIM800C模块远离模拟电路
- GPS天线接口靠近板边
- 为每个传感器预留测试点
-
电源设计:
- 主电源:5V/2A MicroUSB输入
- 备用电源:3.7V/2000mAh锂电池
- 使用TPS5430 DCDC转换器提供3.3V
-
接口防护:
- 所有外部接口添加ESD保护二极管
- SIM卡座选用自弹式型号便于更换
4.2 软件调试技巧
4.2.1 SIM800C常见问题排查
-
无法注册网络:
- 检查APN设置(移动:cmnet)
- 确认SIM卡未欠费
- 测试AT+CSQ信号强度(>10才稳定)
-
TCP连接失败:
- 先执行AT+CIPSHUT复位协议栈
- 检查防火墙设置
- 尝试更换TCP端口
4.2.2 GPS定位优化
-
加速冷启动:
- 预先注入星历数据
- 使用AGPS辅助定位
-
提高定位精度:
- 设置NMEA输出频率1Hz
- 启用SBAS增强系统
- 软件滤波去除跳点
4.3 功耗优化实践
通过实测发现系统主要耗电单元:
| 模块 | 工作电流 | 待机电流 |
|---|---|---|
| STM32 | 25mA | 2mA |
| SIM800C | 200mA | 1mA |
| GPS | 45mA | 10mA |
优化措施:
- 采用间歇工作模式:GPS每5分钟工作30秒
- SIM800C在无数据传输时进入睡眠模式
- STM32主频降至36MHz
- 关闭未用外设时钟
优化后平均电流从78mA降至19mA,2000mAh电池续航从25小时延长到100小时。
5. 实际部署经验
5.1 现场安装注意事项
-
设备佩戴方式:
- 腕带式设计要可调节松紧
- 避免金属表带影响GPS信号
- 定期检查皮肤接触情况
-
网络环境适配:
- 不同地区运营商信号差异大
- 养老院建筑结构可能屏蔽信号
- 建议进行现场信号测试
5.2 数据准确性验证
我们对比了专业医疗设备测量结果:
| 指标 | 本系统 | 专业设备 | 误差 |
|---|---|---|---|
| 心率 | 72bpm | 75bpm | ±3bpm |
| 体温 | 36.7℃ | 36.9℃ | ±0.2℃ |
| 定位 | 15m | - | 约15m精度 |
5.3 用户反馈改进
根据护理人员建议增加了以下功能:
- 低电量预警(30%电量时提醒充电)
- 脱落检测(通过加速度传感器判断)
- 一键SOS紧急呼叫按钮
- 夜间模式(减少LED闪烁)
6. 系统扩展方向
6.1 硬件扩展
-
增加环境传感器:
- SHT30温湿度传感器
- BMP280气压传感器
- VEML6075紫外线传感器
-
本地存储扩展:
- 添加W25Q128 Flash芯片
- 支持离线存储7天数据
-
人机交互改进:
- 0.96寸OLED显示屏
- 触摸按键替代物理按键
6.2 软件优化
-
算法升级:
- 基于机器学习的心律失常检测
- 运动状态识别算法
- 跌倒检测模型
-
通信协议增强:
- 支持LoRaWAN双模通信
- 增加数据加密传输
- 实现OTA远程升级
-
云平台集成:
- 对接微信小程序
- 开发管理后台
- 实现电子围栏功能
这个项目从原型到实际部署共迭代了5个版本,最大的体会是嵌入式开发必须重视现场测试。我们在实验室完全正常的功能,到了实际使用环境中会出现各种意想不到的问题。比如最初没考虑到老人佩戴设备时会有更多动作干扰,导致心率误报率高,后来通过改进算法才解决。