Oled display and SD card logging causing interference on MAX30100

Hello, I am stuck in this problem where the data acquisition of the MAX30100 pulse oximeter is being interfered by the the Oled display. I tried removing the code for the display on "updateDisplay ()" and the sensor works fine (I've figured so, using serial debugging /Serial.print(data to be displayed). But when I added the code in updateDisplay, the data acquisition of the pulse oximeter stopped.

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

#define REPORTING_PERIOD_MS 2000 // Update display every 2 seconds
#define EMA_ALPHA 0.2 // Exponential moving average coefficient (adjust as needed)

U8X8_SSD1306_128X64_NONAME_SW_I2C u8x8(7, 6);
PulseOximeter pox;
uint32_t tsLastReport = 0;
float filteredBpm = 0.0;
float filteredSpO2 = 0.0;

void onBeatDetected() {
    Serial.println("Beat");
   
}

// Exponential moving average filter
float exponentialMovingAverage(float currentValue, float previousFilteredValue, float alpha) {
    return (alpha * currentValue) + ((1 - alpha) * previousFilteredValue);
}
void TCA9548A(uint8_t bus) {
    Wire.beginTransmission(0x70);  // TCA9548A address
    Wire.write(1 << bus);          // send byte to select bus
    Wire.endTransmission();
}
void setup() {
    Serial.begin(9600);
    Wire.begin();
    u8x8.begin();
    TCA9548A(0);

    if (!pox.begin()) {
        Serial.println("FAILED");
        while (1);
    } else {
        Serial.println("Pulse oximeter initialized successfully");
    }
    pox.setIRLedCurrent(MAX30100_LED_CURR_24MA);
    pox.setOnBeatDetectedCallback(onBeatDetected);
}

void loop() {
    pox.update();
    int rawBpm = pox.getHeartRate();
    int rawSpO2 = pox.getSpO2();

    // Apply EMA filtering
    filteredBpm = exponentialMovingAverage(rawBpm, filteredBpm, EMA_ALPHA);
    filteredSpO2 = exponentialMovingAverage(rawSpO2, filteredSpO2, EMA_ALPHA);

    if (millis() - tsLastReport > REPORTING_PERIOD_MS) {
        tsLastReport = millis();
        updateDisplay(static_cast<int>(filteredBpm), static_cast<int>(filteredSpO2));
    }
}

void updateDisplay(int Bpm, int SpO2) {
    u8x8.setFont(u8x8_font_chroma48medium8_r);
    u8x8.drawString(1, 2, "    HEALTH    ");
    u8x8.drawString(1, 3, "  MONITORING");
    u8x8.setCursor(0, 5);
    u8x8.print("BPM:");
    u8x8.setCursor(7, 5);
    u8x8.print(Bpm);
    u8x8.print("  ");
    u8x8.setCursor(0, 6);
    u8x8.print("SpO2:");
    u8x8.setCursor(7, 6);
    u8x8.print(SpO2);
    u8x8.print("% ");
    u8x8.display();
}

What is the address of the i2c display..?

Try adding the following line to the sketch to prevent the U8x8 library from altering the I2C clock frequency:

#include <Wire.h>
#define U8X8_DO_NOT_SET_WIRE_CLOCK //prevents U8x8 from altering Wire clock frequency
#include <U8x8lib.h>
#include "MAX30100_PulseOximeter.h"

Hello, the U8X8lib library doesn't provide a direct method to change the address of the OLED display, so I guess the address for the display is 0x3D for 124x64 dimension.

Thank you for the suggestion, I tried this one and it's still the same.

Sorry, I did not notice that you were using software I2C for the display.
That may be the problem. Testing on a Nano, it takes approximately 400mS to update the display using software I2C, as opposed to 38mS with the hardware I2C. Updating only the Bpm and SpO2 takes around 7mS or less with hardware I2c.

1 Like

Yaaay thanks David for this information. I switched to using Hardware I2C and it is now working. This lead me to conclude that the issue was indeed due to delay introduced by the oled when writing data.

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