Please help: max30100 and mlx90614 not working correctly when connected at the same time to UNO

hi, I'm working on a spo2 (max30100) and temp(mlx90614) measuring system using Arduino uno when i connect each sensor individually to the uno i get correct readings from both sensors, but when connected at the same time the spo2 sensor works fine but the mlx90164 temp sensor reads very unusual temperatures like (-231, 879,376.-100,1007 ,....). I'm using an OLED (I2C) display to view the output. This is the code:

#include <Wire.h>
#include <MAX30100_PulseOximeter.h>
#include <DFRobot_MLX90614.h>
#include <OakOLED.h>

// OLED display and pulse oximeter objects
OakOLED oled;
PulseOximeter pox;
DFRobot_MLX90614_I2C mlx;

// Reporting period in milliseconds
#define REPORTING_PERIOD_MS 1000

void setup() {
  // Initialize serial communication and OLED display
  Serial.begin(9600);

  mlx.begin();

  oled.begin();

  pox.begin();

  // // Initialize the pulse oximeter sensor
  // Serial.println("Initializing pulse oximeter...");
  // if (!pox.begin()) {
  //   Serial.println("Failed to initialize pulse oximeter!");
  //   for (;;);  // Stop the program if initialization fails
  // }

  // // // Initialize the MLX90614 temperature sensor
  // if (!mlx.begin()) {
  //   Serial.println("Failed to initialize MLX90614 temperature sensor!");
  //   for (;;);  // Stop the program if initialization fails
  // }
}

void loop() {
  // Update the pulse oximeter and check if it's time to report SPO2 values
  pox.update();
  static uint32_t tsLastReport = 0;
  if (millis() - tsLastReport > REPORTING_PERIOD_MS) {
    // Print the SPO2 values to the serial monitor and OLED display
    Serial.print("Heart BPM: ");
    Serial.print(pox.getHeartRate());
    Serial.print(" ----- Oxygen Percent: ");
    Serial.println(pox.getSpO2());
    oled.clearDisplay();
    oled.setCursor(0, 0);
    oled.print("BPM: ");
    oled.print(pox.getHeartRate());
      oled.setCursor(0, 15);
    oled.print("SPO2: ");
    oled.print(pox.getSpO2());

    // Read and print the temperature from the MLX90614 sensor
    float temp = mlx.getObjectTempCelsius();
    Serial.print(" ----- Temperature: ");
    Serial.println(temp);
        oled.setCursor(0, 30);
    oled.print("TEMP: ");
    oled.print((temp));

    oled.display();
    tsLastReport = millis();  // reset the timer
  }

  
}

I would appreciate the help ,Thanks in advance.

You could do for all of us what all of us would have to if you don't and say a bit more:

Are these all I2C devices? With no address conflicts?

Do you have links to the make and model of these sensors you could share?

Could you post the sketches that make each work alone, please?

A schematic, even hand drawn take a picture and post it, actually the easiest and best might help, too - be sure to show all the connections and in particular how power is supplied to everything.

Have you tried leaving off the OLED for the moment, and just using the two sensors and the serial monitor?

And so forth. This should take you no time at all, if you had the schematic already, which you should have. Sometimes putting your case together will help you spot something you've overlooked. Mostly just efficiency, yes googling would be easy but there's so much good stuff on Netflix and all. :wink:

TIA

a7

-yes all are I2C devices with no address conflicts
-max30100 is an RCWL-0530, but the mlx90614 has nothing on it
Untitled

  • yes tried disconnecting the OLED, same thing
  • I also changed the I2C_BUS_SPEED for the max30100 from 400000UL to 100000UL, then the mlx90614 reading is correct but the max30100 is wrong!

Yeah, I would watch Netflix too.

any help in solving the issue please

One of the devices, forget which one after 45 seconds, has a max clock speed of 100 kHz, so set that and forget about it.

Leave the OLED out of the picture for now, as it can be a separate problem after the two sensors are functioning together.

I see no address conflicts, and though it is not clear, the presence or absence of additional pull-up resistors on the bus shouldn't be a problem.

