MAX30102センサーを用いた脈拍と血中酸素濃度測定のC++実装

MAX30102センサーの概要と特徴

MAX30102は光センサーを内蔵した生体信号検出モジュールで、心拍数と血中酸素飽和度(SpO2)の非接触測定を実現します。赤色LEDと赤外LED、光検出器を統合し、I²Cインターフェースを通じてマイコンと通信します。このセンサーはウェアラブル機器向けに設計され、低消費電力かつ高精度な生体データ取得が可能です。

ハードウェア構成

  • 統合LEDドライバと光検出回路
  • 自動環境光補正機能
  • 12ビットADCによる高精度測定

生体信号測定の原理

脈拍検出メカニズム

心拍による血液の脈動を光吸収量の変化として検出するPPG(光電式容積脈波)技術を採用しています。心臓の収縮時に動脈に流れる血流量変化を、LED光源の反射光強度変化として捉えます。

血中酸素濃度測定原理

酸素化ヘモグロビンと還元型ヘモグロビンの光吸収特性の違いを利用します。660nmの赤色光と940nmの赤外光の吸光度比から、以下の式でSpO2値を算出:

R = (AC_red/DC_red) / (AC_ir/DC_ir)
SpO2 = -23.3 * R + 100

C++によるセンサードライバー実装

初期化処理

#include <Wire.h>
#include "MAX30102_Driver.h"

MAX30102_Sensor pulseSensor;

void setup() {
  Serial.begin(115200);
  if(!pulseSensor.init()) {
    Serial.println("センサー初期化失敗");
    while(1); //エラーループ
  }
  pulseSensor.configure(
    SAMPLE_RATE_100HZ, 
    LED_CURRENT_15MA,
    PULSE_WIDTH_400US
  );
}

データ取得処理

void loop() {
  if(pulseSensor.hasData()) {
    uint32_t rawIR = pulseSensor.readIR();
    uint32_t rawRed = pulseSensor.readRed();
    
    // フィルタ処理後の値を取得
    float filteredValue = lowPassFilter(rawRed);
    
    // 生体データ計算
    calculateHeartRate(filteredValue);
    calculateSpO2(rawRed, rawIR);
  }
}

I²C通信の最適化

高速データ転送設定

void MAX30102_Sensor::setClockSpeed(uint32_t speed) {
  #ifdef __AVR__
    TWBR = (F_CPU / speed - 16) / 2;
  #elif defined(ESP32)
    i2c_set_frequency(I2C_NUM_0, speed);
  #endif
}

割り込み処理

void IRAM_ATTR dataReadyISR() {
  // バッファリングされたデータを読み込み
  sensorBuffer[bufferIndex++] = 
    Wire.read() << 16 | Wire.read() << 8 | Wire.read();
}

開発プラットフォーム構成

Arduino接続例

センサーArduino
VCC3.3V
GNDGND
SDAA4
SCLA5

Raspberry Pi接続

# Pythonでの初期化例
import smbus2
bus = smbus2.SMBus(1)
bus.write_byte_data(0x57, 0x09, 0x40)

精度向上のための処理

  • 移動平均フィルタによるノイズ除去
  • 温度補償アルゴリズム
  • 接触不良検出機能
bool checkSignalQuality(int16_t irValue, int16_t redValue) {
  return (irValue > 5000 && redValue > 2000);
}

タグ: MAX30102 C++ Arduino Raspberry Pi I²C通信

6月1日 09:09 投稿