From 67182cd74c76530073ea09d5714f07844f67a541 Mon Sep 17 00:00:00 2001 From: Me Here Date: Sun, 31 May 2026 21:53:45 -0500 Subject: [PATCH] PM_G-1: fix I2C init on the pull-up-less Scroll Pack (busio+internal-pulls, bitbangio fallback) The Pico Scroll Pack has no external I2C pull-up resistors (Pimoroni's C++ uses the RP2040 internal pulls), so busio.I2C raised 'No pull up found on SDA or SCL' and the firmware crashed before the splash. _make_i2c() now pre-enables the internal pull-ups for busio and falls back to bitbangio (which uses them inherently). Pins GP4/GP5 were correct. Co-Authored-By: Claude Opus 4.8 (1M context) --- pico-scroll/app.py | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/pico-scroll/app.py b/pico-scroll/app.py index 0697abe..011ce17 100644 --- a/pico-scroll/app.py +++ b/pico-scroll/app.py @@ -279,9 +279,28 @@ LETTERS = { } # ============================== APP ============================== +def _make_i2c(): + # The Pico Scroll Pack has NO external I2C pull-up resistors - it relies on the RP2040's + # *internal* pull-ups (Pimoroni's C++ calls gpio_pull_up()). CircuitPython's busio.I2C + # refuses with "No pull up found on SDA or SCL" unless those internal pulls are on, so: + # 1) pre-enable the internal pull-ups on the pads, then try the fast hardware busio; + # 2) if that still won't init, fall back to bitbangio, which drives the lines using the + # internal pulls inherently (slower, but always works on a pull-up-less board). + try: + for p in (P_SDA, P_SCL): + d = digitalio.DigitalInOut(p); d.switch_to_input(pull=digitalio.Pull.UP); d.deinit() + except Exception: + pass + try: + return busio.I2C(P_SCL, P_SDA, frequency=400_000) + except Exception as e: + print("busio I2C unavailable (%s) - using bitbangio" % e) + import bitbangio + return bitbangio.I2C(P_SCL, P_SDA, frequency=400_000) + class App: def __init__(self): - self.i2c = busio.I2C(scl=P_SCL, sda=P_SDA, frequency=400_000) + self.i2c = _make_i2c() while not self.i2c.try_lock(): pass # the firmware owns the matrix bus for its lifetime self.mtx = Matrix(self.i2c) self.midi = usb_midi.ports[1] if (MIDI_ENABLED and usb_midi and len(usb_midi.ports) > 1) else None