Convert rgb-matrix.sh to Python (with Pi 5 support)#400
Conversation
Modernized 1:1 port of rgb-matrix.sh: - Drop Python 2 handling (py2 is EOL) - Use adafruit_shell helpers (select_n/prompt/reconfig/run_raspi_config/ prompt_reboot) and shell.get_boot_config() for the boot config path - Idempotent isolcpus cmdline editing in pure Python Also bumps the pinned hzeller/rpi-rgb-led-matrix commit from 7a503494 (May 2025) to 4e326c1b (Jun 2026), the first commit with Raspberry Pi 5 (RP1) support. The previous pin builds a register-poke driver that cannot drive the matrix on a Pi 5. Not yet hardware-tested.
The pinned upstream commit replaced 'make build-python' with a scikit-build-core/Cython package, so build the bindings with 'pip install .' into the active environment. Add cmake to the apt prerequisites (required by scikit-build-core). Print the runtime --led-gpio-mapping matching the build choice and a note recommending --led-slowdown-gpio=5 to avoid flicker on solid white (worst case) on Pi 3/4; harmless on the Pi 5 RP1 backend.
There was a problem hiding this comment.
Pull request overview
This PR adds a Python-based installer (rgb-matrix.py) to replace/modernize the prior rgb-matrix.sh flow for installing and configuring hzeller/rpi-rgb-led-matrix, including Raspberry Pi 5 (RP1) support and Bookworm/Trixie-era boot/config handling.
Changes:
- Introduces a new
rgb-matrix.pyinstaller that ports the interactive flow (quality vs convenience, optional RTC, optional CPU isolation). - Pins
hzeller/rpi-rgb-led-matrixto a newer commit intended to support Pi 5 (RP1). - Switches the build/install step to
pip install .(scikit-build-core/Cython-style build) and prints runtime mapping guidance.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| print("Downloading prerequisites...") | ||
| # cmake is required by scikit-build-core, the build backend the upstream | ||
| # repo now uses for its Python bindings. | ||
| shell.run_command( | ||
| "apt-get install -y python3-dev python3-pillow cython3 python3-setuptools cmake" | ||
| ) |
There was a problem hiding this comment.
Done — added build-essential, python3-pip, and unzip to the apt prerequisites so the Cython/scikit-build pip install . and archive extraction work on a minimal image. Fixed in 854e0e1.
| # Change ownership to the user who called sudo. | ||
| sudo_user = os.environ.get("SUDO_USER") | ||
| if sudo_user: | ||
| shell.run_command(f"chown -R {sudo_user}:{sudo_user} {os.getcwd()}") | ||
|
|
There was a problem hiding this comment.
Done — now uses the caller's actual primary GID via SUDO_GID (chown -R user:GID), falling back to just the username if it's unset, instead of assuming the group name matches the username. Fixed in 854e0e1.
| print("The 'rgbmatrix' Python package is installed in:") | ||
| print(f" {sys.executable}") | ||
| print("Run your programs with that interpreter so 'import rgbmatrix' works.") | ||
| print("") |
There was a problem hiding this comment.
Done — reworded to 'installed for this interpreter' to avoid implying sys.executable is an install directory. Fixed in 854e0e1.
| """Idempotently set the isolcpus=N token in cmdline.txt. | ||
|
|
||
| cmdline.txt is a single line; strip any previously-added isolcpus token | ||
| first (re-running the installer, or moving the SD card to a Pi with a | ||
| different core count), then append the new one if a core is reserved. | ||
| """ |
There was a problem hiding this comment.
Done — updated the docstring to match the implementation: the installer manages the isolcpus= token and strips any existing entry (including user-managed ranges) before appending its own, keeping re-runs idempotent. Fixed in 854e0e1.
| shell.run_command( | ||
| f"curl -L {GITUSER}/{REPO}/archive/{COMMIT}.zip -o {REPO}-{COMMIT}.zip" | ||
| ) |
There was a problem hiding this comment.
Done — switched to curl -fL so a bad commit hash / GitHub 404 fails fast with a non-zero exit instead of saving an HTML page that breaks unzip downstream. Fixed in 854e0e1.
- Add build-essential, python3-pip, and unzip to apt prereqs so the Cython/scikit-build pip build and zip extraction work on a minimal image. - chown with the caller's actual primary GID (SUDO_GID) instead of assuming the group name matches the username. - curl -fL so a bad commit hash / 404 fails fast instead of saving an HTML page that later breaks unzip. - Reword 'rgbmatrix installed in <sys.executable>' to 'installed for this interpreter' (it's the interpreter path, not an install dir). - Update set_isolcpus docstring to match the actual behavior (strips any existing isolcpus= token, including user-managed ranges).
On Bookworm/Trixie the system python is externally managed, so 'pip install .' of the rgbmatrix bindings fails mid-install. Detect a non-venv externally-managed interpreter up front and bail with guidance to create/activate a venv first, instead of failing after apt + download. Older (non-PEP-668) systems and venvs are unaffected. Verified on test-pi (Pi 4/Trixie): system python -> bail, venv -> pass.
|
Independent hardware retest — test-pi (Pi 4 Model B, Debian Trixie, Adafruit RGB Matrix + RTC HAT, 64×32 panel). Ran the full installer from this branch: HAT interface, RTC=no, Quality path, Reserve a core (isolcpus) — exercising the riskiest edits plus the review fixes. Results — all green:
One finding addressed in 35fa2e6: Trixie enforces PEP 668, so running the installer against the system interpreter ( |
Converts
rgb-matrix.shtorgb-matrix.py, modernized for current hardware/OS (Pi 3/4/5, Bookworm/Trixie).What changed
isolcpus) handling, repo download, prompt-reboot.hzeller/rpi-rgb-led-matrixto the first commit with Pi 5 (RP1) support.pip install .The new upstream is a scikit-build-core / Cython package; the oldmake build-pythontarget is gone. Addedcmaketo apt prerequisites (required by scikit-build-core). Bindings install into the active environment sofrom rgbmatrix import RGBMatrixworks for the user's project.--led-gpio-mapping=adafruit-hat-pwmfor quality /adafruit-hatotherwise) rather than the old-DDISABLE_HARDWARE_PULSEScompile define. The script prints the correct mapping for the chosen build.get_boot_config(),select_n,reconfig,run_raspi_config,prompt_reboot;isolcpuscmdline edit done in idempotent pure Python.--led-slowdown-gpio=5to avoid flicker on solid white on Pi 3/4 (harmless on the Pi 5 RP1 backend).Testing
Hardware-tested with an Adafruit RGB Matrix HAT + two chained 16x32 panels:
RGBMatrix init OK: 64x16, cycled R/G/B/W/clear with no errors.isolcpusactive,snd_bcm2835blacklisted, RTC bound.pip install .build,adafruit-hat-pwm,gpio_slowdownpath.RGBMatrix init OK, R/G/B/W/clear, no errors.gpio_slowdown=4(Pi 4) cleared completely atgpio_slowdown=5— hence the printed guidance.Both test rigs reverted to baseline after testing.
ruff format+ruff checkclean.