15 KiB
RFP Infinity Flashing
This document covers the two production firmware targets for the Infinity installation.
There is intentionally no separate coldboot firmware anymore: the reliable N16R8
boot settings are part of the normal master and node targets.
Targets
- Master target:
rfp_esp32s3_wroom1_n16r8_master - Node target:
rfp_esp32s3_wroom1_n16r8_3x106
Firmware Release Names
These names are compiled into the firmware as WLED_RELEASE_NAME and show up in
WLED update metadata, OTA validation, serial boot logs, and /json/info.
- Master:
RFP_N16R8_MASTER_V20260511E - Node:
RFP_N16R8_NODE3x106_V20260511E
Both targets use the same robust ESP32-S3-WROOM-1 N16R8 boot configuration:
- Flash: QIO / 16 MB
- Flash frequency: 80 MHz
- PSRAM: OPI / 8 MB octal
- Partition table:
tools/WLED_ESP32_16MB.csv - USB CDC on boot: disabled
- Boot delay:
WLED_BOOTUPDELAY=1200
Clean-Flash Warning
erase_flash removes the complete flash contents, including WLED's saved
cfg.json, Wi-Fi credentials, static IP settings, presets, and filesystem data.
The RFP master and node targets compile the show Wi-Fi as firmware defaults:
- SSID:
RFPLicht - Password: configured in the RFP build flags
After a full erase the board can therefore join Wi-Fi again, but runtime-only settings that were stored through the WLED UI must be re-applied unless they are also encoded as firmware defaults.
Roles
- Master:
- Usually
192.168.178.10 - Runs the
/infinityweb UI - Accepts DMX and web commands
- Sends Infinity Sync packets to the nodes
- Keeps one dummy WLED pixel on
GPIO21so the regular WLED UI remains valid - Keeps the real WLED status pixel exclusively on
GPIO48
- Usually
- Nodes:
- Usually
192.168.178.11to192.168.178.16 - Render the LED output locally
- Receive Infinity Sync from the master
- Use three LED outputs:
GPIO4/5/6, each with106LEDs
- Usually
Build: Master
cd /home/jan/Documents/RFP/WLED-MM/repo
PATH=/home/jan/Documents/RFP/Finanz_App/node/current/bin:$PATH \
NPM_CONFIG_CACHE=$PWD/.npm-cache \
PLATFORMIO_CORE_DIR=$PWD/.piohome \
PLATFORMIO_PACKAGES_DIR=$PWD/.piohome/packages \
PLATFORMIO_PLATFORMS_DIR=$PWD/.piohome/platforms \
PLATFORMIO_CACHE_DIR=$PWD/.piohome/.cache \
PLATFORMIO_BUILD_CACHE_DIR=$PWD/.piohome/buildcache \
.venv/bin/python -m platformio run -e rfp_esp32s3_wroom1_n16r8_master
Master firmware output:
.pio/build/rfp_esp32s3_wroom1_n16r8_master/firmware.bin
build_output/release/WLEDMM_14.7.2-mdev_RFP_N16R8_MASTER_V20260511E.bin
Build: Nodes
cd /home/jan/Documents/RFP/WLED-MM/repo
PATH=/home/jan/Documents/RFP/Finanz_App/node/current/bin:$PATH \
NPM_CONFIG_CACHE=$PWD/.npm-cache \
PLATFORMIO_CORE_DIR=$PWD/.piohome \
PLATFORMIO_PACKAGES_DIR=$PWD/.piohome/packages \
PLATFORMIO_PLATFORMS_DIR=$PWD/.piohome/platforms \
PLATFORMIO_CACHE_DIR=$PWD/.piohome/.cache \
PLATFORMIO_BUILD_CACHE_DIR=$PWD/.piohome/buildcache \
.venv/bin/python -m platformio run -e rfp_esp32s3_wroom1_n16r8_3x106
Node firmware output:
.pio/build/rfp_esp32s3_wroom1_n16r8_3x106/firmware.bin
build_output/release/WLEDMM_14.7.2-mdev_RFP_N16R8_NODE3x106_V20260511E.bin
Recommended Update: Master USB First, Nodes Via Master
Use this for normal show updates. The laptop only needs USB access to the master; it does not need to join the RFP Wi-Fi. The workflow is:
- Build master and node firmware locally.
- Flash the master app by USB.
- Hard-reset the master and verify its RFP release over the serial relay.
- Stream node OTA updates through the master to nodes
.11to.16.
The master USB flash deliberately does not run erase_flash and does
not run uploadfs. This avoids rewriting the large LittleFS area during a
normal firmware update and keeps runtime config/filesystem data intact.
cd /home/jan/Documents/RFP/WLED-MM/repo
.venv/bin/python tools/rfp_update_master_usb_then_nodes.py --port /dev/ttyACM0
Use existing build artifacts without rebuilding:
cd /home/jan/Documents/RFP/WLED-MM/repo
.venv/bin/python tools/rfp_update_master_usb_then_nodes.py --port /dev/ttyACM0 --no-build
Resume node updates after a failure:
cd /home/jan/Documents/RFP/WLED-MM/repo
.venv/bin/python tools/rfp_update_master_usb_then_nodes.py --port /dev/ttyACM0 --no-build --nodes-only --start-from 192.168.178.14
Flash only the master with the same safe USB app-flash path:
cd /home/jan/Documents/RFP/WLED-MM/repo
./flash_master.sh
flash_master.sh is now intentionally an app/bootloader/partition update only:
no full erase and no filesystem upload. Use a full clean flash only when the
partition table or filesystem must be deliberately reset.
USB App Flash: Master
Recommended helper:
cd /home/jan/Documents/RFP/WLED-MM/repo
./flash_master.sh
Manual flow:
cd /home/jan/Documents/RFP/WLED-MM/repo
ls /dev/ttyACM* /dev/ttyUSB* 2>/dev/null
PORT=/dev/ttyACM0
ENV=rfp_esp32s3_wroom1_n16r8_master
PATH=/home/jan/Documents/RFP/Finanz_App/node/current/bin:$PATH \
NPM_CONFIG_CACHE=$PWD/.npm-cache \
PLATFORMIO_CORE_DIR=$PWD/.piohome \
PLATFORMIO_PACKAGES_DIR=$PWD/.piohome/packages \
PLATFORMIO_PLATFORMS_DIR=$PWD/.piohome/platforms \
PLATFORMIO_CACHE_DIR=$PWD/.piohome/.cache \
PLATFORMIO_BUILD_CACHE_DIR=$PWD/.piohome/buildcache \
.venv/bin/python -m platformio run -e "$ENV"
.venv/bin/python .piohome/packages/tool-esptoolpy/esptool.py \
--chip esp32s3 \
--port "$PORT" \
--baud 460800 \
--before default_reset \
--after hard_reset \
write_flash -z \
--flash_mode qio \
--flash_freq 80m \
--flash_size 16MB \
0x0 .pio/build/rfp_esp32s3_wroom1_n16r8_master/bootloader.bin \
0x8000 .pio/build/rfp_esp32s3_wroom1_n16r8_master/partitions.bin \
0xe000 .piohome/packages/framework-arduinoespressif32/tools/partitions/boot_app0.bin \
0x10000 build_output/release/WLEDMM_14.7.2-mdev_RFP_N16R8_MASTER_V20260511E.bin
If upload does not start immediately:
- Hold
BOOT - Tap
RESET - Release
BOOT - Run the upload again
USB Clean Flash: Node
Recommended helper:
cd /home/jan/Documents/RFP/WLED-MM/repo
./flash_node.sh
Manual flow:
cd /home/jan/Documents/RFP/WLED-MM/repo
ls /dev/ttyACM* /dev/ttyUSB* 2>/dev/null
PORT=/dev/ttyACM0
ENV=rfp_esp32s3_wroom1_n16r8_3x106
.venv/bin/python .piohome/packages/tool-esptoolpy/esptool.py \
--chip esp32s3 \
--port "$PORT" \
erase_flash
PATH=/home/jan/Documents/RFP/Finanz_App/node/current/bin:$PATH \
NPM_CONFIG_CACHE=$PWD/.npm-cache \
PLATFORMIO_CORE_DIR=$PWD/.piohome \
PLATFORMIO_PACKAGES_DIR=$PWD/.piohome/packages \
PLATFORMIO_PLATFORMS_DIR=$PWD/.piohome/platforms \
PLATFORMIO_CACHE_DIR=$PWD/.piohome/.cache \
PLATFORMIO_BUILD_CACHE_DIR=$PWD/.piohome/buildcache \
.venv/bin/python -m platformio run -e "$ENV" -t clean
PATH=/home/jan/Documents/RFP/Finanz_App/node/current/bin:$PATH \
NPM_CONFIG_CACHE=$PWD/.npm-cache \
PLATFORMIO_CORE_DIR=$PWD/.piohome \
PLATFORMIO_PACKAGES_DIR=$PWD/.piohome/packages \
PLATFORMIO_PLATFORMS_DIR=$PWD/.piohome/platforms \
PLATFORMIO_CACHE_DIR=$PWD/.piohome/.cache \
PLATFORMIO_BUILD_CACHE_DIR=$PWD/.piohome/buildcache \
.venv/bin/python -m platformio run -e "$ENV" -t upload --upload-port "$PORT"
OTA Preflight
Check whether the current devices look OTA-updatable before flashing:
cd /home/jan/Documents/RFP/WLED-MM/repo
.venv/bin/python tools/rfp_update_all_ota.py --preflight-only --no-build
Single node:
cd /home/jan/Documents/RFP/WLED-MM/repo
.venv/bin/python tools/rfp_network_flash.py flash \
--targets 192.168.178.11 \
--firmware .pio/build/rfp_esp32s3_wroom1_n16r8_3x106/firmware.bin \
--expect-release RFP_N16R8_NODE3x106_V20260511E \
--preflight-only
OTA Update: Whole Installation From RFP Wi-Fi
This builds locally and flashes nodes .11 to .16 first, then the master .10.
The master is flashed last so the show controller stays available while the nodes
update.
cd /home/jan/Documents/RFP/WLED-MM/repo
.venv/bin/python tools/rfp_update_all_ota.py
If your PC is not connected to the RFP Wi-Fi and the master is already on the right release, keep the master connected by USB and let the master relay node OTA updates through its own Wi-Fi connection:
cd /home/jan/Documents/RFP/WLED-MM/repo
.venv/bin/python tools/rfp_update_all_ota.py --via-master-usb --port /dev/ttyACM0 --no-build
This node-only relay is still useful for resumes and tests. For full updates,
prefer tools/rfp_update_master_usb_then_nodes.py so the master is flashed and
verified first. The relay streams the node firmware through the master and does
not store the full file on the master filesystem. The default relay baud rate is
921600 for faster node updates; opening /dev/ttyACM0 can reset the ESP32-S3,
so the tool waits briefly before sending commands. If a flaky USB cable or hub
causes serial errors, retry with --relay-baud 115200.
The updater prefers the named release binaries from build_output/release/ when
they exist and verifies the expected RFP release name after reboot:
- Nodes:
RFP_N16R8_NODE3x106_V20260511E - Master:
RFP_N16R8_MASTER_V20260511E
During the controlled migration from older generic WLED-MM builds, the updater
sends WLED's skipValidation=1 upload parameter by default. The update is still
accepted only if the target reboots and then reports the expected RFP release
name in /json/info.
If you explicitly want WLED's release-name validation to block mismatches before upload, use:
cd /home/jan/Documents/RFP/WLED-MM/repo
.venv/bin/python tools/rfp_update_all_ota.py --no-skip-validation
Use existing build artifacts without rebuilding:
cd /home/jan/Documents/RFP/WLED-MM/repo
.venv/bin/python tools/rfp_update_all_ota.py --no-build
Devices that already report the selected RFP release are skipped by default. This avoids reflashing the same binary and then trying to prove an update from an unchanged release string. To force reflashing the same release anyway:
cd /home/jan/Documents/RFP/WLED-MM/repo
.venv/bin/python tools/rfp_update_all_ota.py --no-build --force-current-release
Resume from a failed device:
cd /home/jan/Documents/RFP/WLED-MM/repo
.venv/bin/python tools/rfp_update_all_ota.py --no-build --start-from 192.168.178.14
OTA Update: Single Device
Master:
cd /home/jan/Documents/RFP/WLED-MM/repo
.venv/bin/python tools/rfp_network_flash.py flash \
--targets 192.168.178.10 \
--firmware build_output/release/WLEDMM_14.7.2-mdev_RFP_N16R8_MASTER_V20260511E.bin \
--expect-release RFP_N16R8_MASTER_V20260511E \
--skip-validation
Node:
cd /home/jan/Documents/RFP/WLED-MM/repo
.venv/bin/python tools/rfp_network_flash.py flash \
--targets 192.168.178.11 \
--firmware build_output/release/WLEDMM_14.7.2-mdev_RFP_N16R8_NODE3x106_V20260511E.bin \
--expect-release RFP_N16R8_NODE3x106_V20260511E \
--skip-validation
Why OTA Can Fail After Build Success
OTA updates only the application image. It does not reliably replace bootloader, flash mode, or partition table. If a board still has an old partition layout, do one USB clean flash with the production target first. After that, OTA should be usable again.
The OTA helper is intentionally strict: upload is considered successful if the
device reboot is proven by an offline transition, an uptime reset, or a WLED
transport reset during upload plus the expected RFP release name in /json/info.
When flashing the exact same release again, the transport-reset proof is weaker,
so the whole-installation updater skips already matching devices by default.
Global 2D Timing Check
The /infinity scene controls intentionally expose only one brightness control.
It sits next to Master Speed, starts at 100%, and the old per-row dimmers
are forced to full output by the controller UI.
Global 2D animations derive their beat position from Infinity master time, not
from frame arrival time on each node. Master Speed is BPM, with one beat equal
to one visible 2D step. For example, Checkerd at 240 BPM changes pattern
240 times per minute.
Use Strobe in the /infinity Global 2D mode selector to check sync visually.
Its Pulse Width control is the normal Size control renamed for this mode.
The strobe is rendered from the shared beat phase, so all nodes should flash
in parallel at every BPM value from 20 to 240.
Master Crash Capture
If the master ever restarts unexpectedly, capture the next run with a serial log. This keeps the production partition layout unchanged while still decoding ESP32 panic backtraces.
cd /home/jan/Documents/RFP/WLED-MM/repo
mkdir -p /tmp/rfp-master-crash
PATH=/home/jan/Documents/RFP/Finanz_App/node/current/bin:$PATH \
NPM_CONFIG_CACHE=$PWD/.npm-cache \
PLATFORMIO_CORE_DIR=$PWD/.piohome \
PLATFORMIO_PACKAGES_DIR=$PWD/.piohome/packages \
PLATFORMIO_PLATFORMS_DIR=$PWD/.piohome/platforms \
PLATFORMIO_CACHE_DIR=$PWD/.piohome/.cache \
PLATFORMIO_BUILD_CACHE_DIR=$PWD/.piohome/buildcache \
.venv/bin/python -m platformio device monitor \
-e rfp_esp32s3_wroom1_n16r8_master \
--port /dev/ttyACM0 \
-b 115200 \
--filter esp32_exception_decoder \
--filter log2file
After a crash, save:
- The monitor log from the current directory or PlatformIO log output
- The first
rst:line after reboot - Any
Guru Meditation,panic, or decoded backtrace lines - The current
/json/infofieldsver,release,e32code, ande32text
Do not switch to a coredump partition shortly before the event unless a repeated crash proves that serial logs are not enough.
WLED Backup Mode
The regular WLED UI is intentionally kept available as a fallback.
Show Mode: ONmeans Infinity Sync is active.WLED Backup: ONmeans Infinity Sync is stopped and regular WLED control can be used.
Stop Infinity on the master by API:
curl -X POST http://192.168.178.10/json/infinity \
-H 'Content-Type: application/json' \
-d '{"enabled":false}'
Re-enable later:
curl -X POST http://192.168.178.10/json/infinity \
-H 'Content-Type: application/json' \
-d '{"enabled":true}'
Coldboot Diagnosis
The firmware side is now consolidated into the normal production targets. If a
board still starts only after pressing RESET, capture the serial log directly
after real power-on.
cd /home/jan/Documents/RFP/WLED-MM/repo
PATH=/home/jan/Documents/RFP/Finanz_App/node/current/bin:$PATH \
NPM_CONFIG_CACHE=$PWD/.npm-cache \
PLATFORMIO_CORE_DIR=$PWD/.piohome \
PLATFORMIO_PACKAGES_DIR=$PWD/.piohome/packages \
PLATFORMIO_PLATFORMS_DIR=$PWD/.piohome/platforms \
PLATFORMIO_CACHE_DIR=$PWD/.piohome/.cache \
PLATFORMIO_BUILD_CACHE_DIR=$PWD/.piohome/buildcache \
.venv/bin/python -m platformio device monitor \
-e rfp_esp32s3_wroom1_n16r8_master \
--port /dev/ttyACM0 \
-b 115200
Expected directly after power-on:
rst:0x1 (POWERON_RESET)
SPI_FAST_FLASH_BOOT
If there is no clean boot log until the reset button is pressed, inspect hardware:
EN/CHIP_PUmust not float.- Use a proper pull-up and reset delay, e.g.
10 kOhmpull-up plus1 uFfromENto GND. - If the 3.3 V rail rises slowly or external loads drag it down, use a reset supervisor.
- Check strapping pins and external DMX/LED wiring for backfeeding during power-up.