A 16×16×16 (4096 LED) WS2812B cube driven by a Teensy 4.1, with a web dashboard for flashing firmware and controlling animations live.
Browser ──/api──▶ Flask backend ──USB serial──▶ Teensy 4.1 ──▶ 4096 LEDs
(SvelteKit) (Raspberry Pi) (firmware)
- The Teensy runs C++ firmware (OctoWS2811) with a registry of animations. It listens on USB serial for commands to switch animations and tweak parameters live.
- The Raspberry Pi runs a Flask backend that relays animation commands to the
Teensy over serial and flashes new firmware (
.hex) onto it. - The dashboard (SvelteKit) is the UI: pick an animation, adjust its parameters with auto-generated controls, and upload firmware.
ledcube/
├── dev.sh # Run the dashboard dev server locally
├── deploy.ps1 # Build + deploy frontend & backend to the Pi (Windows/PowerShell)
├── setup.ps1 # One-time Pi provisioning (Windows/PowerShell)
├── ledcube.service # systemd unit for the backend
├── firmware/ # Teensy 4.1 firmware (PlatformIO, env:teensy41)
└── dashboard/
├── backend/ # Python Flask API (status / animations / flash)
└── frontend/ # SvelteKit + Svelte 5 + Tailwind 4 + TypeScript
See CLAUDE.md for detailed architecture, the serial protocol, the
coordinate system, and conventions.
This repo ships a flake.nix dev shell with the full toolchain —
Node (for the dashboard), PlatformIO (for firmware), and Python + Flask/pyserial
(for the backend). On a machine with Nix (flakes enabled):
nix develop # drops you into a shell with node/npm, pio, and python
./dev.sh # then run the dashboard (or `nix develop -c ./dev.sh`)The lockfile (flake.lock) pins exact package versions, so the toolchain is
reproducible across machines. To auto-activate the shell on cd, add an .envrc
containing use flake and install direnv.
Just need Node once, without the project shell?
nix shell nixpkgs#nodejs_22Not using Nix? Install Node 22+ and (for firmware) PlatformIO by your usual means; the commands below are the same.
./dev.shStarts the SvelteKit dev server (default http://localhost:5173) for local,
live-reload development. API requests are proxied to the Pi's backend — set the
target in dashboard/frontend/vite.config.ts
if the Pi's address changes.
In production the dashboard is served by the Pi at
http://ledcube.local/, so it's reachable from any device on the network —
no dev server needed. The frontend builds to a static bundle that the Flask
backend hosts; deploy.ps1 builds and ships it (see below).
Built with PlatformIO. From firmware/:
pio run # build → .pio/build/teensy41/firmware.hex
pio run -t upload # build + flash directly over USBYou can also flash through the dashboard by uploading the built .hex, or POST it to
the backend:
curl -X POST -F "file=@.pio/build/teensy41/firmware.hex" http://<pi-host>/api/flashPowerShell scripts deploy the dashboard to the Pi over SSH (defaults: host
ledcube.local, user ledcube):
.\setup.ps1 # once per Pi: installs teensy_loader_cli, venv, udev rules, systemd service
.\deploy.ps1 # each update: builds + ships the frontend and backend, restarts the serviceThe Pi's Flask backend serves both the JSON API and the built frontend on port
80, so the dashboard is reachable at http://ledcube.local/ from any
device on the network. (On Linux the *.ps1 scripts don't apply — see the
"Deploying from a Linux machine" section of CLAUDE.md.)
| ID | Name | ID | Name |
|---|---|---|---|
| 0 | Twinkle Fade | 11 | Wave |
| 1 | RGB Color Shift | 12 | Snow |
| 2 | Twinkle | 13 | Fireworks |
| 3 | Random | 14 | Helix |
| 4 | Solid | 15 | Sine |
| 5 | Rainbow Fade | 16 | Cube |
| 6 | Fill | 17 | Starfield |
| 7 | Plane Sweep | 18 | Atoms |
| 8 | Rain | 19 | Plasma |
| 9 | Test | 20 | Life |
| 10 | CenterPulse |
Each animation lives in firmware/src/animations/ and has a matching entry in the
backend's ANIMATIONS dict (dashboard/backend/app.py). See the "Adding a new
animation" section of CLAUDE.md.
Helix, Sine, Cube, Starfield, Fireworks, Atoms, Plasma, and Life are ported from
MaltWhiskey's Mega-Cube (see Credits). Several share the Vector3 +
Quaternion math in firmware/src/Math3D.h — see
README_3D_MATH.md for a walkthrough.
- Teensy 4.1 + OctoWS2811 library
- 16 WS2812B strips × 256 LEDs (one strip per cube layer),
WS2811_RGB | WS2811_800kHz - Raspberry Pi connected to the Teensy via USB (
/dev/ttyACM0)
- The Fireworks, Helix, Sine, Cube, Starfield, Atoms,
Plasma, and Life animations
are ported from MaltWhiskey's Mega-Cube
(
Software/LED Display/src/space/), adapted to this cube's coordinate system and animation framework. TheVector3/Quaternionmath (firmware/src/Math3D.h) and thevoxel/radiatedrawing helpers are trimmed-down versions of itspower/Math3Dandcore/Graphics. Thanks to MaltWhiskey for the original cube and its open-source animations.