試み
MAX30102 というPulse Ox Sensorを利用して、脈拍と酸素濃度を測る試み。
MAX30100の実例が多いが、MAX30102の実例が少ない。
プログラム
「参考1」のSparkFunのライブラリを利用する。そのライブラリはMAX30105(R,G,IR LED)用だが、MAX30102(欠Green LED)でも利用できる。
OLED表示するため、「参考2」の表示部分を合体した。なんとなく、バグがある様な気がする。
// Sample implementation of the MAX30100 PulseOximeter // Using the following module // http://www.ebay.com/itm/-/391709438817?ssPageName=STRK:MESE:IT // can not gaurantee if the app will work with other implementations of the module. //#include "MAX30100_PulseOximeter.h" #include <U8g2lib.h> #include <Wire.h> #include "MAX30105.h" #include "heartRate.h" #define REPORTING_PERIOD_MS 500 U8G2_SSD1306_128X32_UNIVISION_F_HW_I2C u8g2(U8G2_R0); // PulseOximeter is the higher level interface to the sensor // it offers: // * beat detection reporting // * heart rate calculation // * SpO2 (oxidation level) calculation //PulseOximeter pox; MAX30105 particleSensor; const byte RATE_SIZE = 4; //Increase this for more averaging. 4 is good. byte rates[RATE_SIZE]; //Array of heart rates byte rateSpot = 0; long lastBeat = 0; //Time at which the last beat occurred float beatsPerMinute; int beatAvg; //byte pulseLED = 13; //Must be on PWM pin //byte readLED = 11; //Blinks with each data read // bool calculation_complete=false; bool calculating=false; bool initialized=false; byte beat=0; void show_beat() { u8g2.setFont(u8g2_font_cursor_tf); u8g2.setCursor(8,10); if (beat==0) { u8g2.print("_"); beat=1; } else { u8g2.print("^"); beat=0; } u8g2.sendBuffer(); } void initial_display() { if (not initialized) { u8g2.clearBuffer(); show_beat(); u8g2.setCursor(24,12); u8g2.setFont(u8g2_font_profont15_mr); u8g2.print("Place finger"); u8g2.setCursor(0,30); u8g2.print("on the sensor"); u8g2.sendBuffer(); initialized=true; } } void display_calculating(int j) { if (not calculating) { u8g2.clearBuffer(); calculating=true; initialized=false; } show_beat(); u8g2.setCursor(24,12); u8g2.setFont(u8g2_font_profont15_mr); u8g2.print("Measuring..."); u8g2.setCursor(0,30); u8g2.print(beatsPerMinute); u8g2.print(" Bpm"); u8g2.sendBuffer(); } void display_values() { u8g2.clearBuffer(); u8g2.setFont(u8g2_font_profont15_mr); u8g2.setCursor(0,30); u8g2.print(beatsPerMinute); u8g2.print(" Bpm _ "); u8g2.setCursor(65,30); u8g2.print(beatAvg); u8g2.sendBuffer(); } void setup() { Serial.begin(115200); // pinMode(pulseLED, OUTPUT); // pinMode(readLED, OUTPUT); u8g2.begin(); // Initialize sensor if (!particleSensor.begin(Wire, I2C_SPEED_FAST)) //Use default I2C port, 400kHz speed { Serial.println(F("MAX30105 was not found. Please check wiring/power.")); while (1); } particleSensor.setup(); //Configure sensor with default settings particleSensor.setPulseAmplitudeRed(0x0A); //Turn Red LED to low to indicate sensor is running particleSensor.setPulseAmplitudeGreen(0); //Turn off Green LED initial_display(); } void loop() { long irValue = particleSensor.getIR(); float temperature = particleSensor.readTemperature(); // digitalWrite(readLED, !digitalRead(readLED)); //Blink onboard LED with every data read if (checkForBeat(irValue) == true) { calculation_complete=true; calculating=false; initialized=false; // digitalWrite(pulseLED, !digitalRead(pulseLED)); //Blink onboard LED with every Beat //We sensed a beat! long delta = millis() - lastBeat; lastBeat = millis(); if (delta < 10000) { beatsPerMinute = 60 / (delta / 1000.0); } else { calculation_complete=false; beatsPerMinute=0; initial_display(); } if (beatsPerMinute < 255 && beatsPerMinute > 20) { rates[rateSpot++] = (byte)beatsPerMinute; //Store this reading in the array rateSpot %= RATE_SIZE; //Wrap variable //Take average of readings beatAvg = 0; for (byte x = 0 ; x < RATE_SIZE ; x++) beatAvg += rates[x]; beatAvg /= RATE_SIZE; display_values(); } } else { if (irValue < 50000) { calculating=false; initial_display(); } else { display_calculating(5); } } Serial.print("IR="); Serial.print(irValue); Serial.print(", BPM="); Serial.print(beatsPerMinute); Serial.print(", Avg BPM="); Serial.print(beatAvg); Serial.print(", initialized="); Serial.print(initialized); Serial.print(", calculating="); Serial.print(calculating); Serial.print(", calculation_complete="); Serial.print(calculation_complete); Serial.println(); }
実験
かなり不安定の感じがする。
一応、形はできたが、
しかし、脈拍捉えるのは稀て、今回も失敗して。。。
参考
- https://learn.sparkfun.com/tutorials/max30105-particle-and-pulse-ox-sensor-hookup-guide
- https://www.hackster.io/umar-sear/arduino-heart-rate-monitor-a8e9e1
- https://www.hackster.io/AAKS/max30100-and-blynk-0f58f4