I2C Wire Library Master Slave Issue

I'm using ESP32 as I2C Master and Arduino Zero as I2C Slave. Erratic values are returned by Wire.available() when called outside the receiveEvent ISR. I want the code inside the ISR to be kept minimal but it seems the buffer holding the data is cleared when the ISR ends. Is this case?

Master Code:

#include <Wire.h>

void setup()
{
  Wire.begin(); // join i2c bus (address optional for master)
}

byte x = 0;

void loop()
{
  Wire.beginTransmission(4); // transmit to device #4
  Wire.write("x is ");        // sends five bytes
  Wire.write(x);              // sends one byte  
  Wire.endTransmission();    // stop transmitting

  x++;
  delay(5000);
}

Not working Slave code:

#include <Wire.h>

#define Serial SerialUSB
volatile bool incoming = false;
void setup()
{
  Wire.begin(4);                // join i2c bus with address #4
  Wire.onReceive(receiveEvent); // register event
  Serial.begin(9600);           // start serial for output
}

void loop()
{
  if (incoming) {
    while (1 < Wire.available()) // loop through all but the last
    {
      char c = Wire.read(); // receive byte as a character
      Serial.print(c);         // print the character
    }
    int x = Wire.read();    // receive byte as an integer
    Serial.println(x);         // print the integer
    incoming = false;
  }
}

void receiveEvent(int howMany)
{
  incoming = true;
}

Wire.available() is always returning 0 and Wire.read() is returning -1.

Working Slave code:

#include <Wire.h>

#define Serial SerialUSB
void setup()
{
  Wire.begin(4);                // join i2c bus with address #4
  Wire.onReceive(receiveEvent); // register event
  Serial.begin(115200);           // start serial for output
}

void loop()
{
  delay(100);
}

void receiveEvent(int howMany)
{
  while (1 < Wire.available()) // loop through all but the last
  {
    char c = Wire.read(); // receive byte as a character
    Serial.print(c);         // print the character
  }
  int x = Wire.read();    // receive byte as an integer
  Serial.println(x);         // print the integer
}

I've used ESP8266 as Master and Arduino UNO as Slave a while back and never experienced the problem.

If you look at the source code

// must be called in:
// slave rx event callback
// or after requestFrom(address, numBytes)
int TwoWire::available(void)
{
  return rxBufferLength - rxBufferIndex;
}

It would imply you only call this on the slave side inside receiveEvent().

And yes, calling that function does copy out the Rx buffer which allows more data to be received while processing received data

:slight_smile: Thanks.

Thanks to you as well. I have update my page that mentions this trick: Tricks that are (almost) allowed · Koepel/How-to-use-the-Arduino-Wire-library Wiki · GitHub