projectMM v3.0.0
The biggest release since 1.0 — 164 commits across ~10 PRs. Highlights: the parallel-LED drivers consolidate into one runtime-peripheral module; a streaming shift-ring drives 12,288 lights (48×256) on a single S3; Home Assistant MQTT discovery; a live on-device scripting engine (MoonLive); a new ESP32-S31 board with 1 Gb Ethernet; Philips Hue output; a migrated library of 20+ effects and 60 palettes; a multicore render/encode split; and a ground-up robustness pass proven with live-hardware scenario tests.
If you like projectMM, give it a ⭐️, fork it, or open an issue or pull request. It helps the project grow, improve, and get noticed.
🔬 How it's built
Every feature follows projectMM's Industry standards, our own code principle: spec the behaviour from primary sources (the ESP32 / peripheral datasheets, the WS2812 timing spec, reference DSP), reach for the textbook algorithm and the textbook name (a DC-blocker high-pass, a Hann window, an in-order completion FIFO, a bit-transpose), pin it with unit + scenario tests first, then write every line fresh against our own architecture, crediting the prior art by name. New this release: many features were verified with live-hardware scenario tests — the same scripts drive real boards over HTTP and leave each bench board exactly as they found it.
✨ Highlights
One "Parallel LED" driver, three DMA peripherals
MultiPinLedDriver,MoonLedDriver, andParlioLedDrivermerge into a singleParallelLedDriverwhoseperipheralcontrol picks the DMA backend —i80,MoonI80, orParlio. The add-module picker shows one card on every board; the dropdown offers only what the chip supports (i80 on S3/P4/S31/classic, MoonI80 on the LCD_CAM chips, Parlio on the P4). Switching the peripheral is live — no reboot (ADR-0016).- A one-driver-per-hardware-block guard, stable board-portable option labels, and clean per-chip capability filtering.
The MoonI80 streaming shift-ring — 12,288 lights on one chip
- MoonI80 is our own GDMA driver below
esp_lcd. Its streaming ring feeds a small pool of internal buffers refilled behind the DMA read head, so strand length stops being a memory question — the whole frame never has to fit RAM. A full 48×256 = 12,288-light wall renders clean on a single ESP32-S3. - A 74HCT595 pin expander fans one GPIO out to 8 strands (6 pins → 48 strands). Auto-derived ring geometry (or expert
ring*controls), a validated viability rule, and a clock-oracle lapping refill for very long strands.
Home Assistant & smart-home
- MQTT Discovery (JSON schema) with LWT availability — projectMM appears in Home Assistant automatically, including an update entity (a badge when a newer release is out). Homebridge control and Ethernet opt-in alongside.
MoonLive — live on-device scripting
- Write an effect as a small script that compiles to native code on the device and renders each tick; edit the source live and it recompiles without a reboot, with
@control-declared sliders bound to real controls. Runs on three instruction sets (Xtensa S3, RISC-V P4/S31, and the desktop) — a broken script fails safe (renders dark, shows the error) rather than crashing.
New platform — ESP32-S31
- A new board variant: 1 Gb RGMII Ethernet, on-board mic + I²C scan, RISC-V dual-core. Builds, publishes to the web installer + releases, and offers all three LED peripherals.
Effects, modifiers, layouts & palettes
- A migrated MoonLight effect library (20+ effects) plus faithfully-migrated E_MoonModules effects, 60 palettes, and a demo-reel showcase. New: Wave, GridBlacks (a spacer layout with mid-strand dark gaps), Region and the earlier modifiers, text/font primitives.
- A reusable LightPresets library — build a channel-role wiring (RGB / GRBW / moving-head layouts) once, reference it by name from many drivers.
Output & performance
- Philips Hue output (
HueDriver) — drive Hue bulbs from the pipeline, with room/light filtering. - Classic ESP32 i80 driver over the I2S peripheral; 16-lane parallel output; an async double-buffer that hides the WS2812 wire time behind DMA; a SWAR bit-transpose encoder.
- A multicore render↔encode split — the LED encode / packet build runs on core 1 while core 0 renders the next frame, so a frame costs
max(render, output)instead of the sum. Degrades cleanly to single-core when memory is tight. - Diff-on-the-wire state push — only changed control values go over the WebSocket, fixing a 1 Hz LED stutter from re-serialising unchanging data.
Robustness — any input, no crash, no reboot
- A running device tolerates any add / remove / replace / reorder of modules in any order. Fixed this release: a module replace on a split-render device (use-after-free), a live peripheral swap freeing a buffer the encode worker reads, a driver destroyed while the worker was inside it (vptr race), a reordered code-wired child losing its persisted state, a preset name with a quote wiping the custom-preset library on reboot, an out-of-memory preset restore, and the MoonI80 whole-frame double-buffer freeze (it now runs single-buffer; the ring is its scale path).
- Audio is now one
modecontrol (Local / Receive network / Simulate); a Local-mode mic status no longer lingers after switching modes.
Toolchain, tooling & docs
- ESP-IDF pinned to v6.1-beta1. Windows ESP32 builds fixed end-to-end; the whole tree builds clean under GCC with a sanitizer (ASan/TSan) gate. A
ScratchBuffer<T>primitive for the memory-holding effects. - MoonDeck (the dev/bench toolkit, renamed from
scripts/) with live output, and a MkDocs documentation site. Per-module generated docs, and a live-scenario harness that drives peripheral switches on real hardware.
⚠️ Breaking change — action on upgrade
A field device carrying a pre-consolidation MultiPinLedDriver, MoonLedDriver, or ParlioLedDriver persisted type will drop that driver on boot (the old type no longer resolves). Re-add a "Parallel LED" driver and pick the peripheral your board uses, then re-enter its pins. The web installer's board catalog already names the new type, so a fresh install or catalog re-inject wires it correctly. Full details + the other renamed controls: MIGRATING.md.
📦 Install
Flash from your browser — pick your board, flash the matching firmware, hand over WiFi via Improv: the web installer. Step-by-step in the Getting started guide. Desktop builds (macOS arm64 / Windows x64) and per-variant firmware binaries are attached below.
Supported targets this release: ESP32 (classic / Olimex / WROVER), ESP32-S3, ESP32-P4, ESP32-S31 (new), plus macOS arm64 / Windows x64 desktop.