Raspberry Pi I2C Slave Read (clock stretching) Problem

Raspberry Pi I2C Slave Read (clock stretching) Problem

Note: If you have a second rev Raspberry Pi, the I2C is on port 1 not 0 as shown in this tutorial

Some slower I2C devices use a method called clock stretching to allow it to get ready to send the data back to the requesting master I2C device (i.e. the Raspberry Pi).  Although the Raspberry Pi hardware can support this clock stretching feature, it seems that the current I2C drivers don't currently support it.

If the slave device can't respond fast enough, it seems that the Raspberry Pi sends an I2C Stop command. This is then received by the slave device which does as it is told and stops. So no data is received.

In the following image an I2C read command is sent to a slave at address 0x28. Zooming in to Image 2 shows what happens more clearly. The request is received by the slave, which acknowledges the command, but before it can send any data, a Stop command is received.

This is the command

i2cget -y 0 0x28 0x01 b

Image 1 - I2C Read request fails

Raspberry Pi I2C slave read error

Image 2 - I2C Read request failure (zoom into details showing Stop command)

Raspberry Pi I2C slave read error


How to fix it

Well, there is no real cure until the I2C drivers are updated to fully support clock stretching.

However, there is a hack that can be done to effectively slow down the clock speed for slow slave devices. This gives the device more time to send the data and avoid the Stop command being sent.

Details of this hack can be found and downloaded from the byvac website http://doc.byvac.com/index.php5?title=RPI_I2C

Unfortunately, the code as it stands didn't work for the device i was testing. The I2C bus needed slowing down a little bit more than the standard code. Fortunately this is easy to do. I modified the code to create two small programs, one slows the I2C bus down and one sets it back to normal.

i2c_slow Run this to slow down the I2C bus speed
sudo ./i2c_slow
i2c_fast Run this to set the I2C bus speed back to normal
sudo ./i2c_fast

These two programs can be downloaded in file rpi_i2c.zip. Download the zip file and extract the two programs. Copy these to the Raspberry Pi. We have included the byvac program in this download so you can modify the code if required.

You can download the zip file on your Raspberry Pi if it is connected to the internet.

wget http://www.hobbytronics.co.uk/download/rpi_i2c.zip

Extract the files using

unzip rpi_i2c.zip

Then make the files executable with

chmod +x i2c_fast i2c_slow

The image below shows the same data request at the slower I2C speed. This time data is received (0x67)

Raspberry Pi I2C slave read error fix

Our complete request is thus

sudo ./i2c_slow
i2cget -y 0 0x28 0x01 b
sudo ./i2c_fast