Using the Wire.readBytes()

Hello, this is not a question, this is a discussion about using .readBytes() from the Stream class with the Wire library. It started in a other topic.

The Stream.readBytes() can wait for new data to arrive, but the I2C bus uses packages of data and new data will never arrive.

New users might make a mistake with the number of bytes. If they ask too many bytes with Wire.readBytes(), then the timeout kicks in which is useless for the I2C bus.

The source code of Stream.readBytes() is here and the function timedRead() is here. Since the Stream class is at a higher level and not hardware related, its code is often (almost) the same on other platforms.

Test sketch with a bug to make the timeout appear:

#include <Wire.h>

byte buffer[20];

void setup() 
{
  Serial.begin( 115200);
  Serial.println( "Testing timeout with a bug in the code...");

  Wire.begin();
  Wire.setTimeout( 3000);         // default 1 second, let's make it 3 for fun.
  
  Wire.beginTransmission( 0x68);
  Wire.write( 0x00);
  Wire.endTransmission();

  unsigned long t1 = millis();

  // Better code could be:
  //   Wire.requestFrom( 0x68, 5);
  //   if( Wire.available() == 5)
  // Or shorter:
  //   if( Wire.requestFrom( 0x68, 5) == 5)
  // 

  Wire.requestFrom( 0x68, 5);
  if( Wire.available() > 0)      // I do not agree with this code line
  {
    Wire.readBytes( buffer, 6);  // use a bug, read 6 when there are only 5 !
  }

  unsigned long t2 = millis();
  
  unsigned long elapsedMillis = t2 - t1;
  Serial.print( "The code with the bug took ");
  Serial.print( (float) elapsedMillis / 1000.0);
  Serial.println( " seconds.");
}

void loop() {}

The sketch in Wokwi:

This problem is trivial: if the code has a bug then why worry about a unwanted timeout anyway ?
However, when the Wire.readBytes() would be used in the onReceive handler of a Target (Slave), then a timeout (caused by a bug in the sketch) is not harmless anymore.

So, the point is ???

Conclusion: the timeout saved the day for the bad programmer asking for too many bytes.

The point is that they are two different worlds, but it can be used.

Wire is a kind of Stream

class TwoWire : public Stream

ArduinoCore-avr/Wire.h at 24e6edd475c287cdafee0a4db2eb98927ce3cf58 · arduino/ArduinoCore-avr · GitHub

So not really two different worlds

Just that the API for underlying data stream and way of triggering the stream is different than say UART or a file on an SD card

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