MAX30100 sensor does not work within long code

I have MAX30100 oxygen/heartbeat sensor that works fine with a simple code like this one:

#include <Wire.h>
#include "MAX30100_PulseOximeter.h"
#include <LiquidCrystal.h>
 
#define REPORTING_PERIOD_MS     1000
#define rs 12 
#define en 11 
#define d4 9 
#define d5 8  
#define d6 7 
#define d7 6 
// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
 
PulseOximeter pox;  // Object of class oximeter
uint32_t tsLastReport = 0;
uint16_t oxm1=0;
uint16_t oxm2 = 0; 
void onBeatDetected()
{
    Serial.println("Beat!");
}
 
void setup()
{
    Serial.begin(38400);
    Serial.print("Initializing pulse oximeter..");
   // set up the LCD's number of columns and rows: 
  lcd.begin(16, 2);
  // Print a message to the LCD.
  lcd.print("Oximeter");
    // Initialize the PulseOximeter instance
    // Failures are generally due to an improper I2C wiring, missing power supply
    // or wrong target chip
    if (!pox.begin(1)) {
        Serial.println("FAILED");
        lcd.print("FAILED");
        for(;;);
    } else {
        Serial.println("SUCCESS");
        lcd.print("SUCCESS");
    }
     pox.setIRLedCurrent(MAX30100_LED_CURR_7_6MA);
 
    // Register a callback for the beat detection
    //pox.setOnBeatDetectedCallback(onBeatDetected);
}
 
void loop()
{
    // Make sure to call update as fast as possible
    pox.update();
    if (millis() - tsLastReport > REPORTING_PERIOD_MS) {
 oxm1 = pox.getHeartRate();
 oxm2 = pox.getSpO2();
        lcd.clear();
        lcd.setCursor(0,0);
        lcd.print("BPM: ");
        lcd.print(oxm1);
        //Serial.print("BPM: ");
		//Serial.println(oxm1);
		
        lcd.setCursor(0,1);
        lcd.print("SpO2: ");
        lcd.print(oxm2);
        lcd.print("%");
		//Serial.println("SpO2: ");
		//Serial.println(oxm2);
 
        tsLastReport = millis();
    }

// delay(70);
    
}

However, when I try to use this sensor within a more complex code that interacts with multiple inputs/outputs, the sensor code does not work properly and never updates the measurements of heartbeat/SP02. The sensor library includes debug functions which print raw/ processed measurements on the serial monitor. If I use the debug mode within the long sketch, nothing get printed.

After doing some research, I found that the minimum sampling rate for this sensor is 100Hz. while the long sketch takes 300ms to execute, which is about 3Hz.

I verified that this is the source of the problem by adding a delay to the simple code posted above, and found that the code does not read measurements if the delay is > 60ms.

I am looking for a solution to this problem, briefly insuring that the MAX30100 sensor function get called regularly within 50ms frame regardless of the lengthy code needed to handle other stuffs. As I understand, this can be handled using interrupts.

I tried to use the timer5 of Arduino mega 2560 using the following code:

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

#define REPORTING_PERIOD_MS     1000
#define rs 12 
#define en 11 
#define d4 9 
#define d5 8  
#define d6 7 
#define d7 6 
// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
 
PulseOximeter pox;  // Object of class oximeter
uint32_t tsLastReport = 0;
uint16_t oxm1=0;
uint16_t oxm2 = 0; 
void onBeatDetected()
{
    Serial.println("Beat!");
}
 
void setup()
{ 

 // intrrupt code

  cli();//stop interrupts

//set timer5 interrupt at 100Hz
  TCCR5A = 0;// set entire TCCR0A register to 0
  TCCR5B = 0;// same for TCCR0B
  TCNT5  = 0;//initialize counter value to 0
  // set compare match register for 100hz increments

  OCR5A = 155;//155;// = (16*10^6) / (100*64) - 1  set for 100 Hz
  // turn on CTC mode
  TCCR5B |= (1 << WGM52);
  TCCR5B |= (1 << CS52) | (1 << CS50);   // for 1024 prescale
  // enable timer compare interrupt
  TIMSK5 |= (1 << OCIE5A);

sei();//allow interrupts
// intrupt code end
  
    Serial.begin(38400);
    Serial.print("Initializing pulse oximeter..");
   // set up the LCD's number of columns and rows: 
  lcd.begin(16, 2);
  // Print a message to the LCD.
  lcd.print("Oximeter");
    // Initialize the PulseOximeter instance
    if (!pox.begin(1)) {
        Serial.println("FAILED");
        lcd.print("FAILED");
        for(;;);
    } else {
        Serial.println("SUCCESS");
        lcd.print("SUCCESS");
    }
     pox.setIRLedCurrent(MAX30100_LED_CURR_7_6MA);

}
 
void loop()
{
   
    
    if (millis() - tsLastReport > REPORTING_PERIOD_MS) {
 oxm1 = pox.getHeartRate();
 oxm2 = pox.getSpO2();
        lcd.clear();
        lcd.setCursor(0,0);
        lcd.print("BPM: ");
        lcd.print(oxm1);
        //Serial.print("BPM: ");
		//Serial.println(oxm1);
		
        lcd.setCursor(0,1);
        lcd.print("SpO2: ");
        lcd.print(oxm2);
        lcd.print("%");
		//Serial.println("SpO2: ");
		//Serial.println(oxm2);
 
        tsLastReport = millis();
    }
    delay(70);
}

ISR(TIMER5_COMPA_vect){
 // Make sure to call update as fast as possible
  pox.update();
}

Basically I call the function that updates sensor measurements within the interrupt routine.

However, this did not work and the code seems never entering the loop(), as screen never changes after showing “SUCCESS”.

Could you help me solving this issue? any recommendations to handle it?

Thank you

What is all the other stuff that takes ~300mS?

You may be able to structure loop so that it doesn't do everything on each iteration but does update the MAX30100 sensor frequently enough.

wildbill: What is all the other stuff that takes ~300mS?

You may be able to structure loop so that it doesn't do everything on each iteration but does update the MAX30100 sensor frequently enough.

Thank you for the suggestion. The other stuff are: LCD 8 analog read commands 6 digital read commands 2 PWM write commands serial communication processing

I forced the input/output commands to be executed every 500ms and now the loop() iteration takes only ~5 ms, however the MAX30100 sensor problem not resolved. Now the problem seems not due to the delay.

I tried to switch off the serial communication, analog reads, and PWM writes one by one to see if there is any conflict between them and the I2C communication of the sensor, and this also did not help.

I am not sure which pins the mega uses for i2c. On an Uno though they are analog pins. You might experiment and comment out all the analogReads.

wildbill: I am not sure which pins the mega uses for i2c. On an Uno though they are analog pins. You might experiment and comment out all the analogReads.

On Mega 2560, SDA and SCL pins are D20 & D21, which are connected to the oxygen sensor alone.