I2C Problem: ADDR_CLEAR_ERROR

I am running into a problem where i2c.read() is producing the “Timeout waiting for address flag to be cleared” error. I’m trying to use an Imp to run a GoPiGo board. The GoPiGo is a small robotics platform consisting of a motor controller / sensor board onto which is mounted a Raspberry Pi. The GoPiGo has an ATMega controller running on 5V and the RPi runs on 3.3V. Commands are passed over I2C with level converters (N-MOSFET and 10K pull-ups to 3.3V and 5V) on the GoPiGo. The RPi also has 1.8K pull-ups on the I2C lines. I’ve replaced the RPi with an Imp running on the 5V supplied by the GoPiGo and returning 3.3V for use by the level converters. i2c.write() calls appear to work without problem but i2c.read() consistently fails. I’ve tried this with and without additional external pull-ups on the Imp’s I2C lines (to replicate what the RPi has) with no change in behavior. What does this error message indicate?

You’ll get that error if the device address is wrong. Have you tried shifting it left by one bit as described on the i2c.read page?

How did you confirm that the writes are working ok?

Thanks for the reply. The listed address is x08 and I’m shifting this left by one. Anything else produces err -2 on write. The writes are working because the motor movement commands behave as expected however I do need to run the bus at 10KHz otherwise it appears to occasionally drop commands.

Could you attach some code?

Here is a short example. All GoPiGo commands are four bytes. The i2c.write() calls turn the motors on and then off, turn the right led on the board off and then on. The i2c.read() sends the four byte command to read the GoPiGo battery voltage and then read a two byte response. The i2c.writes() succeed - return 0 and the action is performed. The i2c.read() returns null with readerror returning -6.

`server.log("GPG Starting");

local gpgAddr = 0x08 << 1;

local gpg = hardware.i2c89;
gpg.configure(CLOCK_SPEED_10_KHZ);

// command both motors forward
local v = gpg.write(gpgAddr,"\\x69\\x00\\x00\\x00");
server.log(format("err = %d",v));

imp.sleep(3);

// command both motors stop
local v = gpg.write(gpgAddr,"\\x78\\x00\\x00\\x00");
server.log(format("err = %d",v));

// command right led off
v = gpg.write(gpgAddr,"\\x0c\\x05\\x00\\x00");
server.log(format("err = %d",v));

imp.sleep(1);

// command right led on
v = gpg.write(gpgAddr,"\\x0c\\x05\\x01\\x00");
server.log(format("err = %d",v));

// command read battery voltage
v = gpg.read(gpgAddr,"\\x76\\x00\\x00\\x00",2);
if (v == null) {
  server.log(format("null return %d",gpg.readerror()));
}
else {
  server.log(format("v = %x %x",v[0],v[1]));
}`

I have made some progress. It is my understanding that the Imp i2c.read() calls wraps a write operation together with a read. Since the GoPiGo side of this is apparently using the Arduino Wire library, which I believe does not do this, I decided to do the i2c.read() as a write followed by a read with an empty string. This code succeeds in reading the battery voltage.

local v = gpg.write(gpgAddr,"\x76\x00\x00\x00");
if (v != 0) server.log(format(“err = %d”,v));
imp.sleep(0.01);
v = gpg.read(gpgAddr,"",1);
if (v == null) {
server.log(format(“null return %d”,gpg.readerror()));
}
local val = v[0] << 8;

v = gpg.read(gpgAddr,"",1);
if (v == null) {
server.log(format(“null return %d”,gpg.readerror()));
}

val += v[0];

The read’s need to be done one byte at a time - trying to read two bytes at once produces one byte of the voltage followed by 0xff. Without the sleep there appears to be some probability of things getting out of phase (i.e. the 1st byte of voltage comes as the second byte and the next attempt produces the second byte of voltage as the first byte read).

Hmm, is the gopigo actually a software i2c slave implementation? Sounds like maybe it is…