Add ArtNetDMX Pico W firmware with dual DMX and docs.
Art-Net to two RS-485 outputs over Wi-Fi (AP or STA with SoftAP fallback), web UI, mDNS, and QLC+/ArtPoll notes for unicast on STA. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,118 @@
|
||||
# ArtNetDMX — Pico W Art-Net → Dual DMX
|
||||
|
||||
Firmware for **Raspberry Pi Pico W** that receives Art-Net over Wi‑Fi and outputs **two DMX512 universes** through RS‑485, using **PIO + DMA** at **40 Hz**. A web UI configures Wi‑Fi (STA / AP) and shows / sets all 512 channels per universe.
|
||||
|
||||
## Hardware
|
||||
|
||||
| Signal | Pico W | RS‑485 module |
|
||||
|--------|--------|----------------|
|
||||
| DMX A data | GP0 | DI (universe A) |
|
||||
| DMX B data | GP1 | DI (universe B) |
|
||||
| GND | GND | GND |
|
||||
| Power | 3V3 or 5V | VCC (many MAX485 boards want 5V) |
|
||||
|
||||
TX‑only: tie **DE** and **/RE** high (to VCC) on each module. XLR pinout is typically 1=GND, 2=Data− (B), 3=Data+ (A) — match your module labels.
|
||||
|
||||
Pins are defined in [`include/board.h`](include/board.h).
|
||||
|
||||
```
|
||||
Pico W GP0 ──► MAX485 A DI
|
||||
Pico W GP1 ──► MAX485 B DI
|
||||
Pico W GND ──► both module GND
|
||||
VCC ──► both module VCC
|
||||
DE,/RE ──► VCC (TX enable)
|
||||
A/B ──► XLR / DMX cable
|
||||
```
|
||||
|
||||
## Build
|
||||
|
||||
Requires [Pico SDK](https://github.com/raspberrypi/pico-sdk) and an ARM GCC toolchain.
|
||||
|
||||
```bash
|
||||
export PICO_SDK_PATH=/path/to/pico-sdk
|
||||
mkdir -p build && cd build
|
||||
cmake -DPICO_BOARD=pico_w ..
|
||||
make -j$(nproc)
|
||||
```
|
||||
|
||||
Flash with BOOTSEL + drag-and-drop, or:
|
||||
|
||||
```bash
|
||||
picotool load -f build/artnetdmx.uf2
|
||||
```
|
||||
|
||||
USB serial (115200) prints boot status, Wi‑Fi mode, and IP addresses.
|
||||
|
||||
Do not `cp` the UF2 onto a path that is not the mounted `RPI-RP2` volume (a failed copy can leave a plain file instead of flashing).
|
||||
|
||||
## First boot (AP)
|
||||
|
||||
1. Join Wi‑Fi **ArtNetDMX** / password **artnetdmx**
|
||||
2. Open **http://192.168.4.1/** (or **http://artnetdmx.local/** once mDNS is up)
|
||||
3. **WiFi** page: choose mode, credentials, Art‑Net universe numbers, mDNS hostname
|
||||
4. Save — device reboots
|
||||
|
||||
### Wi‑Fi modes
|
||||
|
||||
| Mode | Behaviour |
|
||||
|------|-----------|
|
||||
| **Access Point** | SoftAP only (default `ArtNetDMX` / `artnetdmx` @ `192.168.4.1`) |
|
||||
| **Station** | Joins your LAN only. If join fails, SoftAP starts for recovery |
|
||||
|
||||
There is no concurrent AP+STA mode (legacy “AP+Station” configs are treated as Station). SoftAP is paused while STA obtains DHCP, then left off if join succeeds.
|
||||
|
||||
mDNS hostname defaults to **`artnetdmx`** → **http://artnetdmx.local/** (configurable on the WiFi page).
|
||||
|
||||
## Art-Net
|
||||
|
||||
- UDP port **6454**
|
||||
- Replies to **ArtPoll** / sends **ArtPollReply** (QLC+ and similar discovery)
|
||||
- Maps configured universes to physical ports A (GP0) and B (GP1)
|
||||
- Defaults: universe **0** → A, universe **1** → B
|
||||
|
||||
### SoftAP vs Station (important)
|
||||
|
||||
| Mode | Art-Net transport |
|
||||
|------|-------------------|
|
||||
| **SoftAP** | Controller joins the Pico’s AP. **Broadcast** ArtDmx usually works. |
|
||||
| **Station** | Pico and controller share a home/office AP. Many APs **drop Wi‑Fi broadcast**, so ArtDmx broadcast never arrives. Use **unicast** to the Pico’s STA IP. |
|
||||
|
||||
Unicast ArtDmx on STA has been verified end-to-end; subnet broadcast often is not delivered by the upstream AP.
|
||||
|
||||
### QLC+ setup
|
||||
|
||||
1. Put the Pico in **Station** mode and note its IP (web UI, serial, or mDNS).
|
||||
2. **Inputs/Outputs** → Art-Net plugin.
|
||||
3. You will typically see **two nodes**: **QLC+ itself** and **ArtNetDMX**. Select **ArtNetDMX** (not the QLC+ loopback node).
|
||||
4. Set output to **unicast** → Pico STA IP (e.g. `10.1.1.190`), not broadcast and not `192.168.4.1` unless you are on SoftAP.
|
||||
5. Enable the Art-Net **output** line (icon lit).
|
||||
6. Map universes: **0** → DMX A, **1** → DMX B (or match the WiFi page).
|
||||
7. Patch fixtures to those universes.
|
||||
|
||||
Confirm on **http://<pico-ip>/** (Channels): Art-Net packet count should rise and channel values should follow faders. If the web UI updates but fixtures do not, check RS‑485 wiring / DE·/RE / cabling.
|
||||
|
||||
## Web UI
|
||||
|
||||
- **Channels** — tabs for universe A/B; all 512 values; edit live; Clear / All 255
|
||||
- **WiFi** — AP or Station, credentials, Art‑Net universes, mDNS hostname, live debug line
|
||||
- Status strip: mode, IP, Art‑Net packet count, age since last packet per port
|
||||
|
||||
Manual channel edits drive the same buffers as Art‑Net; new Art‑Net packets overwrite those channels.
|
||||
|
||||
Embedded pages live in `src/http_server.c`. The `www/` tree is a reference copy of the HTML structure.
|
||||
|
||||
## Project layout
|
||||
|
||||
| Path | Role |
|
||||
|------|------|
|
||||
| `src/main.c` | Boot, DMX timer, poll loops |
|
||||
| `src/wifi_mgr.c` | SoftAP / STA, DHCP, mDNS hooks |
|
||||
| `src/artnet.c` | ArtDmx + ArtPoll/ArtPollReply |
|
||||
| `src/dmx_out.c` + `.pio` | PIO + DMA DMX TX |
|
||||
| `src/http_server.c` | Web UI + JSON API |
|
||||
| `src/config.c` | Flash config (CRC, versioned) |
|
||||
| `lwipopts.h` | lwIP tuning (UDP PCBs, SoftAP DHCP, broadcast) |
|
||||
|
||||
## License notes
|
||||
|
||||
DMX PIO timing is adapted from [jostlowe/Pico-DMX](https://github.com/jostlowe/Pico-DMX) (BSD‑3‑Clause). DHCP server is from MicroPython / pico‑examples (MIT).
|
||||
Reference in New Issue
Block a user