0

I'm using a Raspberry Pi 4B to read pressure sensors via I2C, with Python 3.7.3 and the SMBus library. I ran into the Broadcom clock-stretching bug, so I switched to software-based I2C (brief description here: https://github.com/fivdi/i2c-bus/blob/master/doc/raspberry-pi-software-i2c.md). This helped me significantly; the reads on hardware-based I2C were highly oscillatory and unreliable.

Unfortunately, it introduced a new problem: the clock speed. The sensors only support a max of 100 kHz, and the Pi is running at ~140 kHz, as measured on a scope. The problem presents as the bus getting stuck intermittently, with the clock and data lines getting pulled low and unable to bounce back to high until the sensor is physically disconnected from the Pi. I think the stuck bus is due to the clock speed being too fast (the sensors work very well with NI LabVIEW, which uses a clock speed of 100 kHz), so that's what I'm trying to address.

I don't think software I2C clock speed is controlled in the same way as hardware, but I tried several settings nonetheless. The main things I tried:

  • Adding dtparam=i2c_arm=on,i2c_arm_baudrate=100000 in config.txt
  • sudo modprobe i2c_bcm2708 baudrate=100000
  • Creating a .conf file in /etc/modprobe.d/ with the content options i2c_bcm2708 baudrate=100000
  • Editing /etc/modules to contain: i2c-bcm2708 baudrate=400000 i2c-dev

None of these had any effect on the clock speed. Is there a special way to control the clock speed for software-based I2C?

In case it's helpful, I also looked at vcgencmd measure_clock arm while the Pi is at rest, is reading sensors successfully, and has the stuck bus. These are different values than the scope readings for clock frequency, so I'm not quite sure how to interpret them, but they certainly show a difference:

  • Idling: ~600,000,000
  • Successfully reading: ~700,000,000-800,000,000
  • Stuck bus: ~1,500,000,000

If I can't fix the clock speed, some other ideas I've had which I've briefly looked into are:

  • Try using the GPCLK functionality of one of the other GPIO pins--although figuring out how to set those pins to be clocks, let alone editing their specific frequency, seems to be quite challenging
  • Look into headers for converting SPI to I2C, and use SPI functionality on the Pi
  • Switch from Pi to an alternative platform

I'd welcome other options to investigate as well.

1 Answer 1

2

The software I2C bus settings are documented in /boot/overlays/README.

Name:   i2c-gpio
Info:   Adds support for software i2c controller on gpio pins
Load:   dtoverlay=i2c-gpio,<param>=<val>
Params: i2c_gpio_sda            GPIO used for I2C data (default "23")

        i2c_gpio_scl            GPIO used for I2C clock (default "24")

        i2c_gpio_delay_us       Clock delay in microseconds
                                (default "2" = ~100kHz)

        bus                     Set to a unique, non-zero value if wanting
                                multiple i2c-gpio busses. If set, will be used
                                as the preferred bus number (/dev/i2c-<n>). If
                                not set, the default value is 0, but the bus
                                number will be dynamically assigned - probably
                                3.

I suggest you try with an i2c_gpio_delay_us of 3.

1
  • 1
    Thank you so much! This has solved my problem. My delays vs clock speed were: 3 us --> 105 kHz, 4 us --> 85 kHz, 5 us --> 75 kHz. This is exactly what I needed, thanks! Jan 5, 2022 at 17:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.