1. 项目概述与设计思路
这个基于STM32F103C8T6的智能手环项目,是我在嵌入式系统课程设计中的一次实践尝试。市面上大多数学生做的智能手环都停留在基础功能上,而我想挑战一个功能更全面的方案。整个系统整合了运动监测、健康指标检测、安全防护和生活提醒四大核心功能模块,用一块小小的开发板实现了商业手环80%的功能。
选择STM32F103C8T6作为主控是经过深思熟虑的。这款Cortex-M3内核的MCU具有72MHz主频、64KB Flash和20KB RAM,性能足够应对多传感器数据融合处理。更重要的是它的丰富外设接口:3个USART、2个SPI、2个I2C,正好可以连接我们需要的各种传感器模块。实际开发中我发现,当所有传感器同时工作时,芯片的DMA控制器能有效减轻CPU负担,这是项目能稳定运行的关键。
硬件架构上采用了模块化设计思路:
- 感知层:MPU6050(运动)、MAX30102(心率血氧)、DS18B20(温度)构成生物信号采集前端
- 交互层:OLED显示屏+物理按键提供人机接口
- 通信层:SIM800C GSM模块实现短信报警,GPS模块提供位置服务
- 功能扩展:DFPlayer Mini MP3模块增加音乐播放能力
这种架构的最大优势是各模块可以独立调试。我在开发时就先确保每个传感器能单独工作,再逐步集成到主系统中。比如先调通MPU6050的原始数据读取,再开发姿态解算算法;MAX30102先确保能读到稳定的PPG信号,再实现心率算法。这种"分而治之"的方法让复杂系统的开发变得可控。
2. 硬件设计与选型解析
2.1 核心元器件选型对比
主控芯片选型时,我对比了三种方案:
-
STM32F103C8T6(最终选择)
- 优势:性价比高(约15元),外设丰富,社区资源多
- 不足:RAM容量较小,需注意内存优化
-
ESP32
- 优势:内置WiFi/蓝牙,双核处理器
- 不足:功耗较高,实时性不如STM32
-
nRF52832
- 优势:低功耗蓝牙支持
- 不足:处理能力有限,价格较高
运动检测模块的选型更有意思。最初我用的是便宜的LIS3DH加速度计,但发现它无法检测复杂姿态。换成MPU6050(带DMP的六轴IMU)后,不仅能用硬件解算姿态角,还内置了运动中断检测功能。这让我省去了自己写卡尔曼滤波算法的麻烦,直接读取俯仰/横滚角就能判断跌倒状态。
实际使用中发现MPU6050的I2C接口对走线很敏感。建议缩短传感器与MCU的距离,并在SCL/SDA线上加1kΩ上拉电阻。如果出现数据异常,可以尝试降低I2C时钟频率到100kHz。
2.2 关键电路设计细节
电源管理部分采用了TP4056充电芯片+3.7V锂电的方案。这里有个坑:STM32的工作电压是3.3V,而部分模块(如GPS)需要5V供电。我的解决方案是用ME6210稳压到3.3V,同时增加一个MT3608升压电路提供5V输出。实测整机工作电流约80mA,1000mAh电池可支持12小时连续使用。
传感器接口布局遵循以下原则:
- 高速信号(如SPI接口的OLED)靠近MCU放置
- 模拟信号(MAX30102的PPG输出)远离数字线路
- I2C总线上的每个设备地址要唯一配置
特别要提的是MAX30102的电路设计。这个心率血氧模块对供电噪声极其敏感,我在其VCC引脚增加了10μF钽电容+0.1μF陶瓷电容组合,并用独立的LDO供电。PCB布局时将它放在板子边缘,避免数字信号干扰。这些措施使得最终获取的PPG波形非常干净,大大提高了心率检测准确率。
3. 软件架构与核心算法
3.1 多任务调度实现
系统软件采用前后台架构,通过状态机机制管理多个功能模块。主循环代码如下:
c复制while(1) {
static uint32_t tick = 0;
if(HAL_GetTick() - tick > 100) { // 100ms周期
tick = HAL_GetTick();
Key_Scan(); // 按键扫描
Menu_Proc(); // 菜单处理
switch(sys_state) {
case NORMAL_MODE:
Sensor_Update();
Display_Refresh();
break;
case ALARM_MODE:
Alarm_Handler();
break;
case MUSIC_MODE:
MP3_Control();
break;
}
}
if(fall_detected && !alarm_triggered) {
Fall_Alarm_Process();
}
}
这种设计保证了系统响应实时性,同时避免了RTOS带来的复杂性。通过状态机切换,不同功能模块可以按需激活,节省功耗。
3.2 运动检测算法优化
跌倒检测是项目的核心难点。我通过MPU6050获取三轴加速度和角速度数据,采用以下判断逻辑:
-
加速度幅值计算:
c复制float acc_mag = sqrt(acc_x*acc_x + acc_y*acc_y + acc_z*acc_z); -
姿态角判断:
- 俯仰角>60度(向前跌倒)
- 横滚角>45度(侧向跌倒)
-
持续时间阈值:保持异常姿态超过1秒
实际测试中发现,快速坐下也可能触发误报警。于是增加了静止状态检测:当角速度小于50dps且加速度变化率小于0.5g/s时,认为是正常动作。这一改进使跌倒检测准确率从75%提升到92%。
3.3 心率检测信号处理
MAX30102输出的PPG信号需要经过多级处理:
-
直流滤波:移除信号中的直流分量
c复制float dc_removal(float input, float *w, float alpha) { *w = input + alpha * (*w); return *w; } -
带通滤波:0.5Hz-5Hz范围(对应30-300BPM)
-
峰值检测:寻找波形中的脉搏波峰
-
节律分析:计算RR间期,排除异常节律
我对比了两种算法:时域峰值检测和频域FFT分析。最终选择时域法,因为它的实时性更好,在STM32上仅需5%的CPU资源。而FFT虽然抗干扰更强,但计算量太大,会导致系统响应延迟。
4. 功能实现与系统集成
4.1 多传感器数据融合
系统需要同时处理6类传感器数据,我设计了统一的数据结构:
c复制typedef struct {
// 运动数据
float acc[3];
float gyro[3];
uint16_t steps;
// 健康数据
uint8_t heart_rate;
uint8_t blood_oxygen;
float temperature;
// 位置时间
gps_data_t gps;
rtc_time_t time;
} system_data_t;
数据更新采用事件驱动机制。每个传感器中断触发时,只更新对应字段,并通过标志位通知主程序。例如MPU6050使用DMA循环模式采集数据,每20ms产生一次中断;MAX30102则在检测到有效脉搏波时触发中断。
4.2 低功耗优化策略
虽然这不是以低功耗为卖点的设计,但我还是做了一些优化:
-
动态调整传感器采样率:
- 静止状态:MPU6050 10Hz,MAX30102 50Hz
- 运动状态:MPU6050 50Hz,MAX30102 100Hz
-
显示控制:
- 无操作30秒后降低OLED亮度
- 2分钟后关闭显示(按任意键唤醒)
-
外设电源管理:
c复制void GPS_Power(bool on) { HAL_GPIO_WritePin(GPS_PWR_GPIO, GPS_PWR_PIN, on?GPIO_PIN_SET:GPIO_PIN_RESET); if(on) osDelay(500); // 等待模块启动 }
这些措施使平均工作电流从120mA降到了80mA,续航时间延长了33%。
4.3 用户交互设计
OLED界面采用分层菜单结构:
- 主界面:显示时间、步数、心率
- 二级菜单:
- 健康数据(温度、血氧)
- 位置信息
- 系统设置
通过长按/短按实现不同功能。例如短按切换显示页面,长按进入设置模式。我在按键消抖处理上花了些功夫,最终采用硬件消抖(100nF电容)加软件确认(20ms延时检测)的组合方案,完全消除了误触发。
5. 问题排查与优化记录
5.1 典型问题及解决方案
-
MPU6050数据漂移
- 现象:静止时姿态角缓慢变化
- 排查:检查电源纹波(应<50mV)
- 解决:增加传感器校准流程(上电静止2秒)
-
MAX30102信号不稳定
- 现象:心率数据跳变剧烈
- 排查:手指贴合度检测(IR信号强度>10000)
- 解决:增加佩戴检测提示,优化算法参数
-
GPS模块无法定位
- 现象:长时间显示"Searching..."
- 排查:天线阻抗匹配(应使用50Ω天线)
- 解决:调整模块供电电压至3.8V-4.2V
5.2 性能优化经验
-
内存优化:
- 启用STM32的硬件浮点单元
- 将大数组改为
__attribute__((section(".ccmram"))) - 使用内存池管理动态内存
-
实时性保障:
- 关键中断设为最高优先级
- 耗时操作(如FFT)放在主循环
- DMA传输替代CPU搬运
-
算法加速:
- 查表法替代实时计算
- 定点数运算替代浮点
- 使用CMSIS-DSP库
6. 项目扩展与改进方向
目前系统已经实现了基础功能,但还有提升空间:
-
无线传输升级
- 加入蓝牙4.0(BLE)连接手机
- 改用NB-IoT实现远程监控
- 添加数据同步功能
-
算法增强
- 引入机器学习识别运动模式
- 实现更精准的血压估算
- 开发睡眠质量分析
-
功耗优化
- 改用STM32L4系列低功耗MCU
- 增加运动唤醒功能
- 优化电源管理策略
这个项目让我深刻体会到嵌入式开发的乐趣与挑战。从最初的原理图设计,到最后的算法调优,每个环节都需要严谨的工程思维。特别是多传感器数据融合部分,教会我如何平衡实时性与准确性。希望我的这些经验能对后来者有所启发。