I2C register write/read

I'm looking for "best practices" when reading data from an I2C device.
I have sample code (for a BNO085 IMU) that does this:

    Wire.beginTransmission(CMPS14_ADDRESS);  // starts communication with CMPS14
    Wire.write(ANGLE_8);                     // Sends the register we wish to start reading from
    Wire.endTransmission();
    Wire.requestFrom(CMPS14_ADDRESS, 5); 
    while((Wire.available() < 5));
    angle8 = Wire.read();
...

My first concern is the while() loop...if there are not 5 bytes available, it's going to hang. Should I add a loop until I get to 5 bytes, and error out if I don't get there after some time?
I was thinking a specific number of cycles, but then I have to consider the implications of delay().

Also, the BNO returns 5 bytes of data for yaw, pitch, and roll, which I'm using. Then there's a string of bytes I don't need (mag/accel/gyro raw output). But I need the next byte, at register 0x1E. So would it be better to read 26 bytes and discard what I don't want, or would it be better to start a new beginTransmission(); write(0x1e); endTransmission() each cycle?

After doing some hex math in my head, it occurs to me that there's a gap between the last the last byte of IMU data (0x17) and the last byte I'm interested in, at 0x1E. So I should probably do two separate beginTransmission() calls, but I'm still interested in what the experts think is the "right way".

If you think its critical, you can do a delay loop inside the while, then break; when too many loops.

Wire.requestFrom() will return the number of received bytes. For some strange reason (I2C spec) this number will always equal the number of requested bytes. So you can be sure that Wire.available() will return the number of requested bytes, even if the data from Wire.read() may be something meaningless.

1 Like

Not always. If the bus is hung, you can get a timeout error and .requestFrom() will return 0.

1 Like

Please explain how to cure such a failure.

A request from a non-existing slave is aborted with zero bytes received. That makes sense and can be handled.

1 Like

It really depends on the cause. If some slave is holding SDA or SCL low, the arduino can not take control of the bus, which is the first thing it tries to do with a .requestFrom() call (unless there is a repeat start)

If there is noise on the bus, the arduino hardware can get confused and end up in the wrong state and possibly a dead-lock situation where both master and slave are waiting for the other. This can be solved (after the timeout) by resetting the hardware.

That's a weak excuse for design flaws in a project.

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