I2C bus, recieve int -1 in Wire.read()

Hi everybody !

I’ve got some issues with one of my sensors : a MAX30100, which is a heart rate monitoring sensor.
It communicates with Arduino through I2C protocol.

We can access various register from 0x00 to …
I want to access the FIFO register, which stores Infrared and Red photo diode values.

First, i’ve tested the address with this code :

#include <Wire.h>


void setup()
{
  Wire.begin();

  Serial.begin(9600);
  Serial.println("\nI2C Scanner");
}


void loop()
{
  byte error, address;
  int nDevices;

  Serial.println("Scanning...");

  nDevices = 0;
  for(address = 0; address <= 127; address++ ) 
  {
    // The i2c_scanner uses the return value of
    // the Write.endTransmisstion to see if
    // a device did acknowledge to the address.
    Wire.beginTransmission(address);
    error = Wire.endTransmission();

    if (error == 0)
    {
      Serial.print("I2C device found at address 0x");
      if (address<16) 
        Serial.print("0");
      Serial.print(address,HEX);
      Serial.println(" !");

      nDevices++;
    }
    else if (error==4) 
    {
      Serial.print("Unknow error at address 0x");
      if (address<16) 
        Serial.print("0");
      Serial.println(address,HEX);
    }    
  }
  if (nDevices == 0)
    Serial.println("No I2C devices found\n");
  else
    Serial.println("done\n");

  delay(500);           // wait 8 seconds for next scan
}

It responds well, giving me the 0x57 address i’ve expected.
The write / read addresses in MAX30100 datasheet are 0xAE and 0xAF

0xAF = 0b10101111
0xAE = 0b10101110

And

0x57 = 0b1010111 so it’s great.

Then, i want to access the 0x00 = interrupt status in order to test if the connection is working.
Normally, the datasheet says that about the 0x00 register.

And that :

So bits 2-3-4 should be 0 and the only respond i get with this code :

# include <Wire.h>  // La bibliothèque Wire gère l'I2C


#define MODE_CONFIGURATION  (0x06)      //Définition des différentes adresse pour les modes utilisés
#define FIFO_DATA_REGISTER (0x05)  // Adresse du FIFO_DATA (là où sont stockées les données) 
#define WRITE_POINTER (0x02)       // adresse du registre FIFO WRITE POINTER 
#define READ_POINTER (0x04)         // Adresse du registre FIFO READ POINTER
#define INTERRUPT_STATUS (0x00)        // Adresse du registe Interrupt Status
#define MASK (0x02)                    // Masque pour le Bit HR_RDY 
#define MAX (0x57)                // Adresse du capteur en mode écriture

int Number_Of_Sample = 0;               // Nombre de samples disponibles dans la mémoire FIFO 
int tableau[16];            // Tableau dans lequel les donnée seront stockées
int write_pointer = 0;
int read_pointer = 0;



void setup(){          // Initialisation des ressources
 
 Serial.begin(9600);             // Initialisation Terminal Série
 Wire.begin();  
 pinMode(SDA, INPUT);
 pinMode(SCL, INPUT);// Initialisation I2C

}

void loop(){ 
 


 Wire.beginTransmission(0x57);// MAX30100 ID en mode READ
 Wire.write(0x00);
 Wire.endTransmission(false);
 Wire.beginTransmission(0x57);                 // lecture registre Interrupt status, INT doit passer en LOW si POWER_READY = 1   
 byte HR_RDY = Wire.read();
 Serial.println(HR_RDY);                  //La réponse doit être xx1xxxxx.
 Wire.endTransmission();              //restart

                 //STOP
 
 delay(1000);

is -1
Which is 255 in byte, which is 0b11111111

I’ve got several hypothesis with that :

  1. -1 is an error message and the communication with my sensors doesn’t works (buffer is empty)
  2. I2C bus uses to high voltage for my sensor :

But it doesn’t fit with the first code that returns 0x57…
Hardware side, i’ve placed my QFN on a PCB i made, the connections are good but my RED LED doesn’t blink when i test it with an ohm meter (between GND and RED_PWR, GND and VDD pins)

https://www.maximintegrated.com/en/products/analog/sensors-and-sensor-interface/MAX30100.html

Thanks a lot for your help !

The sketch is wrong. When there is nothing in the buffer, the Wire.read() returns -1, which is indeed an indication of an error.

Writing data : beginTransmission --- write,write,write --- endTransmission Reading data : requestFrom --- [available()] --- read,read,read / readBytes

Sorry, if that is cryptic, I mean that when writing data, there can be zero to many Wire.write() between Wire.beginTransmission() and Wire.endTransmission(). When reading data, all that is needed is Wire.requestFrom(). The function Wire.avaiable() can be used but also the return value of Wire.requestFrom() can be used, and to get the bytes either a few Wire.read() or a single Wire.readBytes() can be used.

 Wire.beginTransmission( 0x57);  // MAX30100 write
 Wire.write( 0x00);         // select register 0, status register
 Wire.endTransmission( false);   // repeated start

 int n = Wire.requestFrom( 0x57, 1);    // request a single byte.
 if( n != 1)           // not the amount received that was requested ?
 {
    Serial.println("Error, I2C bus or sensor error");
 }
 else
 {
    byte status = Wire.read();
    Serial.print("Received : 0x");
    Serial.println( status, HEX);
 }