ESP8266/32 based Art-NET over WiFi node for RGBW pixel LEDs with support for multiple outputs/universes and additional Web UI, DMX input/output support.
- Single codebase for ESP8266 and ESP32 support
- Simple two-button + four-led physical interface for configuration reset and basic diagnostics/tests
- USB Console CLI and HTTP Web UI for configuration and advanced diagnostics (WiP)
- Fully configurable via the USB Console CLI or HTTP Web UI
- WiFi STA/AP support with DHCP or static addressing
- Ethernet support with DHCP client/server or static addressing
- Support for WS2811/WS2812B, SK6812 RGBW, SK9822 and APA102/P9813 LED protocols
- Up to four separate SPI, UART or I2S outputs with different protocols
- GPIO output-enable multiplexing for multiple outputs with a single output peripheral
- I2C GPIO expander (PCA9534/9554) support for status LEDs, DMX/LED output enables
- I2S output with a bit-clock signal (SK9822)
- I2S parallel outputs using ESP-32 I2S1 8-bit mode (memory-efficient)
- Multiple Art-NET universes per output for >170 LEDs
- Software power-limiting for LED outputs with configurable total and per-group limits
- Art-NET poll/discovery support
- Art-NET sync support (recommended when outputting multiple universes per port)
- Art-NET DMX seq support (ignore out-of-order packets)
- Art-NET DMX input (UART)
- Art-NET DMX outputs (UART) with GPIO output-enable multiplexing
- ATX-PSU power-enable/good support
Run the webpack build for the web-dist
files to be included in the SPIFFS image:
$ USER_ID=$UID docker compose -f web/docker-compose.yml run --rm npm install
$ USER_ID=$UID docker compose -f web/docker-compose.yml run --rm npm run build
Using the docker-based Espressif ESP8266 RTOS SDK v3.4 + patches SDK/toolchain:
$ docker compose -f projects/esp8266/docker-compose.yml build sdk
Build firmware images (bootloader + app + web-dist):
$ USER_ID=$UID docker compose -f projects/esp8266/docker-compose.yml run --rm build
Flash firmware images (bootloader + app + web-dist) to NodeMCU devkit:
$ ESPPORT=/dev/ttyUSB? docker compose -f projects/esp8266/docker-compose.devices.yml run --rm flash
Access the USB console:
$ ESPPORT=/dev/ttyUSB? docker compose -f projects/esp8266/docker-compose.devices.yml run --rm monitor
Using the docker-based Espressif ESP-IDF v4.4 + patches SDK/toolchain:
$ BUILD_UID=$(id -u) BUILD_GID=$(id -g) docker compose -f projects/esp32/docker-compose.yml build sdk
Build firmware images (bootloader + app + web-dist):
$ docker compose -f projects/esp32/docker-compose.yml run --rm build
Flash firmware images (bootloader + app + web-dist) to the ESP32-devkit:
$ ESPPORT=/dev/ttyUSB? docker compose -f projects/esp32/docker-compose.devices.yml run --rm flash
Access the USB console:
$ ESPPORT=/dev/ttyUSB? docker compose -f projects/esp32/docker-compose.devices.yml run --rm monitor
By default, the ESP8266 will establish an (open) WiFi Access-Point with a qmsk-esp-******
name.
Once connected to the qmsk-esp-******
WiFi network, the integrated Web UI will be available at the matching http://qmsk-esp-******.local
address.
Please configure a WiFi password, and optionally a HTTP username/password.
By default, the ESP8266 will print log messages and open a CLI console on UART0, which can be accessed via the same USB UART used for bootloader flashing:
ESPPORT=/dev/ttyUSB? docker compose run --rm monitor
If using the UART0 pins for other IO (e.g. spi-leds
I2S interface), the console can be closed manually using the exit
command,
or automatically at boot using the timeout
config. The console can be re-started using a short press on the FLASH button;
this will re-initiate any configured timeout
. The console can also be disabled completely using the enabled
config.
If using the UART0 peripheral for other IO (e.g. dmx-input
), the SDK CONFIG_ESP_CONSOLE_UART_CUSTOM
config must be used to redirect SDK logging output. The UART0 console can still be temporarily activated at boot using the timeout
config to briefly show logging output and offer the option of opening the CLI, or disabled completely using the enabled
config.
If the timeout
config is used, the console will use the UART0 to prompt the user, before timing out and releasing the UART0:
! Use [ENTER] to open console
Supports four LEDs and two buttons for a very basic user interface.
Use the make menuconfig
-> "qmsk-esp" component options to configure how the status LEDs/Buttons are connected.
Defaults for NodeMCU ESP8266 devkit, matching the built-in LEDs/buttons on the following pins:
- D0 (GPIO16): USER_LED (active-low with pull-up) -> built-in LED
- D3 (GPIO0): FLASH_LED (active-low with pull-up) -> built-in BOOT/FLASH button
- D8 (GPIO15): ALERT_LED (active-high with pull-down)
The active-low LEDs should be connected from +3.3V to the GPIO pin. The active-high LEDs should be connected from the GPIO pin to GND.
Defaults for ESP32 devkits, without any built-in LEDs/buttons accessible on the external pins:
- IO2: USER_LED (active-low with internal pull-up)
- IO4: FLASH_LED (active-low with internal pull-up)
- IO15: ALERT_LED (active-low with internal pull-up)
The active-low LEDs should be connected from +3.3V to the GPIO pin. The active-high LEDs should be connected from the GPIO pin to GND.
The built-in BOOT/FLASH button is connected to IO0 on the ESP32 devkits, but not all devkits break out IO0 on the external pin headers.
The USER LED on GPIO16 (ESP8266) / IO2 (ESP32) is used to indicate network connectivity:
- Off: Boot / reset
- Fast blinking: WiFi / Ethernet connecting
- Slow blinking: WiFi / Ethernet disconnected
- On: WiFi / Ethernet connected
The FLASH LED on GPIO0 (ESP8266) / IO4 (ESP32) is used to indicate activity:
Flashes for ~10ms on each LED output / update.
The FLASH button on GPIO0 (ESP8266) / GPIO4 (ESP32) is used to trigger config mode or a config reset.
Press the FLASH button briefly until the ALERT LED starts flashing, and release to enter configuration mode. The UART0 console will be activated if stopped, which will block any I2S output.
Press and hold FLASH button for >5s until the ALERT LED stops flashing, and the system will reset the configuration and restart.
If the FLASH button is held pressed at app boot, the configuration will not be loaded, and the Alert LED will flash slowly to indicate that the default configuration is active. Note that this only applies on a soft reset, if the FLASH button is held at power reset, the bootloader will enter UART flashing mode.
The ALERT LED on GPIO15 (ESP8266) / IO15 (ESP32) is used to indicate configuration issues:
- On: Boot failed
- Slow: Missing configuration
- Fast: Invalid configuration
The ALERT button on GPIO15 (ESP266) / IO15 (ESP32) is used to initiate the built-in self-test mode:
- Short press: cycle through the test modes manually, leaving them active when released
- Long press: cycle through the test modes automatically, and clear the test mode when released
From help
output:
help: Show commands
system info: Print system info
system memory: Print system memory
system partitions: Print system partitions
system status: Print system status
system tasks: Print system tasks
system interfaces: Print system network interfaces
system restart: Restart system
status-leds off: Turn off USER LED
status-leds on: Turn on USER LED
status-leds slow: Blink USER LED slowly
status-leds fast: Blink USER LED fast
status-leds flash: Blink FLASH LED once
status-leds read: Read FLASH button
status-leds alert: Turn on ALERT LED
spiffs info [LABEL]: Show SPIFFS partition
spiffs format [LABEL]: Format SPIFFS partition
vfs ls PATH: List files
config show [SECTION]: Show config settings
config get SECTION NAME: Get config setting
config set SECTION NAME VALUE: Set and write config
config clear SECTION NAME: Clear and write config
config reset: Remove stored config and reset to defaults
wifi scan [SSID]: Scan available APs
wifi connect [SSID] [PSK]: Connect AP
wifi info : Show connected AP
spi-leds clear : Clear all output values
spi-leds all RGB [A]: Set all output pixels to value
spi-leds set OUTPUT INDEX RGB [A]: Set one output pixel to value
dmx zero COUNT: Output COUNT channels at zero on all output
dmx all COUNT VALUE: Output COUNT channels at VALUE on all outputs
dmx out OUTPUT VALUE...: Output given VALUEs as channels on output
dmx count OUTPUT COUNT: Output COUNT channels with 0..COUNT as value
From config show
, GET /config.ini
output:
# Control ATX-PSU based on spi-leds output.
# The ATX-PSU will be powered on when spi-led outputs are active, and powered off into standby mode if all spi-led outputs are idle (zero-valued).
[atx_psu]
enabled = false
gpio = 0
# Power off ATX PSU after timeout seconds of idle
timeout = 10
# WiFi station mode, connecting to an SSID with optional PSK.
# Uses DHCP for IPv4 addressing.
[wifi]
mode = AP # OFF STA [AP] APSTA
# For STA mode: minimum threshold for AP provided auth level
# For AP mode: provided auth level
auth_mode = WPA2-PSK # OPEN WEP WPA-PSK [WPA2-PSK] WPA-WPA2-PSK WPA3-PSK WPA2-WPA3-PSK
# For STA mode: connect to AP with given SSID
# For AP mode: start AP with given SSID, or use default
ssid =
password = ***
hostname =
# HTTP API + Web frontend with optional HTTP basic authentication.
[http]
enabled = true
host = 0.0.0.0
port = 80
# Optional HTTP basic authentication username/password
username =
# Optional HTTP basic authentication username/password
password = ***
# Art-Net receiver on UDP port 6454.
# Art-Net addresses consist of the net (0-127) + subnet (0-15) + universe (0-15). All outputs share the same net/subnet, each output uses a different universe. Up to four outputs are supported.
[artnet]
enabled = false
# Set network address, 0-127.
net = 0
# Set sub-net address, 0-16.
subnet = 0
# Control LEDs using synchronous (separate clock/data) serial protocols via Art-Net.
# Multiple serial outputs can be multiplexed from the same SPI driver by using GPIOs to control an external driver chip with active-high/low output-enable GPIO lines.
[spi-leds0]
enabled = false
protocol = APA102 # [APA102] P9813
# Longer cable runs can be noisier, and may need a slower rate to work reliably.
rate = 1M # 20M 10M 5M 2M [1M] 500K 200K 100K 50K 20K 10K 1K
# Delay data signal transitions by system clock cycles to offset clock/data transitions and avoid coupling glitches.
delay = 0
count = 0
# Multiplex between multiple active-high/low GPIO-controlled outputs
gpio_mode = OFF # [OFF] HIGH LOW
# GPIO pin to activate when transmitting on this output
gpio_pin = 0
artnet_enabled = false
# Output from artnet universe (0-15) within [artnet] net/subnet.
artnet_universe = 0
# Art-Net DMX channel mode
artnet_mode = BGR # RGB [BGR] GRB
# Control LEDs using synchronous (separate clock/data) serial protocols via Art-Net.
# Multiple serial outputs can be multiplexed from the same SPI driver by using GPIOs to control an external driver chip with active-high/low output-enable GPIO lines.
[spi-leds1]
enabled = false
protocol = APA102 # [APA102] P9813
# Longer cable runs can be noisier, and may need a slower rate to work reliably.
rate = 1M # 20M 10M 5M 2M [1M] 500K 200K 100K 50K 20K 10K 1K
# Delay data signal transitions by system clock cycles to offset clock/data transitions and avoid coupling glitches.
delay = 0
count = 0
# Multiplex between multiple active-high/low GPIO-controlled outputs
gpio_mode = OFF # [OFF] HIGH LOW
# GPIO pin to activate when transmitting on this output
gpio_pin = 0
artnet_enabled = false
# Output from artnet universe (0-15) within [artnet] net/subnet.
artnet_universe = 0
# Art-Net DMX channel mode
artnet_mode = BGR # RGB [BGR] GRB
# Control LEDs using synchronous (separate clock/data) serial protocols via Art-Net.
# Multiple serial outputs can be multiplexed from the same SPI driver by using GPIOs to control an external driver chip with active-high/low output-enable GPIO lines.
[spi-leds2]
enabled = false
protocol = APA102 # [APA102] P9813
# Longer cable runs can be noisier, and may need a slower rate to work reliably.
rate = 1M # 20M 10M 5M 2M [1M] 500K 200K 100K 50K 20K 10K 1K
# Delay data signal transitions by system clock cycles to offset clock/data transitions and avoid coupling glitches.
delay = 0
count = 0
# Multiplex between multiple active-high/low GPIO-controlled outputs
gpio_mode = OFF # [OFF] HIGH LOW
# GPIO pin to activate when transmitting on this output
gpio_pin = 0
artnet_enabled = false
# Output from artnet universe (0-15) within [artnet] net/subnet.
artnet_universe = 0
# Art-Net DMX channel mode
artnet_mode = BGR # RGB [BGR] GRB
# Control LEDs using synchronous (separate clock/data) serial protocols via Art-Net.
# Multiple serial outputs can be multiplexed from the same SPI driver by using GPIOs to control an external driver chip with active-high/low output-enable GPIO lines.
[spi-leds3]
enabled = false
protocol = APA102 # [APA102] P9813
# Longer cable runs can be noisier, and may need a slower rate to work reliably.
rate = 1M # 20M 10M 5M 2M [1M] 500K 200K 100K 50K 20K 10K 1K
# Delay data signal transitions by system clock cycles to offset clock/data transitions and avoid coupling glitches.
delay = 0
count = 0
# Multiplex between multiple active-high/low GPIO-controlled outputs
gpio_mode = OFF # [OFF] HIGH LOW
# GPIO pin to activate when transmitting on this output
gpio_pin = 0
artnet_enabled = false
# Output from artnet universe (0-15) within [artnet] net/subnet.
artnet_universe = 0
# Art-Net DMX channel mode
artnet_mode = BGR # RGB [BGR] GRB
# DMX output via UART1 -> RS-485 transceiver.
# Because UART1 TX will spew debug messages reset/flash/boot, avoid DMX glitches by using a GPIO pin that is kept low during reset/boot to drive the RS-485 transceiver's active-high transmit/output-enable.
[dmx0]
enabled = false
# GPIO pin will be taken high to enable output once the UART1 TX output is safe.
gpio_pin = 0
# Multiplex between multiple active-high/low GPIO-controlled outputs
gpio_mode = OFF # [OFF] HIGH LOW
artnet_enabled = false
# Output from universe (0-15) within [artnet] net/subnet.
artnet_universe = 0
# DMX output via UART1 -> RS-485 transceiver.
# Because UART1 TX will spew debug messages reset/flash/boot, avoid DMX glitches by using a GPIO pin that is kept low during reset/boot to drive the RS-485 transceiver's active-high transmit/output-enable.
[dmx1]
enabled = false
# GPIO pin will be taken high to enable output once the UART1 TX output is safe.
gpio_pin = 0
# Multiplex between multiple active-high/low GPIO-controlled outputs
gpio_mode = OFF # [OFF] HIGH LOW
artnet_enabled = false
# Output from universe (0-15) within [artnet] net/subnet.
artnet_universe = 0
To recover from a broken configuration, either press and hold the FLASH button, or erase the SPIFFS partition using the USB bootloader:
ESPPORT=/dev/ttyUSB? docker compose run --rm config-reset
Synchronous TX-only UART1 implementation using interrupts and FreeRTOS queues.
Writes bypass the TX queue and interrupt handler if there is room in the hardware FIFO. UART TX interrupt handler empties the queue.
Supports RS232/458 breaks as required for e.g. DMX resets, outputting break/mark for a specified duration.
DMA based I2S output for generating arbitrary (32-bit aligned) bit streams, using interrupts to wait for TX to complete.
Designed for generating WS2812B data signals.
Provide DEBUG
/ INFO
/ WARN
/ ERROR
logging with function context.
Basic line buffering from stdin/stdout, evaluating input lines via cmd
.
Support for the following ASCII control codes:
\r
(ignored)\n
(end of line)\b
(wipeout)
CLI commands with arguments, subcommands, usage help.
Support for reading/writing configuration structs via INI files.
Config read/write from stdio FILE can be used with SPIFFS, CLI and HTTP handlers.
Simple GPIO LED blinking.
DMX input/output support.
Uses UART0 alternate RTS/CTS output pins for DMX input.
Uses UART1 for DMX output.
Control RGB LEDs using SPI/UART/I2S output interfaces, with protocol support for:
- APA102/SK9822 (SPI)
- P9813 (SPI)
- WS2812B / WS2811 (UART, I2S)
- SK6812-GRBW (UART, I2S)
Supports optional GPIO output for multiplexing a single SPI/UART/I2S output interface between multiple spi_leds
outputs.
Art-NET UDP receiver with support for polling/discovery and multiple DMX outputs with sequence numbering support.
Supports local DMX input.
Stack-based JSON serializer for stdio output.
HTTP protocol support.
HTTP server support with listeners, routes, requests and responses.
Configure WIFI STA from loaded configuration (SSID, PSK).
Station e8:db:84:94:5a:7e: Connected
BSSID : aa:bb:cc:dd:ee:ff
SSID : qmsk-iot
Channel : 11:0
RSSI : -60
AuthMode : WPA2-PSK
Pairwise Cipher : NONE
Group Cipher : NONE
Flags : 11b 11g
TCP/IP:
Hostname : espressif
DHCP Client : STARTED
IP : 172.29.16.47
Netmask : 255.255.0.0
Gateway : 172.29.0.1
DNS (main) : 172.29.0.1
DNS (backup) : 0.0.0.0
DNS (fallback) : 0.0.0.0
BSSID SSID CH:CH RSSI AUTHMODE PAIRW/GROUP CIPHFLAGS
xx:xx:xx:xx:xx:xx 11:0 -58 WPA2-PSK CCMP /CCMP bgn
aa:bb:cc:dd:ee:ff qmsk 11:0 -60 WPA/2-PSK TKIP-CCMP /TKIP bgn
aa:bb:cc:dd:ee:ff qmsk-guest 11:0 -61 WPA/2-PSK TKIP-CCMP /TKIP bgn
aa:bb:cc:dd:ee:ff qmsk-iot 11:0 -61 WPA2-PSK CCMP /CCMP bgn
Ethernet support using an external PHY.
Use idf.py menuconfig
-> Component config -> qmsk-esp-eth -> Ethernet board type to select a supported board type:
- WT32-ETH01 (v1.2)
The eth
interface can be configured in three modes:
NONE
- no IPv4 addressing, theip
/netmask
/gw
settings are ignoredDHCP_CLIENT
- start DHCP client, theip
/netmask
/gw
settings are ignoredDHCP_SERVER
- start DHCP server, requires theip
/netmask
/gw
to be configuredSTATIC
- use static IPv4 address, requires theip
/netmask
/gw
to be configured
Control an ATX PSU #PS_EN
via GPIO. Powers on the PSU whenever SPI-LED output is active, with a configurable shutdown timeout.
Art-NET UDP receiver.
Supports up to four Art-NET outputs on the Art-Net Sub-Net matching the higher bits of the configured universe
. With e.g. universe = 0
, artnet outputs can use universes 0-15. To use an artnet output universe 16, the [artnet] universe
must be configured to 16
, and then output universes 16-31 can be used.
Art-NET DMX input via UART2 RX (using UART0 alternate RTS/CTS pins).
The FLASH LED will blink on DMX updates.
Can be used to control local Art-NET outputs using a configured Art-NET universe.
Art-NET DMX output via UART1 TX.
Supports up to two multiplexed outputs using active-high/low GPIOs.
The FLASH LED will blink on DMX updates.
Art-NET DMX controller for RGB LEDs.
Supports up to four separate outputs with different interfaces, protocols.
Supports GPIO-multiplexed outputs sharing the same interface peripheral, with external line driver active-high/low output-enable GPIOs.
The FLASH LED will flash on SPI-LEDs updates.
The ATX PSU output will enable when any SPI-LEDs are active.
The ESP32 I2S output supports arbitrary clock, data and inverted-data output IO pins. Up to 8 data pins can be configured for parallel outputs with a higher refresh rate, at the cost of higher memory usage for DMA buffers (I2S1
only).
The ESP8266 I2S output uses the same IO pins as the UART0 console, and cannot be used while the console is active. Disable the console or set a console timeout to use the I2S output interface.
Load the integrated Web UI.
Returns the boot config in INI form.
Load the running config from INI form.
Returns a JSON structure describing the config schema and current values.
Accepts application/x-www-form-urlencoded
form parameters in a [module]name=value
format, as per config set ...
.
Returns a JSON object describing the system info, state and status.
info
status
partitions
tasks
interfaces
Refresh the running tasks info.
Restart the system.
Return LED config/state.
Accepts application/x-www-form-urlencoded
form parameters using the following syntax:
index=%d
(1-4)all=%x[.%x]
(RRGGBB
orRRGGBB.XX
)%u=%x[.%x]
(RRGGBB
orRRGGBB.XX
)
The .XX
suffix is optional, and the interpretation depends on the protocol, per the GET /api/leds
-> color_parameter
field:
NONE
: not usedDIMMER
: 0-255 controls the LED brightnessWHITE
: 0-255 controls the white LED
Returns [{"mode": ...}]
parameters usable for POST
.
Accepts application/x-www-form-urlencoded
form parameters using the following syntax:
index=%d
(1-4)mode=%s
(seeGET /api/leds/test
)