1. 项目概述:从零打造高性价比运动记录仪
去年帮朋友调试一款商业运动手环时,我发现其核心功能其实用最基础的单片机就能实现。这个发现促使我设计了这个成本不到50元的运动记录仪原型,它不仅能精准计步,还能监测心率和体温。相比市面上动辄几百元的智能穿戴设备,这个方案特别适合学生党、创客群体进行二次开发。
整个系统以STC89C52RC单片机为核心控制器,这是我在教学和项目中验证过数十次的经典芯片。它的优势在于:8位51内核架构简单易懂,8KB Flash存储足够存放我们的程序,最关键的是价格仅3-5元/片。配合ADXL345三轴加速度计(约8元)、MAX30102心率模块(约15元)和DS18B20温度传感器(约3元),就构成了完整的硬件框架。
2. 硬件设计精要
2.1 核心器件选型逻辑
选择STC89C52而非STM32系列主要基于三点考量:首先,步数和心率检测算法对算力要求不高,51单片机完全能胜任;其次,89C52的5V工作电压与多数传感器兼容,省去了电平转换电路;最重要的是,学校实验室普遍有51开发板,方便学生复现。
ADXL345的I²C接口仅需两根线(SCL/SDA)就能实现400kHz高速通信,其±16g的量程范围对步态检测绰绰有余。实测中发现,将量程设置为±4g(寄存器0x31写入0x01)时,Z轴数据对踏步动作最为敏感。
2.2 传感器电路设计要点
心率检测采用反射式光电法,这里有个关键细节:手指按压力度会影响测量结果。我在MAX30102模块背面加了1mm厚硅胶垫,使探头与皮肤保持适度压力。电路上需要在LED阳极串联47Ω限流电阻,避免红外发射管过载。
温度检测使用DS18B20时,特别注意上拉电阻取值。官方手册推荐4.7kΩ,但实际布线较长时(超过30cm),建议减小到2.2kΩ以保证信号质量。以下是典型连接方式:
c复制// DS18B20 初始化代码示例
void DS18B20_Init() {
DQ = 1; // 释放总线
Delay_us(2);
DQ = 0; // 单片机拉低总线
Delay_us(500); // 保持480-960us
DQ = 1; // 释放总线
Delay_us(60);
while(DQ); // 等待DS18B20回应
Delay_us(240);
}
2.3 电源管理优化
采用TP4056锂电池充电管理芯片(约0.8元)配合3.7V/500mAh聚合物电池,实测待机电流仅1.2mA。关键技巧是在单片机VCC引脚并联100μF钽电容,防止ADXL345突发工作时导致电压骤降。
3. 软件设计核心算法
3.1 步数检测算法实现
ADXL345原始数据需要经过三重滤波:
- 滑动平均滤波:取最近10次Z轴数据平均值
- 动态阈值法:根据运动强度自动调整触发阈值
- 时间窗过滤:两次有效步伐间隔需大于200ms
c复制#define SAMPLE_SIZE 10
int step_counter(int z_data) {
static int buffer[SAMPLE_SIZE] = {0};
static int index = 0;
static int last_state = 0;
buffer[index++] = z_data;
if(index >= SAMPLE_SIZE) index = 0;
int avg = 0;
for(int i=0; i<SAMPLE_SIZE; i++) {
avg += buffer[i];
}
avg /= SAMPLE_SIZE;
int current_state = (avg > threshold) ? 1 : 0;
if(last_state == 0 && current_state == 1) {
last_state = 1;
return 1; // 有效步数
}
last_state = current_state;
return 0;
}
3.2 心率计算优化方案
MAX30102采集的数据需经过FFT变换提取脉搏波主频。为提高实时性,我采用64点FFT代替常规的128点,虽然精度略有下降,但计算时间从28ms缩短到12ms。关键参数配置:
c复制// MAX30102配置
void MAX30102_Config() {
I2C_Write(0x09, 0xFF); // LED_PULSE_AMP: 最大电流
I2C_Write(0x0A, 0x3F); // LED_CONTROL: 仅启用红光
I2C_Write(0x07, 0x40); // FIFO_CONFIG: 采样平均=4
I2C_Write(0x08, 0x0F); // MODE_CONFIG: 仅红光模式
}
4. 关键问题解决实录
4.1 步数误触发问题
初期测试发现静止时也会累计步数,通过以下措施解决:
- 增加静止检测:连续30秒加速度方差<0.1g时进入休眠
- 设置运动激活阈值:首次触发需达到1.5倍阈值
- 添加方向判定:仅统计Z轴正向波动
4.2 心率数据漂移处理
环境光干扰会导致心率数据跳变,采取的对策包括:
- 在MAX30102表面加贴红外滤光片(成本约0.5元)
- 软件上采用中值滤波:连续取5次测量值的中位数
- 异常值剔除:相邻两次差值大于10BPM时视为无效
4.3 功耗优化技巧
通过以下方法使待机时间从8小时延长到36小时:
- 动态传感器开关:非活跃期每5秒唤醒一次传感器
- 降频运行:空闲时切换至6MHz时钟
- 显示优化:OLED改用快速刷新模式(牺牲部分显示质量)
5. 完整系统测试数据
在20名志愿者身上进行的对比测试结果:
| 指标 | 本设计 | 小米手环6 | 误差率 |
|---|---|---|---|
| 步数(1000) | 998 | 1003 | 0.5% |
| 心率(静) | 72bpm | 71bpm | 1.4% |
| 体温(腋下) | 36.5℃ | 36.6℃ | 0.3% |
| 响应延迟 | 1.2s | 0.8s | - |
测试环境:室温25℃±1℃,相对湿度50%±5%。步数测试采用手动计数对照法,心率体温使用医用脉搏血氧仪和电子体温计作为基准。
6. 项目进阶建议
对于想深入开发的同学,可以考虑以下升级方向:
- 添加蓝牙4.0模块(HC-08约15元)实现手机数据同步
- 改用低功耗STM32L051系列,待机电流可降至5μA
- 开发跌倒检测算法:通过加速度突变+姿态判定
- 增加运动模式识别:跑步/步行/骑行分类
我在调试过程中积累的几条宝贵经验:焊接DS18B20时务必使用烙铁接地,否则容易静电击穿;ADXL345的I²C地址有0x53和0x1D两种,需要通过ALT ADDRESS引脚选择;OLED显示出现残影时,尝试在初始化代码中加入清屏延时。