Upgrade to Pro — share decks privately, control downloads, hide ads and more …

mrbgem 三角測量 開発

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
Avatar for ogom ogom
September 17, 2026

mrbgem 三角測量 開発

mrbgem 三角測量 開発
PicoRuby製 パルスオキシメータ
複数の言語とマイコンから、デバイスの仕様を見つける

Avatar for ogom

ogom

September 17, 2026

More Decks by ogom

Other Decks in Programming

Transcript

  1. パルスオキシメータの仕組み SpO2推定の原理 赤色光と赤外光で、酸素化・脱酸素化ヘモグロビンの吸収特性が異なる 赤色光(Red)のPPG AC成分 比の比 PIred = ACred 拍動で変化する

    R = PIred DCred 動脈血の信号 PIir = (ACred / DCred) 赤外光(IR)のPPG PIir = ACir DCir DC成分 (ACir / DCir) 組織・静脈血などを含む 基準となる信号 校正曲線 SpO2推定値 各波長のPPGを、拍動で変化するAC成分と基準となるDC成分に分ける 6
  2. パルスオキシメータの仕組み 心拍数推定の原理 平滑化・ IRのPPG ベースライン除去 拍動時刻を検出 拍動間隔を平均 PPG波形 平均拍動間隔 (Δt1

    + Δt2 + … + Δtn) n 拍動1 拍動2 Δt1 拍動3 心拍数[bpm] 60 平均拍動間隔[秒] Δt2 心臓が血液を送り出すたびに指先の動脈血量が増減する 5
  3. パルスオキシメータの仕組み 赤色光と赤外光から脈拍数・SpO2を推定 Red light 約660 nm Infrared light 約880 nm

    指先の血液 フォトダイオード → ADC 吸収量が拍動で 反射光を2つの数値へ変換 変化 脈拍数 SpO2 拍動間隔 Δt R = (ACred/DCred) bpm = 60 Δt[秒] (ACir/ DCir) Rを校正曲線へ変換 理論式だけでは光学部品、装着状態、皮膚、体動などの影響を補えないため、製品ごとの校正が必要 4
  4. MAX30102の仕組み MAX30102の仕組み 赤色・赤外 指 LED フォトダイ 18ビット 32サンプル オード ADC

    FIFO FIFO = First In, First Out 測定順 1 2 3 … 32 読み書きポインターは0〜31で周回する I2C SpO2モードの1サンプル = 6バイト R1 R2 R3 IR1 IR2 IR3 赤色光3バイト + 赤外光3バイト → 2つの18 ビット値 参考:MAX30102データシート https://www.analog.com/media/en/technical-documentation/data-sheets/MAX30102.pdf 5
  5. MAX30102の仕組み MAX30102ライブラリの責務 データシート 初期化 FIFO読出し 18ビット復号 公開API レジスターと リセット・FIFO・ 赤色3バイト

    + 0x3FFFFで { red:, ir: } ビット定義 SpO2モード設定 赤外3バイト マスク 層 担当する処理 ライブラリ 接続確認、レジスター設定、FIFO制御、I2C読み書き ライブラリ 6バイトを赤色光と赤外光の18ビット値へ復号 上位アプリ PPGのフィルタリング、心拍数・SpO2推定、校正、体動ノイズ除去 mrbgemはMAX30102を設定してADC生値を返す。心拍数・SpO2推定は上位アプリが担う 8
  6. 開発の課題 PicoRubyで開発するための課題 データシート mrbgem 上位アプリ •レジスターとビット •I2Cの読み書き •PPGのフィルタリング •リセット完了条件 •待機とタイムアウト

    •脈拍数・SpO2の推定 •FIFOの形式とポイン •6バイトを18ビットへ •校正と体動ノイズ除去 ター 復号 単純の課題 アプリの構成のイメージはできたが、いきなり PicoRuby で制作 しても正しい値が取得できたが確信がもてない 6
  7. 開発の課題 三角測量とTDDの三角測量 測量 TDD 目標 C assert_equal 3, add(1, 2)

    def add(_a, _b) 3 end 2つ目の具体例 A B 基線 AB 複数の観測を組み合わせ、 直接は分からない対象を求める assert_equal 7, add(3, 4) def add(a, b) a + b end 複数例を満たす規則へ一般化する 7
  8. 開発の課題 mrbgem開発における三角測量 目標 C PicoRuby mrbgem Raspberry Pi Pico 観測点

    A 観測点 B MicroPython C言語 Raspberry Pi Pico Spresense 基線 AB:MAX30102のデータシートの仕様 共通点は仕様の候補。差が出たらデータシートとI2Cログへ戻る 8
  9. 開発の三角測量 観測点1:MicroPythonとRaspberry Pi Pico 参照実装は MicroPython i2c = I2C(1, sda=Pin(26),

    scl=Pin(27), freq=400_000) sensor = MAX30102(i2c) red, infrared = sensor.read_fifo() print("RED:", red, "IR:", infrared) MicroPython •公開されているライブラリ でセンサーの動作をすばや く確かめられる ターミナルコマンド mpremote •CLIを使いターミナルから、 $ mpremote fs cp lib/max30102.py :lib/max30102.py $ mpremote run oximeter.py $ mpremote repl Raspberry Pi Picoをターミ ナルから操作する 最初の実装を正解にせず、比較を始める観測点にする 10
  10. 開発の三角測量 観測点2:C言語とSpresense 参照実装は C++(.cxx) uint32_t red = 0; uint32_t ir

    = 0; bool ok = sensor.readFifo(red, ir); if (!ok) { logMsg("MAX30102の読込エラー", "WARN"); } 変えるもの •言語と型 •マイコン return; •OSとI2C API printf("RAW RED=%lu IR=%lu\n", (unsigned long)red, (unsigned long)ir); 見えるもの •ビット幅とI2Cトランザク ション •リセット待機方法の差 2つ目の環境で再現すると、センサー固有の仕様が見え始める •FIFO初期化の有無 10
  11. 開発の三角測量 観測点3:PicoRubyで統合 先行実装をテストへ変換 MicroPython版 max30102̲test.rb PicoRuby 共通仕様と実装差を固定 mrbgem C言語版 FRAME

    = "\x03\xFF\xFF\x02\x00\x01" assert_equal( { red: 262_143, ir: 131_073 }, sensor.read ) ゴールデンベクター •6バイトを再現可能な入力にする •実機なしで18ビット復号を検証 •FIFO周回・負の温度・異常値もFake I2C で再現 11
  12. 開発の三角測量 3実装から抽出した共通の仕様 項目 値・処理 I2Cアドレス / Part ID 0x57 /

    0x15 FIFO設定 0x08 ← 0x4F 動作モード 0x09 ← 0x03(SpO2モード) ADC・レート・パルス幅 0x0A ← 0x27 LED振幅 0x0C, 0x0D ← 0x24 FIFOデータ 赤色3バイト + 赤外3バイト 復号 18ビット値として0x3FFFFでマスク 完全に同じ光学値ではなく、レジスター・データ形式・値域・ビット演算を共通の仕様にする 12
  13. 成果 MAX30102 mrbgemの公開 参照実装は PicoRuby require "i2c" require "max30102" i2c

    = I2C.new(unit: :RP2040_I2C0, sda_pin: 16, scl_pin: 17, frequency: 400_000) sensor = MAX30102.new(i2c: i2c) sample = sensor.read_fifo puts "red=#{sample[:red]}, ir=#{sample[:ir]}" red Red light(赤色光) 約660 nmの反射光を変換した ADC値 ir Infrared light(赤外光) 約880 nmの反射光を変換した ADC値 MAX30102の設定と生データ取得をmrbgemにまとめた https://github.com/ogom/rpremote/blob/main/examples/picoruby/mrbgems/max30102 13
  14. 成果 PicoRuby製パルスオキシメータへの統合 MAX30102 Processor mrbgem BeatDetector SpO2推定 + Session +

    Session 表示 脈拍数 SpO2 IR値の移動平均とベースラインを比較 平均をDC成分、標準偏差をAC成分として 有効な拍動間隔を平均 ratio-of-ratiosを計算 bpm = 60,000 平均間隔[ms] 推定SpO2 = 110 ­ 25 R 脈拍数とSpO2の参考値を推定するPicoRubyアプリケーション https://github.com/ogom/rpremote/tree/main/examples/picoruby/projects/oximeter 14
  15. 成果 まとめ 1 2 MicroPython Pico 基線 すばやく試す C言語 Spresense

    別環境で確かめる MAX30102の データシートの仕様 共通点と相違点を照合し 3 PicoRuby Pico mrbgemの契約へ変換 共通仕様を統合する 3つの観測点から、確信がもてる mrbgem を作る 16
  16. 成果 rpremote の紹介 mpremoteで慣れたリモート操作を、PicoRubyのR2P2ファームウェアに対応 操作 mpremote rpremote コードの一時実行 mpremote run

    main.py rpremote run main.rb REPL mpremote repl rpremote repl ファイル転送 mpremote fs cp file :/file rpremote fs cp file :/file ターミナルコマンド PicoRuby向けの拡張 $ rpremote fs push oximeter/lib/oximeter :/lib/oximeter $ rpremote run oximeter/main.rb •ファームウェアの準備・ビルド・書き込み # build, bootsel, flash, copy, run $ rpremote deploy --build oximeter •deployでlibとmain.rbを配置して実行 •Mrbgems.lockでmrbgemのバージョンを固定 •run・exec・monitor・repl・resetを1つのCLIへ統合 リモート操作に加え、mrbgemを含むPicoRubyファームウェアのビルドまで扱う 参考:https://github.com/ogom/rpremote 13
  17. OSS Gate OSS Gate 大阪 と OSS Gate Pass 2026

    6年9ヶ月ぶりにOSS Gate 大阪を開催 OSS Gate Pass 2026 •OSS Gate 10周年記念オフラインカン ファレンス! •2026-10-03(土) •株式会社アンドパッド(住友不動産東京 三田ガーデンタワー37階) 15