Skip to content

4. Flash the ESP32

Give your user access to the USB serial port, upload the firmware you built, and confirm the device boots cleanly.

Before you start

You passed checkpoint 6, the board is on USB with a data cable, and you built the firmware in step 2. Upload needs that build.

flowchart LR
  A[USB access] --> B[Upload] --> C[Boot log]

Allow USB access

Linux only lets members of the dialout group use serial ports. Run the setup script once. It installs the udev rules and adds you to the group:

sudo ./scripts/setup-linux-usb.sh
Installing udev rules → /etc/udev/rules.d/99-platformio-udev.rules
Reloading udev
Adding johna to group dialout

Setup complete.
…

The script then lists what to do next. Log out and back in so the new group applies, then unplug and replug the board. Check both:

groups | grep -o dialout
ls -l /dev/ttyACM0 /dev/ttyUSB0 2>/dev/null
dialout
crw-rw-rw- 1 root dialout 166, 0 Nov 12 06:42 /dev/ttyACM0

No serial device? Go back to Validate and recheck the data cable. Boards with Espressif USB Serial/JTAG usually appear as /dev/ttyACM0; a CP210x or CH34x bridge may appear as /dev/ttyUSB0.

Upload

Use the serial device you saw above (example /dev/ttyACM0):

.venv/bin/esphome upload firmware/lux.yaml --device /dev/ttyACM0
…
Connected to ESP32-C3 on /dev/ttyACM0:
Chip type:          ESP32-C3 (QFN32) (revision v0.4)
Features:           Wi-Fi, BT 5 (LE), Single Core, 160MHz, Embedded Flash 4MB (XMC)
…
USB mode:           USB-Serial/JTAG
…
Wrote 1521312 bytes (907415 compressed) at 0x00000000 in 11.3 seconds (1076.4 kbit/s).
Verifying written data...
Hash of data verified.
Hard resetting via RTS pin...
INFO Successfully uploaded program.

This writes the complete firmware.factory.bin from the build step to the board.

Stuck on Connecting...?

Hold BOOT, tap RST (some boards label it EN), release BOOT, then run the command again.

Watch it boot

.venv/bin/esphome logs firmware/lux.yaml --device /dev/ttyACM0
…
[C][wifi:1075]:   AP SSID: 'Lux Setup'
[C][wifi:1075]:   AP Password: 'setup1234'
…
[I][app:130]: setup() finished successfully!
…
[C][logger:225]:   Hardware UART: USB_SERIAL_JTAG
…
[C][i2c:113]: Results from bus scan:
[C][i2c:119]: Found device at address 0x10
…
[C][qr_code:011]:   Value: 'WIFI:S:Lux Setup;T:WPA;P:setup1234;;'
[C][display.mipi_spi:010]:   Model: ST7789V
…

Press Ctrl+C when you have enough. Check:

Look for If it's wrong
The log doesn't restart from the top over and over A reboot loop usually means a wiring short or bad power. Unplug and recheck the wiring
Found device at address 0x10 That's the VEML7700. If you see Found no devices or Communication failed, recheck SDA and SCL on the VEML7700 page
SoftAP Lux Setup Wi‑Fi stack failed to start — uncommon; power-cycle and watch the log again
The display backlight is on Recheck BL → GPIO21 and VCC → 3V3 on the Display page
The screen shows Scan to set up with a QR code Backlight on but blank: recheck the five SPI wires (CS, DC, RST, SCL, SDA). Colours inverted: see below

The LED stays off until Mode or Home Assistant turns it on — that is normal on first boot in Off.

Screen states after Wi‑Fi and in Home Assistant are covered in Configure and test.

Colours look inverted?

That's the firmware, not the wiring. Change invert_colors: true to false in firmware/lux.yaml, build again and upload again.

Done when

  • esphome upload ends with Successfully uploaded program.
  • The log shows the VEML7700 at 0x10 and SoftAP Lux Setup
  • The backlight is on and the screen shows Scan to set up with the QR code

Next: Configure and test