# RFP Infinity Flashing This document covers flashing for both the Infinity master and the ESP32-S3 render nodes. ## Targets - Master target: `rfp_esp32s3_wroom1_n16r8_master` - Conservative master cold-boot target: `rfp_esp32s3_wroom1_n16r8_master_coldboot` - Standard node target: `rfp_esp32s3_wroom1_n16r8_3x106` - Conservative cold-boot test target: `rfp_esp32s3_wroom1_n16r8_3x106_coldboot` Use a cold-boot target when a board only starts reliably after pressing `RESET` following a long power loss. ## 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 now 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 any 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 `/infinity` web UI - Accepts DMX and web commands - Sends Infinity Sync packets to the nodes - Keeps one dummy WLED pixel on `GPIO21` so the regular WLED UI remains valid - Keeps the real WLED status pixel exclusively on `GPIO48` - Repairs old master `cfg.json` LED-bus entries so `GPIO48` is not reused as a normal LED output - Nodes: - Usually `192.168.178.11` to `192.168.178.16` - Render the LED output locally - Receive Infinity Sync from the master The flash procedure is similar for both roles, but the PlatformIO target and `firmware.bin` are different. ## WLED Backup Mode The regular WLED UI is intentionally kept available as a fallback. Important behavior: - The master uses the WLED UI only for a dummy backup pixel on `GPIO21`; the actual onboard status pixel remains WLED's normal status pixel on `GPIO48`. - The master does not render the show LEDs directly. - The nodes can still be controlled through their regular WLED UI. - If Infinity Sync is enabled, the master sends scene state about every `100 ms`. - While those packets arrive, the node UI may appear to ignore changes because the next Infinity packet overwrites the local WLED state. Use regular WLED control as backup in one of these ways: 1. Preferred: open `/infinity` on the master and use the mode button in the top bar: - `Show Mode: ON` means Infinity Sync is active. - `WLED Backup: ON` means Infinity Sync is stopped and regular WLED control can be used. 2. Or stop Infinity on the master by API: ```bash curl -X POST http://192.168.178.10/json/infinity \ -H 'Content-Type: application/json' \ -d '{"enabled":false}' ``` 3. Or disable Infinity on one node for local testing: ```bash curl -X POST http://192.168.178.11/json/infinity \ -H 'Content-Type: application/json' \ -d '{"enabled":false}' ``` Re-enable later: ```bash curl -X POST http://192.168.178.10/json/infinity \ -H 'Content-Type: application/json' \ -d '{"enabled":true}' ``` For hotspot testing, replace the IPs with the current addresses, for example `10.42.0.213`. ## Build: Master ```bash 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: ```text .pio/build/rfp_esp32s3_wroom1_n16r8_master/firmware.bin ``` Conservative master cold-boot build: ```bash 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_coldboot ``` Master cold-boot firmware output: ```text .pio/build/rfp_esp32s3_wroom1_n16r8_master_coldboot/firmware.bin ``` ## Build: Nodes Standard build: ```bash 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 ``` Cold-boot test build: ```bash 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_coldboot ``` Node firmware outputs: ```text .pio/build/rfp_esp32s3_wroom1_n16r8_3x106/firmware.bin .pio/build/rfp_esp32s3_wroom1_n16r8_3x106_coldboot/firmware.bin ``` ## WLAN Flash: Master Flash the master by OTA: ```bash cd /home/jan/Documents/RFP/WLED-MM/repo .venv/bin/python tools/rfp_network_flash.py flash \ --targets 192.168.178.10 \ --firmware .pio/build/rfp_esp32s3_wroom1_n16r8_master/firmware.bin ``` ## WLAN Flash: Single Node Standard firmware to one node: ```bash 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 ``` ## WLAN Flash: Group Flash all six nodes in order: ```bash cd /home/jan/Documents/RFP/WLED-MM/repo .venv/bin/python tools/rfp_network_flash.py flash \ --targets 192.168.178.11,192.168.178.12,192.168.178.13,192.168.178.14,192.168.178.15,192.168.178.16 \ --start-from 192.168.178.11 \ --firmware .pio/build/rfp_esp32s3_wroom1_n16r8_3x106/firmware.bin ``` Resume a failed OTA run from a specific node: ```bash cd /home/jan/Documents/RFP/WLED-MM/repo .venv/bin/python tools/rfp_network_flash.py flash \ --targets 192.168.178.11,192.168.178.12,192.168.178.13,192.168.178.14,192.168.178.15,192.168.178.16 \ --start-from 192.168.178.14 \ --firmware .pio/build/rfp_esp32s3_wroom1_n16r8_3x106/firmware.bin ``` ## WLAN Flash: Full Installation Build standard OTA firmware locally, flash all six nodes sequentially, then flash the master last: ```bash cd /home/jan/Documents/RFP/WLED-MM/repo .venv/bin/python tools/rfp_update_all_ota.py ``` Dry-run without building or flashing: ```bash cd /home/jan/Documents/RFP/WLED-MM/repo .venv/bin/python tools/rfp_update_all_ota.py --dry-run --no-build ``` Resume after an interrupted run: ```bash cd /home/jan/Documents/RFP/WLED-MM/repo .venv/bin/python tools/rfp_update_all_ota.py --start-from 192.168.178.14 ``` Useful variants: ```bash .venv/bin/python tools/rfp_update_all_ota.py --nodes-only .venv/bin/python tools/rfp_update_all_ota.py --master-only .venv/bin/python tools/rfp_update_all_ota.py --no-build .venv/bin/python tools/rfp_update_all_ota.py --subnet 192.168.178.0/24 ``` The full-update helper is only for standard OTA builds: - Nodes: `rfp_esp32s3_wroom1_n16r8_3x106` - Master: `rfp_esp32s3_wroom1_n16r8_master` Cold-boot targets remain USB clean-flash targets because OTA does not rewrite the bootloader/flash-mode layout. Notes: - OTA only works when the laptop and nodes are already in the same IP network. - The OTA helper flashes sequentially, verifies reboot, and then continues to the next node. - The cold-boot test target should be flashed by USB, not by OTA. - Reason: - it changes flash/boot related build settings (`flash_mode`, `memory_type`) - it also uses a different release name for validation - OTA only updates the application image, not the full USB-style flash layout - If you try the cold-boot target by OTA, the usual symptom is exactly this: - upload looks "uncertain" - device stays reachable - uptime keeps increasing - reboot cannot be proven - Reboot verification is now strict: - it records firmware version and uptime before upload - it waits for the node to disappear from the network - it waits for the node to come back - if no offline transition is seen, it requires a clear uptime reset before declaring success - This avoids false positives where a node stays reachable and the script would previously print `OK` too early. ## USB Flash: Master Recommended clean-flash helper: ```bash cd /home/jan/Documents/RFP/WLED-MM/repo ./flash_master.sh ``` Check the serial port: ```bash ls /dev/ttyACM* /dev/ttyUSB* 2>/dev/null ``` Flash the master via USB: ```bash cd /home/jan/Documents/RFP/WLED-MM/repo sudo .venv/bin/python .piohome/packages/tool-esptoolpy/esptool.py \ --chip esp32s3 \ --port /dev/ttyACM0 \ --baud 460800 \ --before no_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 .pio/build/rfp_esp32s3_wroom1_n16r8_master/firmware.bin ``` Conservative master cold-boot firmware: ```bash cd /home/jan/Documents/RFP/WLED-MM/repo sudo .venv/bin/python .piohome/packages/tool-esptoolpy/esptool.py \ --chip esp32s3 \ --port /dev/ttyACM0 \ --baud 460800 \ --before no_reset \ --after hard_reset \ write_flash -z \ --flash_mode qio \ --flash_freq 80m \ --flash_size 16MB \ 0x0 .pio/build/rfp_esp32s3_wroom1_n16r8_master_coldboot/bootloader.bin \ 0x8000 .pio/build/rfp_esp32s3_wroom1_n16r8_master_coldboot/partitions.bin \ 0xe000 .piohome/packages/framework-arduinoespressif32/tools/partitions/boot_app0.bin \ 0x10000 .pio/build/rfp_esp32s3_wroom1_n16r8_master_coldboot/firmware.bin ``` Use USB for the cold-boot master target. OTA is not sufficient for this test because the fix changes bootloader/flash-mode related build settings. ## USB Flash: Single Node Recommended clean-flash helper: ```bash cd /home/jan/Documents/RFP/WLED-MM/repo ./flash_node.sh ``` Check the serial port: ```bash ls /dev/ttyACM* /dev/ttyUSB* 2>/dev/null ``` Standard firmware: ```bash cd /home/jan/Documents/RFP/WLED-MM/repo sudo .venv/bin/python .piohome/packages/tool-esptoolpy/esptool.py \ --chip esp32s3 \ --port /dev/ttyACM0 \ --baud 460800 \ --before no_reset \ --after hard_reset \ write_flash -z \ --flash_mode qio \ --flash_freq 80m \ --flash_size 16MB \ 0x0 .pio/build/rfp_esp32s3_wroom1_n16r8_3x106/bootloader.bin \ 0x8000 .pio/build/rfp_esp32s3_wroom1_n16r8_3x106/partitions.bin \ 0xe000 .piohome/packages/framework-arduinoespressif32/tools/partitions/boot_app0.bin \ 0x10000 .pio/build/rfp_esp32s3_wroom1_n16r8_3x106/firmware.bin ``` Cold-boot test firmware: ```bash cd /home/jan/Documents/RFP/WLED-MM/repo sudo .venv/bin/python .piohome/packages/tool-esptoolpy/esptool.py \ --chip esp32s3 \ --port /dev/ttyACM0 \ --baud 460800 \ --before no_reset \ --after hard_reset \ write_flash -z \ --flash_mode dio \ --flash_freq 80m \ --flash_size 16MB \ 0x0 .pio/build/rfp_esp32s3_wroom1_n16r8_3x106_coldboot/bootloader.bin \ 0x8000 .pio/build/rfp_esp32s3_wroom1_n16r8_3x106_coldboot/partitions.bin \ 0xe000 .piohome/packages/framework-arduinoespressif32/tools/partitions/boot_app0.bin \ 0x10000 .pio/build/rfp_esp32s3_wroom1_n16r8_3x106_coldboot/firmware.bin ``` If upload does not start immediately: 1. Hold `BOOT` 2. Tap `RESET` 3. Release `BOOT` Use USB for the first flash of `rfp_esp32s3_wroom1_n16r8_3x106_coldboot`. After that, if you go back to the normal node firmware, OTA is fine again with the standard node target. ## USB Flash: Group USB flashing always happens physically one board after another unless several boards are connected at the same time. Recommended workflow: 1. Build the desired target once. 2. Plug in node 1 and flash it. 3. Unplug node 1, plug in node 2, repeat. 4. Continue until node 6 is done. If the same serial path is reused each time, the single-node USB command above is the repeatable group-flash procedure. ## Quick Difference: Master vs Node - Master: - Target: `rfp_esp32s3_wroom1_n16r8_master` - Typical IP: `192.168.178.10` - Binary: `.pio/build/rfp_esp32s3_wroom1_n16r8_master/firmware.bin` - Node: - Target: `rfp_esp32s3_wroom1_n16r8_3x106` - Typical IPs: `192.168.178.11` to `192.168.178.16` - Binary: `.pio/build/rfp_esp32s3_wroom1_n16r8_3x106/firmware.bin` - Cold-boot test node: - Target: `rfp_esp32s3_wroom1_n16r8_3x106_coldboot` - Binary: `.pio/build/rfp_esp32s3_wroom1_n16r8_3x106_coldboot/firmware.bin` - Cold-boot test master: - Target: `rfp_esp32s3_wroom1_n16r8_master_coldboot` - Binary: `.pio/build/rfp_esp32s3_wroom1_n16r8_master_coldboot/firmware.bin` ## Recommended Order 1. Test the affected board with its cold-boot target: - master: `rfp_esp32s3_wroom1_n16r8_master_coldboot` - node: `rfp_esp32s3_wroom1_n16r8_3x106_coldboot` 2. Remove power for at least 20 to 30 seconds 3. Verify whether it now boots without pressing `RESET` 4. If it works, roll the same target to the remaining nodes 5. If it still fails, inspect the hardware power-up path on `EN`, 3.3V rail, and any external loads ## Hand-off für andere (teamfähig) Use this section when you want to provide the procedure to other people without hard-coding your local paths. ### Quickstart Template ```bash export RFP_REPO="/path/to/WLED-MM/repo" export NODE_BIN="/path/to/node/bin" # optional if node is already in PATH cd "$RFP_REPO" PATH="$NODE_BIN:$PATH" \ NPM_CONFIG_CACHE="$RFP_REPO/.npm-cache" \ PLATFORMIO_CORE_DIR="$RFP_REPO/.piohome" \ PLATFORMIO_PACKAGES_DIR="$RFP_REPO/.piohome/packages" \ PLATFORMIO_PLATFORMS_DIR="$RFP_REPO/.piohome/platforms" \ PLATFORMIO_CACHE_DIR="$RFP_REPO/.piohome/.cache" \ PLATFORMIO_BUILD_CACHE_DIR="$RFP_REPO/.piohome/buildcache" \ .venv/bin/python -m platformio run -e rfp_esp32s3_wroom1_n16r8_3x106 ``` ### OTA group-flash template ```bash cd "$RFP_REPO" .venv/bin/python tools/rfp_network_flash.py flash \ --targets ,,,,, \ --start-from \ --firmware .pio/build/rfp_esp32s3_wroom1_n16r8_3x106/firmware.bin ``` ### Minimal hand-off checklist 1. Confirm all nodes are reachable in the same network. 2. Build once, then flash. 3. Validate reboot behavior on each node. 4. If one node fails, resume with `--start-from` from that node. 5. Document which target was used (`standard` vs `coldboot`). ### Rollback / removal plan for shared instructions 1. Revert this doc section in git: - `git checkout -- docs/rfp-node-flashing.md` 2. Or remove only the hand-off section manually if the rest should stay. 3. If a deployment should be rolled back, flash the previous known-good firmware bin with the same OTA/USB commands.