I am going to use MCP23017 chips, and some of them will be cabled with a 1 meter max unshielded cable. I am expecting that certain transmissions may toss errors. So I want to tackle this problems by using the built in error detection of I2C, polling the inputs frequently (every 20ms or so) and by debouncing the received data in code by comparing the previous state to the current state of every input pin.
If you write bytes to an I2C slave with the Wire library. You can use the return value of Wire.endTransmission();
to test if the slave has acknowledged the message.
How does this work when you are requesting bytes using Wire.requestFrom( address, 3 );
for example. This function does return the amount of received bytes. Can we check this value with the value of the amount of bytes we requested?
I have read the TI document over how I2C works
The master will continue sending out the clockpulses, but will release the SDA line, so that the slave can transmit data. At the end of every byte of data, the master will send an ACK to the slave, letting the slave know that it is ready for more data. Once the master has received the number of bytes it is expecting, it will send a NACK, signaling to the slave to halt communications and release the bus. The master will follow this up with a STOP condition
So the master either ACKs or NACKs a read-in byte. Does the Wire library automatically make several attempts with reading? Oris there something in the Wire library which we can use to detect a failed read operation?
Is it perhaps so that the requestFrom()
function may return a different amount of bytes than you requested with which would indicate that atleast 1 read operation failed?
So could I attempt something like
doItAllAgain:
for(int i = 0 ; i < 5 ; i ++ )
{
Wire.beginTransmission( address ) ;
Wire.write( register ) ;
if( !Wire.endTransmission() ) break ; // if no error, break out of for loop
Serial.println(F("write operation failed");
}
Serial.println(F("write operation succes");
byte requestedBytes = 3 ;
byte returnedBytes = Wire.requestFrom( address, requestedBytes ) ;
if( requestedBytes != returnedBytes )
{
Serial.println(F("read operation failed");
goto doItAllAgain ;
}
else
{
Serial.println(F("read operation also succes");
byte byte1 = Wire.read() ;
byte byte2 = Wire.read() ;
byte byte3 = Wire.read() ;
}
requestFrom()
function returns when there is no deviceWire.requestFrom()
returns 0 when no device is connected. This means that this function does incorporate a check on NACK bits.