Except. This article claims the MAC30100 just won't work at all

pull up resistor problem

So, has that sensor all by itself produced plausible results?

I assume you have the 5 volt version of the other sensor.

I see from your wiring diagram that you are powering everything off the 5 volt pin on the UNO. This is an UNO no no… unless you are drawing very little current. So that's something I haven't time for just now, but might be a clue for you or another forum member.

It is advised to have an external 5 volt power supply for all you attached devices. This supply can power the UNO as well, or the UNO can just enjoy the USB power.

That's all I have on this, just some ideas.

You did not post the sketches that make

  • one sensor work (only code for that)

  • the other sensor work (on,y code for that)

  • your attempt to make both sensors work

It would be convenient to put us on your page by posting those three, two that work, the one that sorta but doesn't work for both.

a7

  • For your first point: as I mentioned I changed the clock speed of the max30100 from 400 to 100kHz ( as it is the only one that has clock speed in its library), after doing that the mlx906214 started working ok but the max301200 didn't read correctly ( the opposite situation of the original try)

  • As for the address conflict: I ran an I2C address scanner, and there were no conflicts in the addresses.

  • I fixed the problem of the spo2 max30100 sensor from the beginning by removing the resistors as mentioned in the like you sent (spo2 is working fine )

  • As for power I connected the sensors to an external power supply separate from the UNO, but still no luck

  • As for the sketches for each individual sensor, in order for the two sensors to work simultaneously their sketches were altered

Which is why…. anyone else who is going to help you will want to see all three sketches.

Good luck!

a7

Sketch for the mlx90614 with oled:


#include <DFRobot_MLX90614.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
//sda A4 scl a5
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
 
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET     -1 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

DFRobot_MLX90614_I2C sensor;   // instantiate an object to drive our sensor

void setup()
{
  Serial.begin(115200);
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  delay(2000);
  display.clearDisplay();
  display.setTextColor(WHITE);
  // initialize the sensor
  while( NO_ERR != sensor.begin() ){
    Serial.println("Communication with device failed, please check connection");
    delay(3000);
  }
  Serial.println("Begin ok!");

  /**
   * adjust sensor sleep mode
   * mode select to enter or exit sleep mode, it's enter sleep mode by default
   *      true is to enter sleep mode
   *      false is to exit sleep mode (automatically exit sleep mode after power down and restart)
   */
  sensor.enterSleepMode();
  delay(50);
  sensor.enterSleepMode(false);
  delay(200);

sensor.setEmissivityCorrectionCoefficient(1);
float ambientTemp = sensor.getAmbientTempCelsius();
float objectTemp = sensor.getObjectTempCelsius();
 
}


void loop()
{

 
  /**
   * get ambient temperature, unit is Celsius
   * return value range: -40 C ~ 85 C
   */
  float ambientTemp = sensor.getAmbientTempCelsius();

  /**
   * get temperature of object 1, unit is Celsius
   * return value range: -40 C ~ 85 C
   */
       
  float objectTemp = sensor.getObjectTempCelsius();

  // print measured data in Celsius
  Serial.print("Ambient celsius : "); Serial.print(ambientTemp); Serial.println(" C");
  Serial.print("Object celsius : ");  Serial.print(objectTemp);  Serial.println(" C");
display.clearDisplay();

  // display R G B Values
  display.setTextSize(2);
  display.setCursor(0,0);
  display.print("Temp:");


  display.setTextSize(3);
  display.setCursor(0, 28);
  display.print(objectTemp);
    


  display.setTextSize(1);
  display.setCursor(0, 56);
  display.print("electroniclinic.com");
 
display.display(); 
  // print measured data in Fahrenheit
  Serial.print("Ambient fahrenheit : "); Serial.print(ambientTemp*9/5 + 32); Serial.println(" F");
  Serial.print("Object fahrenheit : ");  Serial.print(objectTemp*9/5 + 32);  Serial.println(" F");

delay(1000);
}

Sketch for the max30100 with oled:

