v0.3.0-dev · ESP32 + ESP32-C3

Sleep Tracker installer

Flash the firmware, hand over your WiFi, and land on the device's web app — without touching a terminal. Plug in your ESP32 (classic dev kit) or ESP32-C3 board over USB and click below — the installer auto-detects the chip and picks the right build.

This browser can't flash over USB. Use desktop Chrome, Edge, or Opera. (Firefox and Safari don't expose Web Serial, and iOS browsers can't either.)

New device — install firmware and configure WiFi

Pick this if you just got a blank ESP32 or ESP32-C3 board. The page detects the chip family, flashes ~1.4 MB of firmware (about 8 seconds on a C3, ~30 seconds on a classic ESP32 over a CP2102 UART bridge), and immediately opens the WiFi setup dialog.

Your browser doesn't support flashing over USB. This page must be served over HTTPS for browser flashing. ~30 seconds, start to SPA.

Already installed — just (re)configure WiFi

If the firmware is already on the device and you want to change networks (or you're moving the device to a new house), skip the flash step.

Your browser doesn't support Web Serial. Page must be served over HTTPS.

What you'll see, step by step

  1. Pick the serial port. A small browser dialog asks you to pick a port. On a C3 choose USB JTAG/serial debug unit or the cu.usbmodem* entry; on a classic ESP32 with a CP2102/CH340 bridge choose cu.usbserial-* or cu.SLAB_USBtoUART. Click Connect.
  2. Firmware flashes. You'll see a progress bar going from 0 to 100%. About 8 seconds on a C3 over USB 2.0; ~30 seconds on a classic ESP32 over a UART bridge. Skipped if you used "Configure WiFi only".
  3. WiFi network picker appears. The page asks the firmware to scan and shows the result as a list with signal bars and lock icons. Pick your network. 2.4 GHz only — neither chip's radio can see 5 GHz.
  4. Enter your WiFi password. Click Save. The device tries to connect; you'll see "Provisioning…" then either ✅ Provisioned or ❌ Couldn't connect.
  5. Click "Visit Device". The page hands you a link like http://192.168.1.42/. Open it and you're on the SPA. (A backup mDNS link http://sleep-tracker.local/ is also returned in case DHCP later assigns a different IP.)

Troubleshooting

"Invalid head of packet (0xff): Possible serial noise or corruption"

This means the chip didn't enter download mode — usually the auto-reset transistor on the dev board didn't fire reliably, so the existing firmware kept running while the installer tried to talk to the ROM bootloader. Almost always a CP2102/CH340 + classic ESP32 quirk; rare on ESP32-C3 native USB.

Fix:

  1. Press and hold the BOOT (or IO0) button on the dev board.
  2. While holding it, click Connect & install and pick the serial port.
  3. When the progress bar appears (or after ~3 seconds), release BOOT.

If your board only has a RST/EN button: hold BOOT, tap RST, release RST, then keep holding BOOT until the install starts.

Other things that occasionally help: try a different (data-capable, not charge-only) USB cable; switch USB ports; close any other tab or app holding the serial port (pio device monitor, Arduino Serial Monitor, screen, minicom).

"No serial port chosen" / port doesn't appear

Most likely a missing USB-UART driver. Install the CP2102/CP2104 driver (Silicon Labs) for boards labelled CP2102 USB to UART Bridge, or the CH340/CH341 driver (WCH) for boards with the QinHeng chip. Reboot after install. ESP32-C3 boards with native USB-JTAG don't need any driver.

Flash succeeds but the WiFi setup never appears

Stay on the page after the progress bar finishes — the page asks the firmware to start Improv-Serial provisioning, which takes a few seconds while the device boots and the SDK handshakes. If it never appears, refresh and use Configure WiFi only below the install button instead.

Wiring (one sensor, four wires)

Pin numbers depend on which chip you flashed. Both share the same MAX30102 + (optional) MPU6050 on a single I2C bus.

ESP32-C3 DevKitM-1

MAX30102 VIN3V3 pin
MAX30102 GNDGND
MAX30102 SDAGPIO 4
MAX30102 SCLGPIO 5

Classic ESP32 (DevKit-V1, NodeMCU-32S, etc.)

MAX30102 VIN3V3 pin
MAX30102 GNDGND
MAX30102 SDAGPIO 21
MAX30102 SCLGPIO 22

Optional: an MPU6050 IMU on the same I2C bus. No SD card required — sessions are stored in LittleFS.

What's in the firmware

Live SpO₂ + HR1 Hz aggregated samples streamed over WebSocket. Steady reading even when the finger micro-shifts on the sensor.
Sleep stagerAwake / Light / Deep heuristic from HRV + motion.
Smart alarmWakes you in light sleep within a window.
OTA + rollbackFirmware updates from the SPA, auto-rollback on failure.
Crash recoveryLost-power sessions are recovered on next boot.
PIN auth (optional)Lock mutating endpoints behind a 4-digit PIN.
Resilient sensor initAuto-retries MAX30102 / MPU6050 begin every 5 s, so a sensor wired up after boot just starts working.
Diagnostic API/api/debug/i2c-scan, /api/debug/sensor-raw, /api/debug/hr for fast triage.