1. 项目概述
这个周末我完成了一个有意思的小项目——用单片机搭建了一个便携式心率测试仪。作为一个电子爱好者,我一直对人体生理信号测量很感兴趣。这次的设计方案成本不到100元,但测量精度完全能满足日常健康监测需求。
传统的心率检测需要专业医疗设备,而我们这个DIY方案通过光电传感器捕捉指尖血流变化,再经过信号处理就能实时显示心率数值。整套系统包含传感器模块、信号调理电路、单片机主控和显示单元四个部分,代码量约200行,非常适合电子专业学生或创客爱好者练手。
2. 硬件设计详解
2.1 核心器件选型
主控芯片选择了STM32F103C8T6,这款ARM Cortex-M3内核的单片机性价比极高:
- 72MHz主频足够处理心率信号
- 12位ADC满足信号采集精度要求
- 丰富的GPIO接口方便外设扩展
- 开发工具链成熟(Keil MDK环境)
传感器采用MAX30102集成模块,这个指甲盖大小的芯片包含了:
- 光电二极管和LED光源
- 环境光抑制电路
- 18位ADC转换器
- I2C数字接口
2.2 电路设计要点
信号调理电路是设计的核心难点,我的方案包含三级处理:
- 前置放大:采用LM358运放搭建同相放大器,增益设置为100倍
- 带通滤波:设计0.5Hz-5Hz的主动滤波器,消除直流偏移和高频干扰
- 电平抬升:通过偏置电路将信号抬升至0-3.3V范围,匹配STM32的ADC输入要求
特别注意:传感器LED驱动电流需要精确控制在10mA左右,过大会导致发热,过小则信号太弱。我在PCB上预留了可调电阻方便校准。
3. 软件实现方案
3.1 信号采集处理
开发环境使用Keil uVision5,主要代码逻辑如下:
c复制// 初始化I2C接口
MAX30102_Init();
while(1) {
// 读取原始数据
raw_data = MAX30102_ReadFIFO();
// 数字滤波处理
filtered = Butterworth_LPF(raw_data);
// 峰值检测算法
if(IsPeak(filtered)) {
heart_rate = 60000/(current_time - last_peak);
last_peak = current_time;
}
// OLED显示刷新
OLED_ShowNum(heart_rate);
}
3.2 关键算法实现
心率计算采用时域分析法,核心是通过检测脉搏波的峰值间隔来计算心率。我优化后的算法包含三个关键步骤:
- 滑动平均滤波:窗口宽度设为10个采样点,有效抑制突发噪声
- 动态阈值检测:根据信号幅度自动调整峰值判定阈值
- 异常值剔除:当相邻心跳间隔差异超过20%时视为误检
实测表明,这套算法在静坐状态下误差可以控制在±2bpm以内,即使轻微运动时也能保持±5bpm的精度。
4. 制作与调试心得
4.1 组装注意事项
整机采用模块化设计,建议按以下顺序组装:
- 先焊接电源电路,测试各点电压正常
- 连接传感器模块,用示波器观察原始信号
- 调试信号调理电路,确保波形无明显失真
- 最后接入单片机,逐步验证各项功能
4.2 常见问题排查
在实际调试中遇到过几个典型问题:
- 信号基线漂移:检查运放供电电压是否稳定,适当增大滤波电容
- 峰值漏检:调整动态阈值的灵敏度参数
- 显示刷新卡顿:优化OLED驱动代码,改用DMA传输
5. 功能扩展方向
完成基础功能后,还可以考虑以下升级:
- 添加蓝牙模块将数据上传手机APP
- 实现心率变异性(HRV)分析功能
- 增加运动状态识别算法
- 改用低功耗设计延长续航
这个项目最让我惊喜的是,用如此廉价的硬件也能实现接近商用产品的测量精度。下次准备尝试加入血氧检测功能,把传感器换成MAX30105就能实现。