What do I know? MR introduces a new install for Pi OS Trixie, so I just have to try the new install with Ubuntu Trixie required by ROS 2 Lyrical Luth for GoPiGo3 robot Dave’s latest reincarnation.
Seemed like everything was working for Dave, he was docking well and undocking to go out and play with URML. Then I wanted to try his rarely used distance sensor (Dave usually uses LIDAR).
Distance sensor worked on PiOS Trixie, but not Ubuntu Trixie. It reported “buffer overflow”
Managed to dig deep in the I2C sensor stack until I found the magic key in di_i2c.py
If periphery doesn’t work uncomment smbus
I haven’t the slightest what it means or does, or how to properly change it, but bringing the whole sensor stack local allowed me to change it so my test program reads the distance sensor.
Google says:
Instead of relying on clunky system commands or legacy tools like
smbus,
python-peripheryprovides a clean, consolidated API that wraps native Linux I2C device drivers.
Why the Difference Happens
- Raw I2C (
periphery) Requires Chaining: Raw I2C reads typically require two distinct messages within the same transfer: a write to set the register pointer, followed by a read. If the write message’s buffer is sized incorrectly, or the message flags (flags=0for write,flags=I2C_M_RDfor read) are missing, the kernel driver may misinterpret the buffer limits. [1, 2]- SMBus Handles Lengths Automatically: SMBus protocols (like
smbus_read_byte_dataorsmbus_read_i2c_block_data) dictate exactly how many bytes are written (usually a single command byte) and automatically handle repeated starts and stop conditions for the read phase. It doesn’t use rawioctlbuffers in the same way, shielding you from overflow errors. [1, 2, 3, 4]- Kernel Space Limits: When passing large buffers (e.g., block reads) via
periphery, theI2C_RDWRioctlenforces a strict block limit defined by your I2C adapter driver (often 32 or 256 bytes). Attempting to transfer more than this limit returns an overflow/I/O error. [1]How to Fix It
To make
periphery-i2cwork correctly, you must format your I2C messages as a two-part sequence (Write then Read) and respect the adapter’s block limit.