Running the LED matrix web controller on an Adafruit MatrixPortal S3.
A non-blocking CircuitPython app that runs animations on a 64×32 HUB75 RGB matrix and exposes a simple web UI / JSON API so you can change animations in real time without blocking the HTTP server.
- Adafruit MatrixPortal S3
- 64×32 HUB75 RGB LED matrix (proper 5V power supply)
- HUB75 ribbon/cable to the MatrixPortal S3 connector
- CircuitPython (8.x / 9.x recommended)
- Copy needed libraries into
/lib(from Adafruit bundle):adafruit_httpserveradafruit_display_textadafruit_bitmap_font- other dependencies used by animations
- Flash CircuitPython to the MatrixPortal S3.
- Copy project files to CIRCUITPY:
code.py,boot.py,settings.toml,web/,led_sequences/,lib/
- Edit
settings.toml:CIRCUITPY_WIFI_SSID = "your_ssid" CIRCUITPY_WIFI_PASSWORD = "your_password" - Connect the HUB75 display and power the matrix with a suitable 5V supply.
- Power the board; it will connect to WiFi and start the web server (IP printed to serial).
- UI:
http://<device-ip>/(serves/web/index.html) - JSON endpoints:
GET /api/animations— list available animationsGET /api/current— current selection + play statePOST /api/set{ "name": "" } — select animationPOST /api/load-animation— queue/start selected animationPOST /api/stop-animation— stop current animationGET /api/status— elapsed/remaining time
- Source file in the repo:
web/index.html - On the device: copy the entire
web/folder to the CIRCUITPY root so the board can serve it (path on device:/web/index.html). - Access from a browser on the same network at:
http://<device-ip>/(default HTTP port 80). - How to discover the device IP:
- Check the USB serial console after boot — the script prints the IP address when Wi‑Fi connects.
- Or find the device in your router's DHCP client list.
- To customize the UI:
- Edit
web/index.htmllocally. - Copy the edited file(s) to the device's
/web/folder. - The web server serves files immediately; reload the browser to see changes.
- Edit
- Static assets: If you add images, JS or CSS, place them in
/web/alongsideindex.html.
- Animations live in
led_sequences/ - Each non-blocking animation should implement:
init_animation()→ initial state dictupdate_animation(state)→ draw one frame and return state
- Add new filenames (without
.py) toANIMATIONSincode.py(andboot.pyif used).
- No image: check 5V power and HUB75 wiring (common ground).
- WiFi fail: confirm
settings.tomlcredentials. - Errors: open serial console to view runtime prints.
License: MIT