adafruit / Adafruit-MLX90614-Library

Arduino library for the MLX90614 sensors in the Adafruit shop
Other
128 stars 97 forks source link

Multiple I2c Does not working -Always returning high number 1037 #20

Closed fervidautomation closed 3 years ago

fervidautomation commented 3 years ago

Hello Team, I am using Adafruit_MLX90614 for capturing the temperature. When I am using a single I2C sensor it is working fine and returning the correct temperature.

When I tried to use Adafruit_MLX90614 wih MAX30105.h library. My MAX30102 is working fine and returning the correct value for MAX30102 sensor but MLX90614 always return 1037 lke below output

@ ⸮⸮X⸮h̘⸮1⸮M⸮⸮mlx status is status is mlx Ambient = 1037.55C Object = 1037.55C Ambient = 1899.59F Object = 1899.59F status is mlx Ambient = 1037.55C Object = 1037.55C Ambient = 1899.59F Object = 1899.59F status is mlx Ambient = 1037.55C Object = 1037.55C Ambient = 1899.59F Object = 1899.59F 100.00,100.00,80.00,85.00,90.00,95.00,100.00 status is mlx Ambient = 1037.55C Object = 1037.55C Ambient = 1899.59F Object = 1899.59F

The same wiring works fine when I am using a single I2C device. Any help will be highly appreciated Thank you.

Code:

/*

Hardware Connections (Breakoutboard to ESP32 Arduino):

-VIN = 3.3V -GND = GND -SDA = 21 (or SDA) -SCL = 22 (or SCL) -INT = Not connected

*/

include

include //sparkfun MAX3010X library

include

bool status; Adafruit_MLX90614 mlx = Adafruit_MLX90614(0x5A); MAX30105 particleSensor; TwoWire I2CBME = TwoWire(0); TwoWire I2CMLX = TwoWire(1);

define USEFIFO

define I2C_SDA 33 //21

define I2C_SCL 32 //22

define I2C_SDA1 21 //21

define I2C_SCL1 22 //2

void setup() { Serial.begin(9600); I2CMLX.begin(I2C_SDA1, I2C_SCL1, I2C_SPEED_FAST);

mlx.begin(); I2CBME.begin(I2C_SDA, I2C_SCL, I2C_SPEED_FAST); // Serial.println("mlx start Initializing...");

//status = mlx.begin();
Serial.print("mlx status is " + status) ; // mlx.begin();

if (!mlx.begin()) //Use default I2C port, 400kHz speed { Serial.println("mlx was not found. . "); while (1); }

// 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");

delay(5000); 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++;

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

}

ladyada commented 3 years ago

you need to use setPins() to set the i2c pins on ESP32 because libraries call begin() in the library https://github.com/espressif/arduino-esp32/issues/3779

fervidautomation commented 3 years ago

I got below error when I tried to setpins()

32:9: error: 'class TwoWire' has no member named 'setPins' Wire.setPins(I2C_SDA1,I2C_SCL1); ^ exit status 1 'class TwoWire' has no member named 'setPins'

Code:

include

include

include //sparkfun MAX3010X library

define IR1 0x5A

bool statusMLX; bool statusMAX; Adafruit_MLX90614 mlx = Adafruit_MLX90614(IR1); MAX30105 maxSensor; TwoWire I2CMAX = TwoWire(0);

define I2C_SDA 33 //21

define I2C_SCL 32 //22

define I2C_SDA1 21 //21

define I2C_SCL1 22 //22

inline const char * const BoolToString(bool b) { return b ? "true" : "false"; }

void setup() { Serial.begin(9600);

ifdef ARDUINO_ARCH_ESP32

Wire.setPins(I2C_SDA1,I2C_SCL1);

endif

statusMLX= mlx.begin(); //statusMAX =maxSensor.begin(Wire, I2C_SPEED_FAST); Serial.println("mlx status is "); Serial.println( BoolToString( statusMLX)) ; Serial.println("MAX status is "); Serial.println( BoolToString( statusMAX)) ;

I2CMAX.begin(I2C_SDA, I2C_SCL, I2C_SPEED_FAST); }

void loop() { 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); }

ladyada commented 3 years ago

you'll need to figure out for your platform how to create two different i2c ports without using begin(pin1, pin2) - not sure what you're doing or how

fervidautomation commented 3 years ago

Thank you for your response.

I am using ESP32 Wroom with 2 I2C sensor. MAX30102 and MLX90614.

I need to get value from both sensor after a set interval. individually both the sensor are working in poc project. When I am trying to access both in single program than MLX90614 is not returning the correct value. it always return 1037.

Thank you in advance for your help

mjohanarif commented 3 years ago

i am doing similar project like yours, so have you been able to do it? and how did you do it?

caternuson commented 3 years ago

Closing. This isn't an issue with this library. It's a generic issue with configuring I2C port(s) for use with multiple devices.