Intermittent I2C Bus Hang & Data Corruption on MAX30102 (HW-605)

Intermittent I2C Bus Hang & Data Corruption on MAX30102 (HW-605)

Hi everyone,

I am experiencing a very strange issue with my MAX30102 (HW-605 module) and Arduino Uno.

The Problem:

  1. The Freeze: When I place my finger on the sensor, the I2C bus intermittently hangs/freezes, stopping all serial output.
  2. The "Fix" Made it Worse: When I try to solve this by adding external 6.8k ohm pull-up resistors to SDA and SCL, the data becomes corrupted. Instead of valid readings, I start getting garbage values or erratic jumps in the raw data, even before the bus eventually hangs.

Setup:

  • MCU: Arduino Uno (ATmega328P)
  • Sensor: MAX30102 (HW-605 breakout)
  • Power: 3.3V
  • Current Pull-ups: 6.8k ohms (External). Note: The module might have internal pull-ups, but adding external ones seems to degrade signal integrity instead of improving it.

Code

/*
  Optical Heart Rate Detection (PBA Algorithm) using the MAX30105 Breakout
  By: Nathan Seidle @ SparkFun Electronics
  Date: October 2nd, 2016
  https://github.com/sparkfun/MAX30105_Breakout

  This is a demo to show the reading of heart rate or beats per minute (BPM) using
  a Penpheral Beat Amplitude (PBA) algorithm.

  It is best to attach the sensor to your finger using a rubber band or other tightening
  device. Humans are generally bad at applying constant pressure to a thing. When you
  press your finger against the sensor it varies enough to cause the blood in your
  finger to flow differently which causes the sensor readings to go wonky.

  Hardware Connections (Breakoutboard to Arduino):
  -5V = 5V (3.3V is allowed)
  -GND = GND
  -SDA = A4 (or SDA)
  -SCL = A5 (or SCL)
  -INT = Not connected

  The MAX30105 Breakout can handle 5V or 3.3V I2C logic. We recommend powering the board with 5V
  but it will also run at 3.3V.
*/

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

#include "heartRate.h"

MAX30105 particleSensor;

const byte RATE_SIZE = 4; //Increase this for more averaging. 4 is good.
byte rates[RATE_SIZE]; //Array of heart rates
byte rateSpot = 0;
long lastBeat = 0; //Time at which the last beat occurred

float beatsPerMinute;
int beatAvg;

void setup()
{
  Serial.begin(9600);
  Serial.println("Initializing...");

  // Initialize sensor
  if (!particleSensor.begin(Wire, I2C_SPEED_FAST)) //Use default I2C port, 400kHz speed
  {
    Serial.println("MAX30105 was not found. Please check wiring/power. ");
    while (1);
  }
  Serial.println("Place your index finger on the sensor with steady pressure.");

  particleSensor.setup(); //Configure sensor with default settings
  particleSensor.setPulseAmplitudeRed(0x0A); //Turn Red LED to low to indicate sensor is running
  particleSensor.setPulseAmplitudeGreen(0); //Turn off Green LED
}

void loop()
{
  long irValue = particleSensor.getIR();

  if (checkForBeat(irValue) == true)
  {
    //We sensed a beat!
    long delta = millis() - lastBeat;
    lastBeat = millis();

    beatsPerMinute = 60 / (delta / 1000.0);

    if (beatsPerMinute < 255 && beatsPerMinute > 20)
    {
      rates[rateSpot++] = (byte)beatsPerMinute; //Store this reading in the array
      rateSpot %= RATE_SIZE; //Wrap variable

      //Take average of readings
      beatAvg = 0;
      for (byte x = 0 ; x < RATE_SIZE ; x++)
        beatAvg += rates[x];
      beatAvg /= RATE_SIZE;
    }
  }

  Serial.print("IR=");
  Serial.print(irValue);
  Serial.print(", BPM=");
  Serial.print(beatsPerMinute);
  Serial.print(", Avg BPM=");
  Serial.print(beatAvg);

  if (irValue < 50000)
    Serial.print(" No finger?");

  Serial.println();
}

Link to video/logs:

Thanks in advance!

You have got to be kidding.

A shaky, low res video of code? Less than a second's look at the sensor? And an AI summary?

If you really want help, do better.

2 Likes

Believe me, this is the first time I've experienced something like this, and instead of a short three-sentence post, I'd rather have AI prepare it; it will reach the reader much better than I can. and video sometimes conveys the message better than text for someone who thinks text alone is insufficient, otherwise I would have stated my problem in writing already

thank you for reply

This sounds odd:

6.8k should not cause a problem. To which power rail did you connect these ?
Anyway, post a link to the MAX30102 module you are using.
Also post a good quality picture of your setup. From the video it looks like you could be powering the module at 3.3v

Have you soldered the headers onto the MAX30102?

You are using code for the MAX10105 breakout which has voltage translators for the I2C bus, the board you have does not.
It's not likely to work with 5V I2C.

Sparkfun never sold a MAX30102 board.

Thank you for your interest. Yes, I am working with 3V3. I couldn't find a datasheet for the module I'm using. There was only a document I thought was the module's name, so I added it to the title. I tried to pull up I2C with 3V3. Maybe that's the problem. Someone wrote that the I2C line of the Arduino Uno operates at 5V.

Yes, I did it.

So would you recommend I get the max30105?

Because for now, I don't want to use a circuit with an extra signal converter :')

Are you just trying to measure heart rate?

1 Like

Depending on your budget, buy any module that is currently sold by Sparkfun or Adafruit that is supported by a library supplied by them.
This one looks very interesting:

You should be able to run it on 5V and the Processor at 3V3. The pull up resistors should go to the 3V3 not the 5V. This chart will help explain why, any voltage between the bars is undefined and can be either "1" or "0" or keep changing.

Originally I2C operated at 5V, but later specifications allowed for lower voltage levels, such as 2V, accommodating modern devices that often use 3.3V or even lower. This works because the output is not driven high but depends on external pull up devices. Example, open drain or collector configuration.

1 Like

yeah just for

So see post #11

I'll take a look at this

Yes, I had set it to 3v3 at first.

As I said it won't work with 5V and probably not at 3.3V either. It's just a bad design because there are no level shifters on the board like the MAX30105 has

1 Like

yeah

I found an article like this, and it says what you said:

If you're using a 5V-based microcontroller but the sensor breakout board pulls SDA and SCL up to 3.3V, you should ensure that its inputs are compatible with the 3.3V logic levels. An original Atmel ATMega328p considers anything above 3V as HIGH, so it might work well without level shifting hardware.

Since the MAX30102 I2C pins maximum ratings aren't bound to Vdd, a cheap option to avoid level shifting is to simply pull SDA and SCL up to 5V instead of 3.3V.

That really makes no sense. The MAX30102 is powered by 1.8V and it's logic levels are in reference to that voltage. You may be able to meet the Vih spec but the Vil is very iffy. As I said the MAX30105 did it the right and included the correct level shifters.