SSD1306 and MAX301012

Hi all,

Using a Arduino UNO with MAX30102 with an SSD1306 OLED display module to display pulse and SPO2.

Having an error, there isn't anything being displayed onto the screen, nor is the LED on the sensor coming on.

My code was heavily inspired by: Open Source Pulse Oximeter for COVID-19 - Arduino Project Hub

The MAX30102 sensor in the above link has only 4 pins, but mine has 7 as attached in the photograph.

The SSD1306 is working fine, I have used the library example to check it.

code:

#include <Wire.h>
#include "MAX30105.h"
#include "spo2_algorithm.h"
#include "Adafruit_SSD1306.h"


MAX30105 particleSensor;
Adafruit_SSD1306 oled;


#define SCREEN_WIDTH 128 // oled display width, in pixels
#define SCREEN_HEIGHT 64 // oled display height, in pixels

#define oled_RESET     -1 // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3C ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, oled_RESET);



#if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__)
//Arduino Uno doesn't have enough SRAM to store 50 samples of IR led data and red led data in 32-bit format
//To solve this problem, 16-bit MSB of the sampled data will be truncated. Samples become 16-bit data.
uint16_t irBuffer[50]; //infrared LED sensor data
uint16_t redBuffer[50];  //red LED sensor data
#else
uint32_t irBuffer[50]; //infrared LED sensor data
uint32_t redBuffer[50];  //red LED sensor data
#endif

int32_t spo2; //SPO2 value
int8_t validSPO2; //indicator to show if the SPO2 calculation is valid
int32_t heartRate; //heart rate value
int8_t validHeartRate; //indicator to show if the heart rate calculation is valid

void setup()
{
  Serial.begin(115200); // initialize serial communication at 115200 bits per second:

  oled.begin(display, 0x3C);
  oled.setFont(Arial14);

  // Initialize sensor
  if (!particleSensor.begin(Wire, I2C_SPEED_FAST)) //Use default I2C port, 400kHz speed
  {
    Serial.println(F("Sensor not found. Please check Power"));
    while (1);
  }

  particleSensor.setup(55, 4, 2, 200, 411, 4096); //Configure sensor with these settings
}

void loop()
{

  //read the first 50 samples, and determine the signal range
  for (byte i = 0 ; i < 50 ; i++)
  {
    while (particleSensor.available() == false) //do we have new data?
      particleSensor.check(); //Check the sensor for new data

    redBuffer[i] = particleSensor.getRed();
    irBuffer[i] = particleSensor.getIR();
    particleSensor.nextSample(); //We're finished with this sample so move to next sample
    Serial.print(F("red="));
    Serial.print(redBuffer[i], DEC);
    Serial.print(F(", ir="));
    Serial.println(irBuffer[i], DEC);
  }

  //calculate heart rate and SpO2 after first 50 samples (first 4 seconds of samples)
  maxim_heart_rate_and_oxygen_saturation(irBuffer, 50, redBuffer, &spo2, &validSPO2, &heartRate, &validHeartRate);

  //Continuously taking samples from MAX30102.  Heart rate and SpO2 are calculated every 1 second
  while (1)
  {
    //dumping the first 25 sets of samples in the memory and shift the last 25 sets of samples to the top
    for (byte i = 25; i < 50; i++)
    {
      redBuffer[i - 25] = redBuffer[i];
      irBuffer[i - 25] = irBuffer[i];
    }

    //take 25 sets of samples before calculating the heart rate.
    for (byte i = 25; i < 50; i++)
    {
      while (particleSensor.available() == false) //do we have new data?
        particleSensor.check(); //Check the sensor for new data

      redBuffer[i] = particleSensor.getRed();
      irBuffer[i] = particleSensor.getIR();
      particleSensor.nextSample(); //We're finished with this sample so move to next sample
      Serial.print(F("red="));
      Serial.print(redBuffer[i], DEC);
      Serial.print(F(", ir="));
      Serial.print(irBuffer[i], DEC);

      Serial.print(F(", HR="));
      Serial.print(heartRate, DEC);

      Serial.print(F(", HRvalid="));
      Serial.print(validHeartRate, DEC);

      Serial.print(F(", SPO2="));
      Serial.print(spo2, DEC);

      Serial.print(F(", SPO2Valid="));
      Serial.println(validSPO2, DEC);
      
    }

    //After gathering 25 new samples recalculate HR and SP02
    maxim_heart_rate_and_oxygen_saturation(irBuffer, 50, redBuffer, &spo2, &validSPO2, &heartRate, &validHeartRate);
    printToScreen();
  }
}

void printToScreen() {
  
  oled.clear();
  oled.setCursor(0,0);
  
  if(validSPO2 && validHeartRate) {
    
    oled.print(F("Pulse: ")); .println(heartRate, DEC);
    oled.print(F("Oxygen: ")); oled.println(spo2, DEC);
  } else {
    oled.print(F("Invalid reading, please try again."));
  }
}

Please advise.

Regards,
Taran

Well done posting code as a code-section and a picture
Thoough the picture tells not very much as the descriptive letters on the pins is not readable.

For this it is better to draw a schematic freehand. No fritzing please

Before mixing two hardware-moduls together in software you should test them both with a test-program that is well known for working reliable.

Did you lookup the datasheet of your MAX30105?

Did you do some basic tests with the MAX30105?

best regards Stefan

Dear Taran,

most likely your problem is related to a design flaw with this sensor board. This board connects the I2C interface to internal pullup 1.8V. Your Arduino board needs at least 2V for high level on the I2C. Hence it can not work.

There is a simple way to check if this is your problem: You load the I2C address scanner and check if the sensor appears at address 0x57. If not, you have found your problem.

There are ways to resolve the issue:

1st Option: This modification requires some manual skills on micro surgery: On the board you find three resistors 4.7k each. They are the pull-up resistors for SDA, SCL, INT. You can trace their common connect to the 1.8V on board regulator IC (this is the 3-pin chip just above the sensor chip. You must disconnect the resistors from this regulator by scratching the PCB board at this point (next to the upper most resistor). You might use a scalpel or any sharp tool for this. Once this is done you connect the common of the three resistors to pin 1 of the 3.3V regulator (this is the 6 pin IC at the most left position on the board, pin 1 is where the dot mark is on the chip). This is very tiny work. You will need a solder iron for SMD devices with very fine tip. Now your board is ready and will work.

2nd Option: You remove the three 4.7k resistors from the sensor board (the three resistors in one row left to the sensor chip. Now you connect tree external resistors from SDA, SCL, INT pad to VIN. Your board is ready and will work.

3rd Option: You buy a level shifter board and place it in between on your I2C bus and the sensor board. This will also work.

Selecting your suitable solution will depend on your soldering skills. Think carefully and don't destroy your sensor board. Good luck!

Hello George,

Many thanks for the advise and replies.

If the address appears at 0x57 but there is still no red LED what am I to do?

I tried the 2nd option and burnt out the sensor, I have ordered and received the second.

I will try the first method with a micro tip soldering iron and then circle back on the forum.

Surprising that so many sensors were produced with these design flaws.

Hope this gets resolved and I have a working project.

Thanks and regards,
Taran

Dear Taran,

The problem with those boards is that they are designed for low voltage operation with small battery. Hence they do not fail in general, but just in the combination with an Arduino. There are other boards on the market which do not need this modification.

Be careful on soldering. You should not touch the senor chip with the iron. It's really delicate work. If your experience on soldering is not enough, just break out the 3 resistors mechanically and go for option 2.

Myself got very frustrated with this board until I had found the workaround. Since modified the board is working fine.

Good luck.

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