Add BPM speed control and OTA update workflow
This commit is contained in:
503
docs/rfp-node-flashing.md
Normal file
503
docs/rfp-node-flashing.md
Normal file
@@ -0,0 +1,503 @@
|
||||
# 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 <ip1>,<ip2>,<ip3>,<ip4>,<ip5>,<ip6> \
|
||||
--start-from <ip1> \
|
||||
--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.
|
||||
Reference in New Issue
Block a user