Problems with I2C link to SRF08 rangefinder

25 Jun 2010

Reading from the ultrasonic rangefinder is like reading from serial memory - an internal memory address needs to be sent followed by a repeat start. I assumed the following lines would do it:

        cmd[0] = 0x02;                      // Set pointer to first echo

        sonar.write(addr, cmd, 1, 1);   // send address of data register       
        sonar.read(addr, echo, 2);      // read two-byte echo result

It doesn't work though and I'm not sure why...Resorting to the new low-level functions does work:

        sonar.start();                    // Start condition
        sonar.write(addr);              // Address write
        sonar.write(0x02);             // First echo register
        sonar.start();                    // Repeated start
        sonar.write(addr+1);          // Address read
        echo[0] = sonar.read(I2C::ACK);     // Read MSB, with ACK
        echo[1] = sonar.read(I2C::NoACK); // Read LSB, no ACK
        sonar.stop();                     // Stop condition

Any ideas?

 

26 Jun 2010

I'm not sure why this doesn't work, but I am wondering if there is a problem with the slave holding the clock down between the write and the read, and so that there isn't enough delay between them. Try a small wait() between the .write() and the .read(), and see if that works?

26 Jun 2010

Just tried a delay between the write and read: makes no difference unfortunately...

 

26 Jun 2010

Just a thought...there should be no stop bit sent at the end of the first write. When the repeat start flag is set, does this suppress the stop bit before sending the repeat start bit?

 

26 Jun 2010

That's basically what the "repeated = true" parameter does - supress transmission of the stop bit.

26 Jun 2010

Hmm..the response to a question on the faq for the SFR08 suggested that the master might not be responding to the clock hold condition from the slave, but I assume that sort of thing is taken care of by the MCU chip hardware...

27 Jun 2010

I have a similar problem with a PCF8575

in earlier libraries (< 23) i get a result with

i2c.read(0x40,data40i,2); or /*    i2c.read(0x40,data40i,2,false);

normaly it must gave me a 255 for data40i[0] and 137 for data40i[1];

now i get 255 for data40i[0] and 0 for data40i[1]

the lower 8 bit are absolutly correct. The bits changed as want. the upper

 

when i write

i2c.start();
i2c.write(0x42);            // Address 0xC0 read
data40i[0] = i2c.read(I2C::ACK);    // Read lower 8 bits, with ACK
data40i[1] = i2c.read(I2C::ACK);        // Read higher 8 bits, with ACK as philips told  in its datasheet
i2c.stop();                // Stop condition

data40i[0]=data40[1]= 192

whats wrong or how can i downgrade the library ?

Thanks

27 Jun 2010

Correction,

when i  write

i2c.start();
i2c.write(0x41);            // Address 0xC0 read                                         <-- My mistake read is address +1
data40i[0] = i2c.read(I2C::ACK);    // Read lower 8 bits, with ACK
data40i[1] = i2c.read(I2C::ACK);        // Read higher 8 bits, with ACK as philips told  in its datasheet
i2c.stop();                // Stop condition

 

i get the expected result.

28 Jun 2010

The mbed I2C block is supposed to respond to the slave holding the clock down. I will investigate.

07 Jul 2010

OK - I now have an SFR08 device, and I have managed to replicate this. The data on the bus actually looks correct, so it looks like it is something to do with the handling of the state machine of the I2C block.

07 Jul 2010

Confirmed as a bug - will have this fixed in the next release (hopefully very soon).

07 Jul 2010

Great news! That'll shorten my program source code...

08 Jul 2010

Version 24 of the library just went live, which should fix this.

08 Jul 2010

The bug is fixed, so this code:

        sonar.start();                                  // Start condition
        sonar.write(addr);                           // Address write
        sonar.write(0x02);                          // First echo register
        sonar.start();                                 // Repeated start
        sonar.write(addr+1);                       // Address read
        echo[0] = sonar.read(I2C::ACK);     // Read MSB, with ACK
        echo[1] = sonar.read(I2C::NoACK); // Read LSB, no ACK
        sonar.stop();                                 // Stop condition

reduces to:

        cmd[0] = 0x02;                            // Address of first echo
        sonar.write(addr, cmd, 1, 1);         // Send address of first echo      
        sonar.read(addr, echo, 2);            // Read two-byte echo result

Thanks for that!