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. 残った謎