# 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).