用光敏电阻和 Arduino 制作精准心率监测仪
组件与物料
| 组件 | 数量 | 备注 |
|---|---|---|
| Digilent OpenScope MZ | 1 | 示波器/波形仪,用于观察波形 |
| Arduino UNO | 1 | 心率计算与显示 |
| 通用四路运放 (如 TL084) | 1 | 滤波、放大、虚拟地 |
| 高速比较器 (如 TLV3501) | 1 | 带迟滞的方波输出 |
| 25圈精密电位器 10kΩ | 2 | 比较器阈值精调 |
| 单圈电位器 100kΩ | 1 | 放大器增益调节 |
| 单圈电位器 10kΩ | 1 | |
| 电容 100µF | 1 | 电源滤波 |
| 电容 100nF | 1 | 去耦 |
| 电阻 10kΩ | 2 | 或单个 20kΩ |
| 电阻 4.75kΩ | 1 | |
| 电阻 82kΩ | 1 | 可用两个 100k 电位器代替 |
应用与在线服务
- Arduino IDE – 固件编译上传
- Digilent WaveForms Live – OpenScope 波形实时显示与光标测量
原理概述
心脏收缩引起血压微小波动,在皮肤薄处可透过光线检测。光敏电阻随光强变化电阻,配合电压分压电路将脉搏信号转为电压变化。
信号链路
- 光敏电阻 + 20kΩ 分压 – 光强增加 → 分压电压升高
- Amp1 (带通滤波) – 滤除高频噪声
- Amp2 (反相放大) – 最大化信号幅度
- Amp3 (虚拟地) – 将信号中心设为 2.5V,保证 0~5V 摆幅
- 比较器 (非对称迟滞) – 上升沿与下降沿不同阈值,消除重搏齿与噪声导致的多重触发,输出单一方波
光敏电阻封装
建议套透明热缩管,引脚绝缘,防止皮肤电位干扰。
调试步骤
- 在 WaveForms Live 中设置:Time=1s, Trigger=OFF, Ch1/Ch2 Offset=2.5V, Samples=1000
- 手指按压光敏电阻,观察 Amp2 输出波形,调节增益电位器使脉搏波清晰不削顶
- 用光标测量波峰与重搏齿后电压,作为比较器阈值 Vh、Vl
- 用附带 Excel 表格计算 R3、R4 电位器设定值
- 调整虚拟地电位器使输出中心为 2.5V
- 比较器输出应为每搏一个方波脉冲
Arduino 代码
使用外部中断 (INT0/D3) 检测比较器输出脉冲宽度 (200~800ms 有效),15 秒滑动平均计算 BPM,串口输出心率。
#define INT0 3
float frequency, freqAvg, total = 15;
long timeCount, pulseStart;
int counter = 0;
boolean low = false;
void setup() {
attachInterrupt(digitalPinToInterrupt(INT0), intrruption, CHANGE);
Serial.begin(9600);
}
void loop() {
timeCount = millis();
while (millis() - timeCount < 5000) { frequency = counter; }
if (frequency > 3) {
total += frequency; total -= freqAvg; freqAvg = total / 3;
}
showHR(); counter = 0;
}
void intrruption() {
if (digitalRead(3) == 0) { pulseStart = millis(); low = true; }
else if (low) widthCheck();
}
void widthCheck() {
long pulseEnd = millis();
if (pulseEnd - pulseStart > 200 && pulseEnd - pulseStart < 800) { counter++; low = false; }
}
void showHR() {
Serial.print("Heart rate = "); Serial.println(freqAvg * 12);
}
未来改进
- 加入 LED 光源提供稳定照明,类似医用指夹/手机心率传感器
- 软件自动寻峰算法配合数字电位器动态调整比较器阈值
- 使用数字引脚中断提高计数精度
原理图
Fritzing 源文件 (hr_monitor_tnffXlVQQV.fzz) 包含完整原理图与面包板布局。
制造工艺