Wire.endTransmission() returns error code 5 which is undocumented

Hello there,

Title says everything: I get an undocumented error code from Wire.endTransmission(), code 5. Here's the relevant code.

  // read FIFO pointers
  Wire.beginTransmission(max30105);
  Wire.write(0x04);
  error = Wire.endTransmission();
  nbytes = Wire.requestFrom(max30105, 3, true);  //read 3 bytes for the two FIFO pointers and overflow counter
  if (error != 0) {
    Serial.print("Could not read FIFO pointers, error code (if zero, number of bytes returned was wrong): ");
    Serial.println(error);
    return; // for some reason, the program crashes at this point
  }

Output:

Could not read FIFO pointers, error code (if zero, number of bytes returned was wrong): 5

The code is in an interrupt routine. I did not have problems before moving it to the interrupt routine, which I did because of other problems not to discuss here. Time between interrupts is 50 ms.

My board is an Adafruit ESP32 Feather. I use Arduino IDE version 1.8.15.

What does the error code mean and how can I possibly fix it?

Thanks for reading.

PS: Referencing this documentation page: Arduino - WireEndTransmission
It says corrections should be posted to the forum but the link does not work so that's another correction to make besides adding error code 5. :smiley:

Always post ALL your code. Snippets are useless.

The code is in an interrupt routine.

Never do serial I/O in an interrupt routine. That is for the main program to do.

The two wire interface operates off of interrupts. If you actually look at the twi code for the Arduino most functions wait for status that is set by the TWI interrupt. I think calling the wire functions from an interrupt is problematic. Not a 2 wire expert but I bet this is an issue, which is why it worked outside of interrupt code.

1 Like

https://github.com/espressif/arduino-esp32/blob/master/cores/esp32/esp32-hal-i2c.h

// External Wire.h equivalent error Codes
typedef enum {
    I2C_ERROR_OK=0,
    I2C_ERROR_DEV,
    I2C_ERROR_ACK,
    I2C_ERROR_TIMEOUT,
    I2C_ERROR_BUS,
    I2C_ERROR_BUSY,
    I2C_ERROR_MEMORY,
    I2C_ERROR_CONTINUE,
    I2C_ERROR_NO_BEGIN
} i2c_err_t;

I2C_ERROR_BUSY,

revert the ISR.

Thanks for your answers. Looks like the code snippet was sufficient after all.

By ISR, "interrupt service register" is meant? Of my sensor or of the ESP? Is it unrecommended or simply impossible to use I²C from an interrupt routine?

ISR = Interrupt Service Routine

The 2 wire code usually sets up for an operation and performs what we usually call a "busy wait" waiting for the ISR to complete. In other words, nothing is getting done while waiting, just spinning in a loop. This is not desired in an interrupt and, in fact, depending on processor hardware might even cause the system to hang if interrupts are disabled and the interrupt you are waiting on can't happen!

There might a way to get it to work (I'm not an ESP32 expert) but it could cause a lot of other issues, like affecting timers, communications, etc. Just not a good idea!

1 Like

Alright. Thanks for the explanations. I'll mark the comment as answer that has technically the answers to my questions.

@chemnitzscientist

Your codes of Post-1 are desired to have the following format:

// read FIFO pointers
  Wire.beginTransmission(max30105);
  Wire.write(0x04);
  byte error = Wire.endTransmission();
  if(error !=0)
  {
      Serial.print("I2C Bus communication problem.");
      while(1): //wait for ever
  }
  byte nbytes = Wire.requestFrom(max30105, 3, true);  //read 3 bytes for the two FIFO pointers and overflow counter
  while(Wire.available()>0)
  {
         myData[i] = Wire.read();
         Serial.println(myData[i], HEX);
         i++;
  }