[ESP8266][MAX30102] MAX30102でパルスオキシメーターを作る


コロナ肺炎とパルスオキシメーター

新型コロナウイルスの重症度の判定で血中酸素飽和度を簡単に測定できるでバルスオキシメーターが品薄になってしまった。パルスオキシメーターを指に挟むことで脈拍(脈波・心拍数)と酸素飽和度(サチュレーション)を簡単に測定できる。歯科治療においても、この2項目をモニターすることで、患者さんの異常を早く検知できるのでとても心強いし、価格も安価(だった)なので複数持っている先生も多いと思う。

体温計が一気に市場から消えたのと同じく、新型コロナウイルスによる肺炎の重症度の目安として「血中酸素飽和度(SpO2)が常に95%以下」との報道がなされると同時に店から消えた。中国発送のものはまだ買えるみたいだけど、到着まで早くても1か月以上はかかると思う。

昔にラズパイのセンサーを買い漁ってた時にSpO2を測定できるセンサーのMAX30102を2個買っていたことを思い出した。この時は、MAX30102をラズパイで使うライブラリを見つけられなくて早々に興味を無くし、いつか使うであろうボックスに投げ込んでおいた。

このパルスオキシメーターが足りない現在、ArduinoやESP8266で実用化できるレベルまで使えるようにすれば、もしコロナに感染した時に常にモニターして、心拍、SpO2に異常があれば家族に自動的にメールなどすれば最悪の事態は避けられるかもしれない。


MAX30102(心拍数・SPO2センサー)をESP8266で使う

早速、ESP8266、MAX30102で下のサイトを参考にすすめてみた。

I2C接続でMAX30102を繋げる。Arduinoのデフォルト(A4[SDA]・A5[SCL])で接続することになるけど、ESP8266で利用するにはGPIO0とGPIO2を使って行う。基本構成は下図で行こうとおもう。ESP-01な感じで書いてあるけど( ´∀` )。。。技適通ったESP8266に適宜読み替えてください。

Wire.begin(0,2);

をI2Cセットアップ時にを忘れずに!!。

ちなみにMAX30102はしたのを購入済み(去年の10月w)

で、参考サイトを読んでいると、ライブラリも導入する必要がある。ライブラリは下

Arduino Studioからもインストール可能。サンプルスケッチExample8_SPO2を実行してみる

ん・・・。HR=166、SPO2=76-89とか・・・。

このバイタルサインは・・・死んでますよ?ww

どんな処理しているのかコードを追ってみる。。。どうやらspo2_algorithm.cppが心臓部らしい。

読んでみると・・・

なにしてるかよくわかんねぇぇよww

「これは・・・終わったかな?」とおもったけど、下のテストスケッチで生データをシリアルプロッタでみると、ちゃんとデータは取れているようだ・・・。

赤外線(IR)パルスと赤色(Red)パルスを分析することでSPO2がわかるらしいので、できるかどうかも含めて資料をネットの海から集める。

https://arxiv.org/ftp/arxiv/papers/1907/1907.11989.pdf

(抜粋)

上のグラフ図にすべてが集約されているようだ。つまりはRed_AC、Red_DC、IR_AC、IR_DCがわかればSPO2が出るってことね。あとは

$$R=\frac{Red_{AC} \div Red_{DC}}{IR_{AC} \div IR_{DC}}$$

でRを求めて、RからSPO2を求める式はspo2_algorithm.cppにあったのでこれを準用する。

$$SPO_{2}[\%]=-45.060R^2+30.354R+94.845$$

自分はSPO2は通常、安静状態で97-99程度(手持ちのパルスオキシメーターで確認済)なので、

$$98=-45.060R^2+30.354R+94.845$$

上の二次方程式を解くと 大体R = 0.1284 , 0.5452となる。この付近の数値になればいいと予想がつく。

その上でグラフの目盛りを大体で読んで手計算で求めたら、R=1.782とかになった。何度も何度も検算しても1以下にならない

もうさぁ~このセンサー壊れてない?

心が折れそうになったその時、1.782って・・・なんか・・・

$$\frac{1}{1.782}=0.561$$

逆数にするとちょうどよくね?息ごらえ(SPO2を意図的に下げる)して計算しても93-94%に落ちているようだ。

これは・・・IRとRedが逆なんでは?

コード上でが逆になってる様子はない。嫌な予感・・・ledMode = 1(赤色LEDのみ)にしてセンサーをみると、赤色LEDは光っていない。指をかざすとgetRed()で変化する数値が取得で来ている・・・・これは・・・もしや・・・IR(赤外線)のほうでは?

赤外線カメラで確認してみると

おEEEE!!!やっぱり逆じゃねーか!

この個体が逆なのか、メーカ正規品(SparkFun)は正常なのか、わからないけど、これはとりあえずIRとRedは逆なんですねw。こんなので2日も悩んだよ・・・マジで・・・


組み立てとスケッチ実装

気を取り直して、3Dプリンタでマウンタを作り、マジックテープのバンドをつけて安定して固定できるようにした。

センサー表面には直接金属端子が触れないよう、セロテープを表面に張り付けた。

スケッチにコメントいれてあるけど、要点は3つのみ

  • ビートの区切りは直前のデータとの差の変位量で判断(IRの方を使っている)
  • DCの計算は1ビートの移動平均を使う
  • ACの計算は1ビートの最大値と最小値の差で計算

ちなみにビートとDC(移動平均)のグラフを掲載

ちなみに移動平均を簡単に処理してくれる下のライブラリを使わせてもらった。感謝!

ノイズ処理はもーちょいしたほうがよさそうだけど、サンプルスケッチなんかよりはよっぽど安定していると思う。

赤はSPO2、青は心拍数。SPO2が下がっているところは息ごらえ(頑張って息を止める)をしたところ。

酸素が少ない血が指まで運ばれるのに時間がかかるので、実際下がるのは5秒~10秒後なので下がらないからといって止めてると死にますから注意です。

心拍数はギザギザ上下しているように見えけど、これは息を吸う時は心拍数が少し上がり、吐くときに少し下がるという生理現象。さすがに息止めの前後は変化してるけど、呼吸性の変化も捉えることができているのは驚き。

手持ちのパルスオキシメーターとの比較したけど、ほぼ同じ数値をとっていました~。とりあえず、ここまでできればあとはデータベースで焼くなり煮るなりすればいいと思います。95%以下が3分続いたらメールとかね。もう疲れたから今度やります。

最後に一言!センサーを使う前に

赤外線と赤色光の数値を要チェック!!

これ重要!!

[追記2020/05] リアルタイムにグラフ表示もしてみました

[追記2020/05/20]

FBでライブラリのissueに「IRとRedが逆じゃない?」みたいな質問あるねって情報もらいました。

5/10にissue投稿してるんだけど、5/4-5にこの記事だしてるから、もしかしてこのサイトみたのかなぁ(期待)?それはいいとして…とりあえずSparkFun純正使ってないと答えてくれないだろうし…回答を見守ります。

2 thoughts on “[ESP8266][MAX30102] MAX30102でパルスオキシメーターを作る

Comments are closed.