#include <Wire.h>
#include "MAX30100_PulseOximeter.h"

#include "Wire.h"
#include "Adafruit_GFX.h"
#include "OakOLED.h"
#define REPORTING_PERIOD_MS     1000
OakOLED oled;

PulseOximeter pox;

uint32_t tsLastReport = 0;

const unsigned char bitmap [] PROGMEM=
{
  0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x18, 0x00, 0x0f, 0xe0, 0x7f, 0x00, 0x3f, 0xf9, 0xff, 0xc0, 
  0x7f, 0xf9, 0xff, 0xc0, 0x7f, 0xff, 0xff, 0xe0, 0x7f, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xff, 0xf0, 
  0xff, 0xf7, 0xff, 0xf0, 0xff, 0xe7, 0xff, 0xf0, 0xff, 0xe7, 0xff, 0xf0, 0x7f, 0xdb, 0xff, 0xe0, 
  0x7f, 0x9b, 0xff, 0xe0, 0x00, 0x3b, 0xc0, 0x00, 0x3f, 0xf9, 0x9f, 0xc0, 0x3f, 0xfd, 0xbf, 0xc0, 
  0x1f, 0xfd, 0xbf, 0x80, 0x0f, 0xfd, 0x7f, 0x00, 0x07, 0xfe, 0x7e, 0x00, 0x03, 0xfe, 0xfc, 0x00, 
  0x01, 0xff, 0xf8, 0x00, 0x00, 0xff, 0xf0, 0x00, 0x00, 0x7f, 0xe0, 0x00, 0x00, 0x3f, 0xc0, 0x00, 
  0x00, 0x0f, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

void onBeatDetected()
{
    Serial.println("Beat!");
    oled.drawBitmap( 60, 20, bitmap, 28, 28, 1);
    oled.display();
}

void setup()
{
    Serial.begin(9600);
    Serial.print("Initializing pulse oximeter..");
    
    oled.begin();
    oled.clearDisplay();
    oled.setTextSize(1);
    oled.setTextColor(1);
    oled.setCursor(0, 0);

  oled.println("Initializing pulse oximeter..");
  oled.display();


    if (!pox.begin()) {
        Serial.println("FAILED");
        oled.clearDisplay();
        oled.setTextSize(1);
        oled.setTextColor(1);
        oled.setCursor(0, 0);
        oled.println("FAILED");
        oled.display();
        for(;;);
    } else {
        oled.clearDisplay();
        oled.setTextSize(1);
        oled.setTextColor(1);
        oled.setCursor(0, 0);
        oled.println("SUCCESS");
        oled.display();
        Serial.println("SUCCESS");
    }
    pox.setOnBeatDetectedCallback(onBeatDetected);
}

void loop()
{
    pox.update();

    if (millis() - tsLastReport > REPORTING_PERIOD_MS) {
        Serial.print("Heart BPM:");
        Serial.print(pox.getHeartRate());
        Serial.print("-----");
        Serial.print("Oxygen Percent:");
        Serial.print(pox.getSpO2());
        Serial.println("\n");
        oled.clearDisplay();
        oled.setTextSize(1);
        oled.setTextColor(1);
        oled.setCursor(0,16);
        oled.println(pox.getHeartRate());    
     
        oled.setTextSize(1);
        oled.setTextColor(1);
        oled.setCursor(0, 0);
        oled.println("Heart BPM");
      
        oled.setTextSize(1);
        oled.setTextColor(1);
        oled.setCursor(0, 30);
        oled.println("Spo2");
      
      
        oled.setTextSize(1);
        oled.setTextColor(1);
        oled.setCursor(0,45);
        oled.println(pox.getSpO2());
        oled.println("%");
        oled.display();
        tsLastReport = millis();
    }
}

sketch for the tow sensors together with the oled:

#include <Wire.h>
#include <MAX30100_PulseOximeter.h>
#include <DFRobot_MLX90614.h>
#include <OakOLED.h>

// OLED display and pulse oximeter objects
OakOLED oled;
PulseOximeter pox;
DFRobot_MLX90614_I2C mlx;

// Reporting period in milliseconds
#define REPORTING_PERIOD_MS 1000

void setup() {
  // Initialize serial communication and OLED display
  Serial.begin(9600);

  mlx.begin();

  oled.begin();

  pox.begin();

  // // Initialize the pulse oximeter sensor
  // Serial.println("Initializing pulse oximeter...");
  // if (!pox.begin()) {
  //   Serial.println("Failed to initialize pulse oximeter!");
  //   for (;;);  // Stop the program if initialization fails
  // }

  // // // Initialize the MLX90614 temperature sensor
  // if (!mlx.begin()) {
  //   Serial.println("Failed to initialize MLX90614 temperature sensor!");
  //   for (;;);  // Stop the program if initialization fails
  // }
}

void loop() {
  // Update the pulse oximeter and check if it's time to report SPO2 values
  pox.update();
  static uint32_t tsLastReport = 0;
  if (millis() - tsLastReport > REPORTING_PERIOD_MS) {
    // Print the SPO2 values to the serial monitor and OLED display
    Serial.print("Heart BPM: ");
    Serial.print(pox.getHeartRate());
    Serial.print(" ----- Oxygen Percent: ");
    Serial.println(pox.getSpO2());
    oled.clearDisplay();
    oled.setCursor(0, 0);
    oled.print("BPM: ");
    oled.print(pox.getHeartRate());
      oled.setCursor(0, 15);
    oled.print("SPO2: ");
    oled.print(pox.getSpO2());

    // Read and print the temperature from the MLX90614 sensor
    float temp = mlx.getObjectTempCelsius();
    Serial.print(" ----- Temperature: ");
    Serial.println(temp);
        oled.setCursor(0, 30);
    oled.print("TEMP: ");
    oled.print((temp));

    oled.display();
    tsLastReport = millis();  // reset the timer
  }

  
}

update:
after removing the OLED and changing the clock speed to 100000ul
Wire.set clock(100000)
the measurements outputted to the serial monitor are correct on both sensors, so the problem is when connecting the OLED to the Arduino
this is the code after removing the oled
any thoughts ..... ??

#include <Wire.h>
#include <MAX30100_PulseOximeter.h>
#include <DFRobot_MLX90614.h>
#include <OakOLED.h>

#define REPORTING_PERIOD_MS 1000 

OakOLED oled;
PulseOximeter pox;
DFRobot_MLX90614_I2C mlx;



void setup() 
{
  Serial.begin(9600);
  mlx.begin();
  oled.begin();
  pox.begin();
Wire.setClock(100000);     
}                      


void loop()
{
  pox.update();
  static uint32_t tsLastReport = 0;
  if (millis() - tsLastReport > REPORTING_PERIOD_MS) {
    Serial.print("Heart BPM: ");
    Serial.print(pox.getHeartRate());
    Serial.print(" ----- Oxygen Percent: ");
    Serial.println(pox.getSpO2());
    oled.clearDisplay();
    oled.setCursor(0, 0);
    oled.print("BPM: ");
   oled.print(pox.getHeartRate());
    oled.setCursor(0, 15);
    oled.print("SPO2: ");
    oled.print(pox.getSpO2());

    float temp = mlx.getObjectTempCelsius();
    float ambientTemp = mlx.getAmbientTempCelsius();
    Serial.print(" ----- Temperature: ");
    Serial.println(temp);
    oled.setCursor(0, 30);
    oled.print("TEMP: ");
    oled.println((temp));
 oled.print("ambientTemp: ");
 oled.print((ambientTemp));


    
    oled.display();
    tsLastReport = millis();  
  }

  
}


any help?

These are world wide fora, it is not uncommon to wait hours for response. A bump pleading for help might only be justified after a day or so.

It appears that the two working sketches, thanks for posting them, use two different oled libraries.

So we know one sensor gets along with library A, and the other gets along with library B.

You picked one for the combined sketch. As you must.

I don't see

this is the code after removing the oled

in #9. But I think a solution, maybe, but progress no matter what, would be to restructure your code so that

  • get one sensor's data
  • get the other sensor's data

and then

  • format and present the data on the OLED.

The OLED code should not be interleaved with the other uses of the I2C bus.

At the very least, move the I2C stuff so it is not interleaving. You could go further, which would might be a good idea in any case:

By isolating the OLED functionality, you have an easy way to try both libraries. Write your own functions, and put the gory details of dealing with a display in those.

So you might have three versions of a few functions. One set for testing, which would put the data on the serial monitor. And one set each for how the two libraries are used. Differences may well only amount to how the display object is instantiated.

Start with the least functionality you can get away with, until you find that one, or the other or both display libraries are happy.

This is what I woud do, as I have no idea why what you did failed to simply work. Ppl with Eagle eyes may spot something dumb in your combined code yet.

a7

#include <Wire.h>
#include <MAX30100_PulseOximeter.h>
#include <Adafruit_MLX90614.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>


#define REPORTING_PERIOD_MS 1000


uint32_t tsLastReport = 0;

Adafruit_MLX90614 mlx = Adafruit_MLX90614();
PulseOximeter pox;
Adafruit_SSD1306 oled;

void setup() 
{
Serial.begin(9600);
mlx.begin();
pox.begin();
oled.begin();
oled.clearDisplay();
   
}

void loop() 
{
  // oled.clearDisplay();
pox.update();
 if (millis() - tsLastReport > REPORTING_PERIOD_MS) 
 {
    Serial.print("Heart rate = ");Serial.print(pox.getHeartRate());Serial.print(" BPM");
    Serial.print("      SpO2 = ");Serial.print(pox.getSpO2());Serial.println(" %");
    Serial.print("Ambient = "); Serial.print(mlx.readAmbientTempC());Serial.print("c");
    Serial.print("           Object = "); Serial.print(mlx.readObjectTempC()); Serial.println("c");
    Serial.println();   

    oled.setTextColor(WHITE);             
    oled.setCursor(0,0);   
    oled.print("Object = "); oled.print(mlx.readObjectTempC()); oled.println("c");
    oled.print("SpO2 = ");oled.print(pox.getSpO2());oled.print(" %");   

oled.display();
oled.clearDisplay();
    tsLastReport = millis();          
}
   
}

this code will stop the max30100 from working and it won't read anything in the serial monitor:
Heart rate = 0.00 BPM SpO2 = 0 %
Ambient = 29.25c Object = 27.85c
but the mlx90614 works fine

when removing
oled.display();
oled.clearDisplay();
the sketch works fine and the values appear correct in the serial monitor, but of course, nothing displays on the oled

something to do with the oled.begin();

or could it be that the Arduino doesn't have enough F memory to handle two sensors and an oled display at the same time?

the sketch is using a bit more than half the memory:
Sketch uses 19660 bytes (60%) of program storage space. Maximum is 32256 bytes.
Global variables use 849 bytes (41%) of dynamic memory, leaving 1199 bytes for local variables. Maximum is 2048 bytes.

i faced the issue but my MAX30100 didnt respond only when i try to connect to iot cloud
and my oled screen, Ad8232,MLX90614 works perfectly
tell me Whether i can solve your issue

Hello @mhamat,
I had been facing the same issue for two weeks.
The problem is when using libraries for different I2C sensors, so the first thing you should check is whether sensor addresses in I2C lines have the same addresses, so you should change the address of one of them, if not you should check the I2C bus line speed in libraries, So all libraries of sensors you are using in your code should have same I2C bus line speed, if you edit library you would solve your problem.
thanks.
majd

hi @majdali .
for the i2c addresse, each device has a diffrent address i cheak it. as for the line speed how do you cheak it and change it ?
thanks

Hi @mhamat.
you should open the library.h, check it from the document/Arduino/libraries folder, and read the file.
if this does not work or there is no problem with the I2C bus line speed,
So to solve the problem you can add pox.begin after reading the other sensors's values,
and add "yourOtherSensor".begin after reading pox values and make sure to make code clean such as adding

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.