Adventures in I2C: clock stretching on the Raspberry Pi

This is a bit complicated, technically, but I’ve been asked to document the issue just in case someone comes across it.

I was getting I2C read errors when using the new TE AmbiMate MS4 sensor board (review coming soon!) with the Raspberry Pi 4. I contacted TE about it and they asked me to try a Pi 3. So I did, and it worked absolutely fine.

It was an intermittent issue on the Pi 4 (everyone’s favourite sort of error!), and so I did some research and found some information on something called ‘clock stretching‘.

This apparently affects the Raspberry Pi and was documented in a lot of detail, back in 2013 by someone at Advamation. Here is that post.

Although I found evidence on the Raspberry Pi forums that it had been fixed on the Pi 4, this is apparently not the case as it was a Pi 4 I was getting the problem on.

I tried a good old-fashioned apt-get update and upgrade and tried it again. No joy.

I was pointed at this GitHub issue which implied that the problem still exists. It suggested adding a line to /boot/config.txt

dtoverlay=i2c-bcm2708

which forces the Pi to use the old I2C driver. This failed to work, in fact it made the problem worse because suddenly it wouldn’t read anything from the sensor. I reversed this.

I tried an rpi-update to get the latest firmware, just in case a fix had been implemented on a newer version. This again failed to work.

Eventually, after some searching around (good ol’ Google!) I came across this issue on GitHub which suggested that the problem was the speed at which I was trying to read the I2C bus. So, I added a config option to /boot/config.txt as follows to reduce the read speed from 100000 baud to 10000 baud:

dtparam=i2c_baudrate=10000

Miraculously, this worked and I received stable readings from all the sensors on the AmbiMate without the errors occurring.

I came across an alternative solution (which I haven’t tried). Apparently, the bug only affects hardware clock stretching. However, it is possible to use an alternate set of pins for I2C and use software clock stretching. This is documented on GitHub here. Here is the relevant bit:

Raspbian has a software I2C driver that can be enabled by adding the following line to /boot/config.txt:

dtoverlay=i2c-gpio,bus=3

This will create an I2C bus called /dev/i2c-3. SDA will be on GPIO23 and SCL will be on GPIO24 which are pins 16 and 18 on the GPIO header respectively.

I hope this is of some use to someone!

3 comments for “Adventures in I2C: clock stretching on the Raspberry Pi

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.