Post date: 2020/06/21
在宅ワークのためのホコリセンサーのつもりで Max30105 (particle sensor) を買おうとしていたのだが、何かの間違いで Max30102 (pulse oximeter, heart-rate sensor) を買ってしまった。Amazon でいろいろ見て回るうちに、一番安いのを買ったのかもしれない(が、よく覚えていない)。
せっかくなので、脈拍と血中酸素濃度の測定器を作成することにした。
RaspberryPi Zero WH につないで、測ってみた。
こちらのサイト(Raspberry Piと心拍センサ(MAX30102)で脈を見てみよう)のソースを動かしてみたところ、5V をつなげばそのまま動いた。
$ i2cdetect -y 1 で出ない)血中酸素濃度も図れるようなので感心していたら、家族から「それ最近品薄で問題になっているやつ」との指摘あり。
M5StickC につないで、表示ありで動くようにすることにした。
Amazon の販売ページにMeasure Heart Rate and SpO2 with MAX30102という記事へのリンクあったので、それを利用
M5.begin();Wire.begin(0, 26);問題発生:
particleSensor.begin() が1回で応答しないので、while ループに変更while(!particleSensor.begin()) { delay(1); }仕方がないので、SPO2値の計算方法を調べてみるが、とりあえず2波長のAC成分とDC成分から計算すればよいことがわかる。
※本当は、Maker Faire Kyoto Online に参加しようと 5/2 当日朝から頑張っていたのだが、15:30 にぎりぎり間に合わず断念。
その後、忙しいので放っておいたが、Amazon の販売ページに新しいコメントを発見(同等品と思われるこちらにも記述あり)。やはり library がおかしい (それも、red と IR のデータが逆?点滅の順がおかしい?)。
詳しくはこちら (MAX30102でパルスオキシメーターを作る)。
記事通りに、led=1 (red only) としてみると、
ことがわかる。つまり、
led=1 は IR onlygetRed() は IR灯火時のセンサ読み取り値getIR() は Red 灯火時のセンサ読み取りの値であることが確認されてしまう。ライブラリのソースを見ると順番に読み取っているだけのようなのだが、面倒なのでアドホックに対応。
getRed() をgetIR() に変更getIR() をgetRed() に変更これでとりあえず動くようになった。
※ただ、私のはうまく読み取れるのだが。。。。
Red, IR, Green の順に4 byte x 3 づつ読み出し -> 18 bit 抜き出し
修正方法?:
...static const uint8_t SLOT_RED_LED = 0x01;static const uint8_t SLOT_IR_LED = 0x02;static const uint8_t SLOT_GREEN_LED = 0x03;...void MAX30105::setup(...) { ... //Multi-LED Mode Configuration, Enable the reading of the three LEDs //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- enableSlot(1, SLOT_RED_LED); if (ledMode > 1) enableSlot(2, SLOT_IR_LED); if (ledMode > 2) enableSlot(3, SLOT_GREEN_LED); ...}uint16_t MAX30105::check(void){... while (toGet > 0) { ... byte temp[sizeof(uint32_t)]; //Array of 4 bytes that we will convert into long uint32_t tempLong; //Burst read three bytes - RED temp[3] = 0; temp[2] = _i2cPort->read(); temp[1] = _i2cPort->read(); temp[0] = _i2cPort->read(); //Convert array to long memcpy(&tempLong, temp, sizeof(tempLong)); tempLong &= 0x3FFFF; //Zero out all but 18 bits sense.red[sense.head] = tempLong; //Store this reading into the sense array if (activeLEDs > 1) { ... sense.IR[sense.head] = tempLong; } if (activeLEDs > 2) { ... sense.green[sense.head] = tempLong; } toGet -= activeLEDs * 3; }「みんなのM5Stack自慢大会」の告知を SwitchScience で発見し、何とかネタにしようと30分考えた。
ということで、プログラム小修正と、実験開始。しかし、なかなか動くようで、動かないようで。。。。
とりあえず「Heboi」ジャンルで、facebook に投稿 (2020-06-20)。
6. 残った謎