[solved] GoPiGo3 New Install on Trixie Ubuntu I’m sensing trouble here

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-periphery provides 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=0 for write, flags=I2C_M_RD for read) are missing, the kernel driver may misinterpret the buffer limits. [1, 2]
  • SMBus Handles Lengths Automatically: SMBus protocols (like smbus_read_byte_data or smbus_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 raw ioctl buffers 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, the I2C_RDWR ioctlenforces 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-i2c work correctly, you must format your I2C messages as a two-part sequence (Write then Read) and respect the adapter’s block limit.

Not my pay grade but Ubuntu is not in GoPiGo3 “supported”…

Easy workaround, it turns out:

  1. copy the official di_i2c.py from the site-packages to my local python utils folder “…/plib”
/home/ubuntu/.venv/gopigo3/lib/python3.14/site-packages/di_i2c.py  ~/LyricalDave/plib
  1. Edit to use smbus instead of periphery
# https://www.dexterindustries.com
#
# Copyright (c) 2019 Dexter Industries
# Released under the MIT license (http://choosealicense.com/licenses/mit/).
# For more information see https://github.com/DexterInd/DI_Sensors/blob/master/LICENSE.md
#
# Python I2C drivers

import time
import threading
import di_mutex

print("Using local di_i2c.py")

__version__ = "1.3.2"

# Enabling one of the communication libraries
# This is not meant to change on a regular basis
# If Periphery doesn't work for you, uncomment either pigpio or smbus
#RPI_1_Module = "pigpio"
RPI_1_Module = "smbus"                     # Make this the default I2C bus, comment out periphery
# RPI_1_Module = "periphery"
...
  1. Put my plib/ at the front of the python path
    (simplistic example - no error handling)
import sys
sys.path.insert(1,"/home/ubuntu/LyricalDave/plib/")
import easygopigo3

egpg = easygopigo3.EasyGoPiGo3(use_mutex=True)
egpg.ds = egpg.init_distance_sensor()  # HW I2C
reading = egpg.ds.read_mm()
print(f"initDistanceSensor: reading: {reading}")