1. 项目概述:基于Micro:bit的心率监测系统开发
在嵌入式开发和物联网应用领域,Micro:bit因其易用性和丰富的功能接口,成为教育领域和快速原型开发的热门选择。这次我们要实现的是一个完整的可穿戴心率监测系统,从硬件连接到软件实现的全流程方案。
这个项目的核心价值在于:
- 使用成本极低的硬件(Micro:bit开发板仅需百元左右)
- 完全开源的软件方案(基于MicroPython和Python)
- 可立即复现的完整代码和接线方案
- 提供了从数据采集到可视化的完整链路
我曾在多个创客工作坊中使用这个方案教学,即使是完全没有嵌入式开发经验的学员,也能在2小时内完成基础功能的搭建。下面我会详细拆解每个环节的关键技术点。
2. 硬件选型与连接方案
2.1 核心硬件组件解析
Micro:bit v2开发板:
- 搭载Nordic nRF52833芯片(ARM Cortex-M4F内核)
- 内置加速度计、磁力计、温度传感器
- 支持蓝牙5.1低功耗通信
- 提供25个可编程GPIO接口
- 板载5x5 LED矩阵和两个可编程按钮
MAX30102心率传感器:
- 集成脉搏血氧(SpO2)和心率监测(HRM)功能
- 采用光电容积描记法(PPG)原理
- I²C数字接口,工作电压1.8V-3.3V
- 内置环境光消除电路
- 采样率可配置(最高3.2kHz)
注意:市场上有些廉价的MAX30102模块质量不稳定,建议选择带有稳压电路和电平转换的版本,确保与Micro:bit的3.3V逻辑兼容。
2.2 硬件连接示意图
code复制Micro:bit引脚 MAX30102引脚
-----------------------------
3V3 VIN
GND GND
Pin19 (SCL) SCL
Pin20 (SDA) SDA
实际连接时需要注意:
- 使用母对母杜邦线连接时,确保插接牢固
- 避免电源线(3V3和GND)与信号线交叉
- 如果使用面包板,建议给MAX30102模块的电源引脚并联一个100μF的电容,减少电源噪声
3. MicroPython固件开发详解
3.1 传感器初始化配置
MAX30102需要正确初始化才能获取可靠的心率数据。以下是关键寄存器配置说明:
python复制def init_sensor():
# 重置设备
i2c.writeto_mem(MAX30102_ADDR, 0x09, bytes([0x40]))
sleep(100)
# 设置FIFO配置
i2c.writeto_mem(MAX30102_ADDR, 0x08, bytes([0x7F])) # 样本平均=8, FIFO满=17
# 设置模式控制
i2c.writeto_mem(MAX30102_ADDR, 0x09, bytes([0x03])) # HR-only模式
# 设置SpO2配置
i2c.writeto_mem(MAX30102_ADDR, 0x0A, bytes([0x27])) # 100Hz采样率, 16位分辨率
# 设置LED脉冲幅度
i2c.writeto_mem(MAX30102_ADDR, 0x0C, bytes([0x24])) # RED LED=7.6mA
i2c.writeto_mem(MAX30102_ADDR, 0x0D, bytes([0x24])) # IR LED=7.6mA
# 设置多LED模式控制
i2c.writeto_mem(MAX30102_ADDR, 0x11, bytes([0x03])) # 启用SLOT1(RED)和SLOT2(IR)
3.2 心率算法实现
原始PPG信号需要经过处理才能得到准确的心率值。这里实现一个简化版的算法:
python复制def calculate_bpm(red_data, ir_data):
# 简单的峰值检测算法
threshold = np.mean(ir_data[-10:]) * 1.2
peaks = []
for i in range(1, len(ir_data)-1):
if ir_data[i] > threshold and ir_data[i] > ir_data[i-1] and ir_data[i] > ir_data[i+1]:
peaks.append(i)
if len(peaks) < 2:
return 0
# 计算平均心跳间隔
intervals = np.diff(peaks)
avg_interval = np.mean(intervals)
# 转换为BPM (每分钟心跳次数)
bpm = 60 / (avg_interval / SAMPLE_RATE)
return int(bpm)
3.3 数据采集与传输
主循环中实现数据采集和串口输出:
python复制while True:
# 读取FIFO数据
fifo_data = i2c.readfrom_mem(MAX30102_ADDR, 0x07, 6)
red = (fifo_data[0] << 16) | (fifo_data[1] << 8) | fifo_data[2]
ir = (fifo_data[3] << 16) | (fifo_data[4] << 8) | fifo_data[5]
# 存储最近100个样本
red_buffer.append(red)
ir_buffer.append(ir)
# 每100个样本计算一次心率
if len(red_buffer) >= 100:
bpm = calculate_bpm(red_buffer, ir_buffer)
print(f"HR:{bpm},RED:{red},IR:{ir}")
red_buffer.clear()
ir_buffer.clear()
sleep(10) # 10ms间隔
4. PC端数据处理与可视化
4.1 串口通信设置
python复制import serial
from serial.tools import list_ports
def find_microbit_port():
ports = list_ports.comports()
for port in ports:
if "MicroPython" in port.description:
return port.device
return None
ser = serial.Serial(
port=find_microbit_port(),
baudrate=115200,
timeout=1,
parity=serial.PARITY_NONE,
stopbits=serial.STOPBITS_ONE,
bytesize=serial.EIGHTBITS
)
4.2 实时数据可视化
使用PyQt5创建更专业的监控界面:
python复制from PyQt5 import QtWidgets, QtCore
import pyqtgraph as pg
class HeartRateMonitor(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
# 创建绘图窗口
self.graph = pg.PlotWidget()
self.setCentralWidget(self.graph)
# 初始化曲线
self.bpm_curve = self.graph.plot(pen='r')
self.data = collections.deque(maxlen=300)
# 定时器更新数据
self.timer = QtCore.QTimer()
self.timer.timeout.connect(self.update_plot)
self.timer.start(100) # 每100ms更新一次
def update_plot(self):
line = ser.readline().decode().strip()
if line.startswith("HR:"):
parts = line.split(',')
bpm = int(parts[0].split(':')[1])
self.data.append(bpm)
self.bpm_curve.setData(list(self.data))
5. 系统优化与穿戴设计
5.1 电源管理优化
python复制# 在Micro:bit上实现低功耗模式
def enter_low_power():
# 关闭不必要的外设
display.off()
i2c.writeto_mem(MAX30102_ADDR, 0x09, bytes([0x00])) # 关闭传感器
# 设置加速度计唤醒
accelerometer.set_range(4)
accelerometer.set_wake_up(200, 2) # 200mg阈值, 持续2秒
# 进入系统待机
microbit.sleep()
# 当检测到运动时唤醒
def on_gesture():
if accelerometer.current_gesture() == "shake":
init_sensor()
display.on()
5.2 3D打印外壳设计
可穿戴设备需要考虑人体工程学设计:
- 使用Tinkercad或Fusion 360设计弧形外壳
- 选择TPU柔性材料进行3D打印
- 内部预留传感器定位槽和通风孔
- 使用医用级硅胶表带固定
6. 常见问题与解决方案
6.1 传感器读数不稳定
可能原因及解决方法:
- 环境光干扰:确保传感器与皮肤紧密接触,必要时增加遮光罩
- 电源噪声:在电源引脚并联100μF电容
- 运动伪影:增加软件滤波算法,如移动平均或卡尔曼滤波
6.2 蓝牙连接问题
调试步骤:
- 确认Micro:bit蓝牙已激活
- 检查手机/电脑蓝牙兼容性
- 重新配对设备
- 检查MicroPython蓝牙库版本
6.3 数据延迟严重
优化建议:
- 降低采样率到50Hz
- 使用二进制协议替代文本协议
- 增加数据压缩算法
- 优化Python端的数据处理流程
7. 项目扩展方向
7.1 云端数据同步
使用MQTT协议将数据上传至物联网平台:
python复制import paho.mqtt.client as mqtt
client = mqtt.Client()
client.connect("iot.eclipse.org", 1883, 60)
def on_serial_data(data):
client.publish("heartrate/device01", payload=data)
# 在串口回调中调用
ser.callback = on_serial_data
7.2 异常心律检测
实现简单的心律失常检测算法:
python复制def detect_arrythmia(rr_intervals):
mean_rr = np.mean(rr_intervals)
std_rr = np.std(rr_intervals)
if std_rr / mean_rr > 0.1: # 心率变异性过高
return "Possible AFib"
elif any(abs(rr - mean_rr) > 0.3 * mean_rr for rr in rr_intervals):
return "Possible PVC"
else:
return "Normal"
在实际部署这个系统时,我发现传感器佩戴位置对数据质量影响很大。最佳位置是食指指尖或手腕桡动脉处,需要施加适当压力但不能阻碍血液循环。另外,运动状态下的心率监测需要更复杂的算法处理,可以考虑结合加速度计数据进行运动补偿。