フォトレジスタとArduinoで作る高精度心拍数モニター
概要
フォトレジスタ(CdSセル)を光センサーとして指先の血流変化を検出し、オペアンプ3段+コンパレータで波形整形、Arduinoで心拍数(BPM)を計算表示する低コスト心拍モニターです。オシロスコープ(Digilent OpenScope MZ + WaveForms Live)で波形観測しながら閾値調整可能。
動作原理
光電脈波(PPG)の検出
心拍に伴う血管内圧力変動により、指先などの薄い組織を透過する光量が微小に変化します。フォトレジスタはこの光量変化を抵抗値変化として検出します。ただし変化は極めて小さく、ノイズも多いため増幅・フィルタリングが必須です。
信号処理チェーン
- 分圧回路: フォトレジスタ + 20kΩ で電圧変化に変換
- Amp1(フィルタ): 高周波ノイズ除去(ローパス)
- Amp2(反転増幅): 利得最大化(飽和直前まで)
- Amp3(バーチャルグラウンド): 信号を2.5V中心にシフト(0-5Vフルスイング確保)
- コンパレータ(ヒステリシス付き): 非対称閾値(Vh, Vl)で矩形波化。ジッター・二重峰(二尖切痕)対策
- Arduino割り込み: 立下りエッジでパルス幅測定(200-800ms範囲のみカウント)、15秒移動平均でBPM算出
必要な部品
| 部品 | 数量 | 備考 |
|---|---|---|
| Digilent OpenScope MZ(オシロスコープ) | 1 | 波形観測・閾値調整用。なければ他のオシロで代用可 |
| Arduino UNO | 1 | 心拍計算・表示用 |
| 汎用クアッドオペアンプ(TL084等) | 1 | Amp1-3用。単電源5V動作可能なもの |
| 高速コンパレータ(TLV3501等) | 1 | ヒステリシス用フィードバック回路実装 |
| マルチターンポテンショメータ 10kΩ (25ターン) | 2 | コンパレータ閾値設定用(R3, R4)。精密調整必須 |
| シングルターンポテンショメータ 100kΩ | 1 | Amp2利得調整用(R7)。マルチターン推奨 |
| シングルターンポテンショメータ 10kΩ | 1 | バーチャルグラウンド調整用(R8/R9代替) |
| コンデンサ 100µF, 100nF | 各1 | 電源バイパス・フィルタ用 |
| 抵抗 10kΩ, 4.75kΩ, 82kΩ | 各種 | 分圧・フィードバック網用 |
| フォトレジスタ(CdSセル) | 1 | クリア熱収縮チューブでリード線絶縁推奨 |
調整手順
1. 増幅段(Amp2)利得調整
R7(100kΩポテンショメータ)を約375Ω側から開始。OpenScope Ch2をAmp2出力に接続、Time=1s、Trigger=OFF、Offset=2.5V、Samples=1000設定でRUN。指をセンサーに当て、パルス波形がクリップしない最大振幅になるようR7調整。
2. コンパレータ閾値設定
代表的な波形を一時停止、カーソル電圧測定でピーク付近を Vh、二尖切痕下を Vl として読み取り。添付Excel(comparator calcs.xlsx)に R5実測値、Vh, Vl を入力 → R3, R4 計算値をマルチターンポテンショメータで設定。
3. バーチャルグラウンド調整
R8/R9(または単一ポテンショメータ)でAmp3出力を2.50Vに設定。
Arduinoスケッチ(心拍計算部)
#define INT0 3
volatile int counter = 0;
volatile long pulseStart = 0;
volatile bool low = false;
float freqAvg = 0, total = 15;
void setup() {
pinMode(3, INPUT);
attachInterrupt(digitalPinToInterrupt(INT0), intrruption, CHANGE);
Serial.begin(9600);
}
void loop() {
long start = millis();
counter = 0;
while (millis() - start < 5000) { /* 5秒間カウント */ }
if (counter > 3) {
total += counter;
total -= freqAvg;
freqAvg = total / 3; // 15秒移動平均(5秒×3)
}
Serial.print("Heart rate = ");
Serial.println(freqAvg * 12); // 5秒カウント → 1分換算 (×12)
delay(100);
}
void intrruption() {
if (digitalRead(3) == LOW) { // 立下りエッジ
pulseStart = millis();
low = true;
} else if (low) { // 立上りエッジ
long width = millis() - pulseStart;
if (width > 200 && width < 800) counter++; // 生理的パルス幅のみ
low = false;
}
}
既知の課題と改善案
- 周囲光の影響: 環境光変化でベースライン・振幅が変動。解決策:高輝度赤色LEDを光源としてセンサーと対向配置(指挟み込み型)、遮光ケース化。
- 動作アーティファクト: 指の圧力変化でノイズ発生。解決策:機械的固定具、加速度センサー併用でモーション除去。
- 閾値固定の限界: 個人差・条件変化で再調整必要。解決策:デジタルポテンショメータ(MCP41xxx等)でArduinoから閾値自動追従(オートレンジ)。アナログ入力でピーク/ボトム検出 → 閾値計算 → デジタルポテンショメータ設定 → コンパレータ出力で割り込みカウント。
- 精度向上: 高分解能タイマー(Timer1/ICP)でパルス幅測定、ピーク検出アルゴリズム(動的閾値・微分/積分処理)導入。
添付ファイル
comparator calcs.xlsx- コンパレータ非対称閾値計算シート(R3, R4 自動算出)Arduino Heart Rate Counter.ino- 上記スケッチ完全版hr_monitor_tnffXlVQQV.fzz- Fritzing回路図
参考文献
- Texas Instruments: Signal Conditioning with Hysteresis (Application Report)
- CapitanoRed YouTube: フォトレジスタ心拍モニター原型
製造プロセス
- 体外式除細動器:歴史、設計、製造
- 人工心臓:技術、歴史、将来展望
- 人工心臓弁:種類、歴史、未来の革新
- 最新心電計(ECG)完全ガイド:技術、製造、未来の革新
- ペースメーカー:心拍リズム障害を救う現代のライフセービングテクノロジー
- Raspberry PiとAS3935で落雷検知: 実践ガイド
- Windows 10 IoT Core on Raspberry Piで心拍パルスを読み取る - ステップバイステップガイド
- リモート心拍数監視システム:AWS IoTアラート付き
- 心臓を守る:2月「心臓月」に実践したい生活習慣の基本
- スマート衣類に統合された心拍センサーで信頼性の高いウェアラブル監視を実現
- 単一原子核の磁気シグネチャーの測定