- README is the overview; web UI, pages, Home Assistant, how it works, wiring, Nano over WiFi and the recovery app have their own page in docs/. - docs/web-ui.md has a screenshot of every tab, made with headless Edge by tools/make_webui_screenshots.py. - The web UI opens a page in the editor with #pages/<name>. Version 2.7.2. - The reply wire is fitted (flashing the Nano over WiFi works). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
3.5 KiB
Flashing the Nano over WiFi
The ESP32 can flash the Nano for you, so you don't need a USB cable at the display:
pio run -e nano_ota -t upload
What happens:
- The uploader (tools/nano_net_upload.py) connects to the ESP32 on TCP port 2323 and tells it the bootloader's baud rate.
- The ESP32 pauses the clock and switches the relay off for 1 second, then on again. If the reset wire is fitted, it also pulses the Nano's RESET pin. This restarts the Nano, and its bootloader starts.
- The ESP32 switches its link to the bootloader's baud rate and passes bytes between WiFi and the Nano.
- The uploader writes the new firmware and reads it back to verify it.
- When the uploader disconnects, the ESP32 switches the relay off. The clock powers the Nano on again with the new firmware and continues.
The display goes dark for the duration of the upload, which takes a few seconds.
Requirements
- The reply wire must be connected: Nano D1 (TX) → voltage divider → ESP32 GPIO 16. The uploader needs the bootloader's answers.
- The ESP32 must be running firmware with the flash bridge (this version or newer).
Bootloaders
Flashing the Nano's firmware never changes its bootloader. Both common Nano bootloaders are supported:
| Bootloader | Baud | Starts after a power cycle | Reset wire |
|---|---|---|---|
| Old bootloader (ATmegaBOOT), the one this Nano has now | 57600 | Yes | Not needed |
| Optiboot ("new bootloader") | 115200 | No, only after a reset-pin reset | Required |
By default (--baud=auto in upload_flags) the uploader tries 57600 first and then
115200. Set --baud=57600 or --baud=115200 to skip the other attempt.
If you ever replace the bootloader with Optiboot:
- Fit the reset wire: ESP32 GPIO → 1 kΩ → base of an NPN transistor (e.g. 2N2222 or
BC547). Connect the collector to Nano RESET and the emitter to GND. Set
NANO_RESET_PINinsrc/esp32/config.hto that GPIO, for example4. The transistor keeps the Nano's 5 V reset line away from the 3.3 V ESP32 pin. - For uploads over USB, change
boardin thenanoenvironment tonanoatmega328new.
Settings
- ESP32 IP address:
upload_portin thenano_otaenvironment inplatformio.ini. You can add a port number:10.1.1.198:2323. For a one-time different address, usepio run -e nano_ota -t upload --upload-port 10.1.1.50. - Port, reset pin and timings:
NANO_FLASH_PORT,NANO_RESET_PIN,NANO_POWER_OFF_TIMEandNANO_RESET_DELAYinsrc/esp32/config.h.
If it fails
| Message | Cause |
|---|---|
can't connect to ... |
Wrong IP address, or the ESP32 is offline |
the ESP32 flash bridge didn't accept the request |
The ESP32 runs older firmware without the flash bridge. Flash it first (esp32 or esp32_usb). |
no answer from the Nano bootloader |
Reply wire missing, or the Nano has Optiboot and the reset wire is missing |
bad reply to command ... / verify failed |
Connection problem. Try again. A failed upload can leave the Nano without working firmware, but the bootloader itself is never overwritten, so flashing again (over WiFi or USB) always fixes it. |
The ESP32 ends the session after 10 seconds without data, so the clock always resumes, even if the uploader is interrupted.
Security: anyone on your network can connect to port 2323 and flash the Nano, just like the ESP32's own OTA has no password. Keep the display on a trusted network.