One of the quickest way to add peripherals to the Raspberry Pi is by using the I2C bus. There are countless number of vendors and products that are available. And with the addition of the Qwiic Connect System it literally becomes a snap to add devices.
I have been using I2C the on most of my Raspberry Pi and Arduino projects for quite some time. But when I recently rewrote my I2C code for my chicken coop project I started to noice a number of Remote I/O errors.
At first I assumed that the Qwiic Shim wasn’t quite connected securely. But that was easy to verify and I went as far as soldering the shim to the Pi expansion pins.
Then I was concerned that maybe the Qwiic Button devices were faulty. But I attached them to one of my older Ardinuo based projects and they worked fine.
I2C can be a tricky protocol and it helps to understand a little bit about how the bus works.
After a but more hardware debugging, including an attempt to impedance match the bus, it occurred to me that that maybe the Raspberry Pi was running the I2C bus a bit too fast for some of the devices.
Digging into the documentation for the Raspberry Pi SoC (System on Chip), I found the documentation for the Broadcom BCM2835 Peripherals. If you look at the section about the clock divider register (CDIV). It specifies the clock speed of the I2C peripherals has a default value that results in a 100 kHz I2C clock frequency. Maybe I could slow that down a bit, after all I am not doing large amounts of data transfer, quite the opposite.
I discover that it was quite easy to adjust this by setting the i2c_arm_baudrate
value in the config.txt
file.
Here is how you do it. Open the config file with a text editor.
sudo nano /boot/config.txt
then find the line containing
dtparam=i2c_arm=on
and somewhere, preferably after it add the following “i2c_arm_baudrate=xxxx
” where xxxx is the speed you wish to try. You should end up with something like the following.
Then save the file, reboot and it the new speed should take effect. In the above case I slowed down the clock to 50Mhz, half the original speed.
And just like that the Remote I/O errors disappeared.
Note that this technique is different than clock stretching. While there seems to be some issue with BCM2835 used in the Raspberry Pi missing the clock stretching request, we are bypassing that completely. I am simply slowing the clock down to where I am not seeing errors anymore.
I found this bug frustrating and I hope this technique will be helpful to other developers.