Description
Make your question, not a Statement, inclusive. Include all pertinent information:
What you are trying to do
I tried to use ESP32 wroom dev board and use Adafruit_MLX90614 and MAX30102 sensor on I2C communication. As you might know both works on I2C communication. but It did not work. Any piece of advice will be highly appreciated.
Describe your system (Hardware, computer, O/S, core version, environment)
ESP32 Wroom dev MLX90614 and MAX30102
Describe what is failing
MAX30102 provide the data but mlx does not. If I am using a separate-2 2 programs then It is working fine.Which is kind of indication that the wiring is correct.
/*
simple SpO2 plotter for MH-ET LIVE MAX30102 breakout board and ESP32 devkit-C
Using Sparkfun MAX3010X library
https://github.com/sparkfun/SparkFun_MAX3010x_Sensor_Library
ESP32_MAX30102_simple-SpO2_plotter.ino
by coniferconifer Copyright 2020
LICENSED under Apache License 2.0
Version 1.0
Shows SpO2 and the user's heart beat on Arduino's serial plotter.
No display hardware is required.
This program should not be used for medical purposes.
I wrote this to learn how SpO2 can be measured and pay tributes for the inventors.
Pulse oximetry was developed in 1972, by Takuo Aoyagi and Michio Kishi,
bioengineers, at Nihon Kohden in Japan.
https://ethw.org/Takuo_Aoyagi
Since MH-ET LIVE MAX30102 breakout board seems outputting IR and RED swapped.
red = particleSensor.getFIFOIR();
ir = particleSensor.getFIFORed();
is used in my code. If you have Sparkfun's MAX30105 breakout board , try to
use #define MAX30105
Tips:
SpO2 is calculated as R=((square root means or Red/Red average )/((square root means of IR)/IR average))
SpO2 = -23.3 * (R - 0.4) + 100;
// taken from a graph in https://ww1.microchip.com/downloads/jp/AppNotes/00001525B_JP.pdf
// https://ww1.microchip.com/downloads/en/Appnotes/00001525B.pdf
Instructions:
- Install Sparkfun's MAX3010X library
- Load code onto ESP32 with MH-ET LIVE MAX30102 board
- Put MAX30102 board in plastic bag and insulates from your finger.
and attach sensor to your finger tip - Run this program by pressing reset botton on ESP32
- Wait for 3 seconds and Open Arduino IDE Tools->'Serial Plotter'
Make sure the drop down is set to 115200 baud - Search the best position and presure for the sensor by watching
the blips on Arduino's serial plotter
I recommend to place LED under the backside of nail and wrap you
finger and the sensor by rubber band softly. - Checkout the SpO2 and blips by seeing serial Plotter
100%,95%,90%,85% SpO2 lines are always drawn on the plotter
Hardware Connections (Breakoutboard to ESP32 Arduino):
-VIN = 3.3V
-GND = GND
-SDA = 21 (or SDA)
-SCL = 22 (or SCL)
-INT = Not connected
this script also works on Arduino nao
Hardware Connections (Breakoutboard to Arduino nano): experimental
-VIN = 3.3V
-GND = GND
-SDA = A4 (or SDA)
-SCL = A5 (or SCL)
-INT = Not connected
Trouble Shooting:
Make sure to solder jumper on 3V3 side.
if you forget this, I2C does not work and can not find MAX30102.
says "MAX30102 was not found. Please check wiring/power."
*/
#include <Wire.h>
#include "MAX30105.h" //sparkfun MAX3010X library
#include <Adafruit_MLX90614.h>
bool status;
Adafruit_MLX90614 mlx = Adafruit_MLX90614(0x5A);
MAX30105 particleSensor;
TwoWire I2CBME = TwoWire(0);
//#define MAX30105 //if you have Sparkfun's MAX30105 breakout board , try #define MAX30105
#define USEFIFO
#define I2C_SDA 33 //21
#define I2C_SCL 32 //22
void setup()
{
// Serial.begin(9600);
Serial.begin(115200);
I2CBME.begin(I2C_SDA, I2C_SCL, I2C_SPEED_FAST);
// Serial.println("mlx start Initializing...");
//status = mlx.begin();
Serial.print(status) ;
// mlx.begin();
mlx.begin();
// Serial.println("mls end Initializing...");
// Serial.println("max start Initializing...") ;
// Initialize sensor
//if (!particleSensor.begin(Wire, I2C_SPEED_FAST)) //Use default I2C port, 400kHz speed
if (!particleSensor.begin(I2CBME, I2C_SPEED_FAST ,0x57)) //Use default I2C port, 400kHz speed
{
// Serial.println("MAX30102 was not found. Please check wiring/power/solder jumper at MH-ET LIVE MAX30102 board. ");
// while (1);
}
//Setup to sense a nice looking saw tooth on the plotter
byte ledBrightness = 0x7F; //Options: 0=Off to 255=50mA
byte sampleAverage = 4; //Options: 1, 2, 4, 8, 16, 32
byte ledMode = 2; //Options: 1 = Red only, 2 = Red + IR, 3 = Red + IR + Green
//Options: 1 = IR only, 2 = Red + IR on MH-ET LIVE MAX30102 board
int sampleRate = 200; //Options: 50, 100, 200, 400, 800, 1000, 1600, 3200
int pulseWidth = 411; //Options: 69, 118, 215, 411
int adcRange = 16384; //Options: 2048, 4096, 8192, 16384
// Set up the wanted parameters
particleSensor.setup(ledBrightness, sampleAverage, ledMode, sampleRate, pulseWidth, adcRange); //Configure sensor with these settings
}
double avered = 0; double aveir = 0;
double sumirrms = 0;
double sumredrms = 0;
int i = 0;
int Num = 100;//calculate SpO2 by this sampling interval
double ESpO2 = 95.0;//initial value of estimated SpO2
double FSpO2 = 0.7; //filter factor for estimated SpO2
double frate = 0.95; //low pass filter for IR/red LED value to eliminate AC component
#define TIMETOBOOT 3000 // wait for this time(msec) to output SpO2
#define SCALE 88.0 //adjust to display heart beat and SpO2 in the same scale
#define SAMPLING 5 //if you want to see heart beat more precisely , set SAMPLING to 1
#define FINGER_ON 30000 // if red signal is lower than this , it indicates your finger is not on the sensor
#define MINIMUM_SPO2 80.0
void loop()
{
Serial.print("status is mlx " + status) ;
Serial.println("Ambient = ");
Serial.print(mlx.readAmbientTempC());
Serial.print("*C\tObject = ");
Serial.print(mlx.readObjectTempC());
Serial.println("*C");
Serial.print("Ambient = ");
Serial.print(mlx.readAmbientTempF());
Serial.print("*F\tObject = ");
Serial.print(mlx.readObjectTempF());
Serial.println("*F");
uint32_t ir, red , green;
double fred, fir;
double SpO2 = 0; //raw SpO2 before low pass filtered
#ifdef USEFIFO
particleSensor.check(); //Check the sensor, read up to 3 samples
while (particleSensor.available()) {//do we have new data
#ifdef MAX30105
red = particleSensor.getFIFORed(); //Sparkfun's MAX30105
ir = particleSensor.getFIFOIR(); //Sparkfun's MAX30105
#else
red = particleSensor.getFIFOIR(); //why getFOFOIR output Red data by MAX30102 on MH-ET LIVE breakout board
ir = particleSensor.getFIFORed(); //why getFIFORed output IR data by MAX30102 on MH-ET LIVE breakout board
#endif
i++;
mlx.begin();
Serial.print("Ambient = ");
Serial.print(mlx.readAmbientTempC());
Serial.print("*C\tObject = ");
Serial.print(mlx.readObjectTempC());
Serial.println("*C");
Serial.print("Ambient = ");
Serial.print(mlx.readAmbientTempF());
Serial.print("*F\tObject = ");
Serial.print(mlx.readObjectTempF());
Serial.println("*F");
Serial.println();
delay(1000);
fred = (double)red;
fir = (double)ir;
avered = avered * frate + (double)red * (1.0 - frate);//average red level by low pass filter
aveir = aveir * frate + (double)ir * (1.0 - frate); //average IR level by low pass filter
sumredrms += (fred - avered) * (fred - avered); //square sum of alternate component of red level
sumirrms += (fir - aveir) * (fir - aveir);//square sum of alternate component of IR level
if ((i % SAMPLING) == 0) {//slow down graph plotting speed for arduino Serial plotter by thin out
if ( millis() > TIMETOBOOT) {
float ir_forGraph = (2.0 * fir - aveir) / aveir * SCALE;
float red_forGraph = (2.0 * fred - avered) / avered * SCALE;
//trancation for Serial plotter's autoscaling
if ( ir_forGraph > 100.0) ir_forGraph = 100.0;
if ( ir_forGraph < 80.0) ir_forGraph = 80.0;
if ( red_forGraph > 100.0 ) red_forGraph = 100.0;
if ( red_forGraph < 80.0 ) red_forGraph = 80.0;
// Serial.print(red); Serial.print(","); Serial.print(ir);Serial.print(".");
if (ir < FINGER_ON) ESpO2 = MINIMUM_SPO2; //indicator for finger detached
Serial.print(ir_forGraph); // to display pulse wave at the same time with SpO2 data
Serial.print(","); Serial.print(red_forGraph); // to display pulse wave at the same time with SpO2 data
Serial.print(",");
Serial.print(ESpO2); //low pass filtered SpO2
Serial.print(","); Serial.print(85.0); //reference SpO2 line
Serial.print(","); Serial.print(90.0); //warning SpO2 line
Serial.print(","); Serial.print(95.0); //safe SpO2 line
Serial.print(","); Serial.println(100.0); //max SpO2 line
delay(3000);
}
}
if ((i % Num) == 0) {
double R = (sqrt(sumredrms) / avered) / (sqrt(sumirrms) / aveir);
// Serial.println(R);
SpO2 = -23.3 * (R - 0.4) + 100; //http://ww1.microchip.com/downloads/jp/AppNotes/00001525B_JP.pdf
ESpO2 = FSpO2 * ESpO2 + (1.0 - FSpO2) * SpO2;//low pass filter
// Serial.print(SpO2);Serial.print(",");Serial.println(ESpO2);
sumredrms = 0.0; sumirrms = 0.0; i = 0;
break;
}
particleSensor.nextSample(); //We're finished with this sample so move to next sample
//Serial.println(SpO2);
}
#else
while (1) {//do we have new data
#ifdef MAX30105
red = particleSensor.getRed(); //Sparkfun's MAX30105
ir = particleSensor.getIR(); //Sparkfun's MAX30105
#else
red = particleSensor.getIR(); //why getFOFOIR outputs Red data by MAX30102 on MH-ET LIVE breakout board
ir = particleSensor.getRed(); //why getFIFORed outputs IR data by MAX30102 on MH-ET LIVE breakout board
#endif
i++;
fred = (double)red;
fir = (double)ir;
avered = avered * frate + (double)red * (1.0 - frate);//average red level by low pass filter
aveir = aveir * frate + (double)ir * (1.0 - frate); //average IR level by low pass filter
sumredrms += (fred - avered) * (fred - avered); //square sum of alternate component of red level
sumirrms += (fir - aveir) * (fir - aveir);//square sum of alternate component of IR level
if ((i % SAMPLING) == 0) {//slow down graph plotting speed for arduino IDE toos menu by thin out
//#if 0
if ( millis() > TIMETOBOOT) {
float ir_forGraph = (2.0 * fir - aveir) / aveir * SCALE;
float red_forGraph = (2.0 * fred - avered) / avered * SCALE;
//trancation for Serial plotter's autoscaling
if ( ir_forGraph > 100.0) ir_forGraph = 100.0;
if ( ir_forGraph < 80.0) ir_forGraph = 80.0;
if ( red_forGraph > 100.0 ) red_forGraph = 100.0;
if ( red_forGraph < 80.0 ) red_forGraph = 80.0;
// Serial.print(red); Serial.print(","); Serial.print(ir);Serial.print(".");
if (ir < FINGER_ON) ESpO2 = MINIMUM_SPO2; //indicator for finger detached
Serial.print((2.0 * fir - aveir) / aveir * SCALE); // to display pulse wave at the same time with SpO2 data
Serial.print(","); Serial.print((2.0 * fred - avered) / avered * SCALE); // to display pulse wave at the same time with SpO2 data
Serial.print(","); Serial.print(ESpO2); //low pass filtered SpO2
Serial.print(","); Serial.print(85.0); //
Serial.print(","); Serial.print(90.0); //warning SpO2 line
Serial.print(","); Serial.print(95.0); //safe SpO2 line
Serial.print(","); Serial.println(100.0); //max SpO2 line
//#endif
Serial.println();
delay(1000);
}
}
if ((i % Num) == 0) {
double R = (sqrt(sumredrms) / avered) / (sqrt(sumirrms) / aveir);
// Serial.println(R);
SpO2 = -23.3 * (R - 0.4) + 100; //http://ww1.microchip.com/downloads/jp/AppNotes/00001525B_JP.pdf
ESpO2 = FSpO2 * ESpO2 + (1.0 - FSpO2) * SpO2;
// Serial.print(SpO2);Serial.print(",");Serial.println(ESpO2);
sumredrms = 0.0; sumirrms = 0.0; i = 0;
break;
}
particleSensor.nextSample(); //We're finished with this sample so move to next sample
//Serial.println(SpO2);
}
#endif
}