Files
mangavalkandClaude Opus 5.5 58a7cb03c2 Split the README into docs/ pages, add web UI screenshots
- 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>
2026-10-15 22:42:46 +02:00

3.5 KiB

Flashing the Nano over WiFi

← Back to the README

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:

  1. The uploader (tools/nano_net_upload.py) connects to the ESP32 on TCP port 2323 and tells it the bootloader's baud rate.
  2. 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.
  3. The ESP32 switches its link to the bootloader's baud rate and passes bytes between WiFi and the Nano.
  4. The uploader writes the new firmware and reads it back to verify it.
  5. 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_PIN in src/esp32/config.h to that GPIO, for example 4. The transistor keeps the Nano's 5 V reset line away from the 3.3 V ESP32 pin.
  • For uploads over USB, change board in the nano environment to nanoatmega328new.

Settings

  • ESP32 IP address: upload_port in the nano_ota environment in platformio.ini. You can add a port number: 10.1.1.198:2323. For a one-time different address, use pio 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_TIME and NANO_RESET_DELAY in src/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.