Skip to content

Troubleshooting

Ravi Singh edited this page May 7, 2026 · 2 revisions

Troubleshooting

Common issues in roughly the order users hit them. Each entry has a symptom + diagnosis + fix.

Flash fails with "No serial data received"

Symptom

idf.py flash (or esptool ... write_flash) fails repeatedly. The chip enumerates as /dev/cu.usbmodem* (so USB-CDC is up) but esptool's SYNC packets go unanswered. Sometimes the chip feels warm.

Diagnosis ladder — try in order

  1. Check the port isn't held by another process.

    lsof /dev/cu.usbmodem*

    Common culprits on macOS: LG Calibration (LG monitor calibration daemon), Arduino IDE serial monitor, VSCode serial monitor. Kill any holders before retrying.

  2. Force the C3 into ROM download mode. The BOOT-mode dance:

    • Hold BOOT.
    • While holding BOOT, tap RST.
    • Wait 1 s. Release BOOT.
    • Retry idf.py flash immediately.
  3. Hold BOOT throughout the flash. Some clones need BOOT held continuously, not just sampled at reset. Run the flash command with BOOT still pressed; release only after the flash completes.

  4. Single-button boards. BOOT is sometimes a tiny solder pad on the back, or BOOT = GPIO 9. Bridge GPIO 9 to GND with tweezers while pressing RST.

  5. --before usb_reset. The C3-specific reset:

    python -m esptool --chip esp32c3 -p /dev/cu.usbmodem... -b 460800 \
      --before usb_reset --after hard_reset write_flash @flash_args
  6. macOS USB-CDC stuck state — restart the Mac. When the chip enumerates but esptool can't sync despite all of the above, macOS sometimes caches a stale USB-CDC endpoint state for the C3's USB-Serial-JTAG and won't release it until reboot. This is the documented final-resort fix.

Device boots but no AP, no STA

Symptom

After flashing, the serial output shows boot logs but no AmbiSense-XXXX SSID shows up on a phone scan and the device never joins Wi-Fi.

Most common cause

Stale NVS holding a board profile for a different MCU (e.g. esp32-devkit saved on a C3 from a prior test flash). v6.x has an MCU-mismatch boot guard, but if you're upgrading from a v6.0 alpha build the safest recovery is:

idf.py -p /dev/cu.usbmodem... erase-flash
idf.py -p /dev/cu.usbmodem... flash

erase-flash wipes the NVS partition so the device boots with factory defaults. Confirm via monitor that you see:

Board profile (default): esp32c3-supermini (ESP32-C3 SuperMini)

followed by netmgr starting AP.

Slider in web UI throws ERR_CONNECTION_RESET

Symptom

Dragging a slider in the LEDs or Motion screen flood-fires POST /api/settings and the browser console fills with ERR_CONNECTION_RESET / ERR_EMPTY_RESPONSE.

Cause

The C3 is single-core. The HTTP server, radar UART, motion smoother, and LED render task all run on one RISC-V core. Sliders can fire onChange ~30 times/second; without debouncing, each one was posting at full rate, saturating httpd's max_open_sockets = 7.

Fix

v6.x adds a 300 ms debounced save on the client side. The slider only POSTs once you stop dragging, and multiple slider changes within 300 ms get coalesced into a single batched request body.

If you're seeing this on v6.x, the UI bundle in the firmware might be stale. Re-flash with the latest binary or rebuild the frontend (cd frontend && npm run build then copy dist/index.html into firmware/components/webui/ui.html and re-flash).

Brownout reset loop

Symptom

Device reboots in a loop with Brownout detector was triggered in the serial log.

Cause

The C3's brownout detector is configured at threshold level 7 (~2.7 V). Brownouts on a C3 powered only by USB while driving a long LED strip from the same rail are common.

Fix

  • LED strip on its own PSU. This is the supported architecture. Don't power LEDs from the C3's 5 V/3.3 V rails.
  • For testing with a few LEDs from USB power: keep count ≤ 30 and brightness ≤ 100/255.
  • If your PSU is sized correctly but you still see brownouts, check the wire gauge — 24 AWG is fine for a 30-LED strip, 22 AWG for 100, 20 AWG for 200+.

Radar shows distance 0 or flat

Symptom

The Live tab's distance reads 0 (or 9999) and never changes. Hardware → Radar diagnostic shows either no bytes RX or bytes RX climbing but frames parsed flat.

Diagnosis

  • Bytes RX = 0: nothing is coming from the radar. Check wiring. Common causes:
    • TX/RX swapped (the radar's TX must go to the MCU's RX, not RX→RX).
    • VCC not connected, or radar getting too little voltage (LD2450 wants 5 V).
    • GND not common between MCU and radar.
  • Bytes RX climbing, frames parsed = 0: bytes are arriving but the parser is rejecting them. Common causes:
    • Wrong driver — Hardware → Radar kind shows ld2410 instead of ld2450. Switch + reboot.
    • Wrong baud — LD-family is 256000. If you've forced something else in NVS, fix it.
    • Counterfeit / incompatible radar — a few clones report frames that don't match the documented LD2450 format. Try a different unit.

Fix verification

After fixing, walk in front of the radar and watch:

  • Bytes RX climbs steadily.
  • Frames parsed climbs.
  • Last frame age stays under 200 ms.
  • Distance number on the Live tab changes as you move.

Onboard LED stays solid after boot

Symptom

The C3's onboard LED stays solid (BOOT pattern) more than a few seconds after powering on.

Diagnosis

app_main crashed before reaching set_pattern(AP_MODE) (around line 249 of main.c). The status_led task is alive but never got told to switch.

Fix

Connect via USB-Serial-JTAG and check the serial log:

. ~/esp/esp-idf-v5.5.2/export.sh
idf.py -p /dev/cu.usbmodem... monitor

Look for the panic / abort message. Most common causes:

  • radar_init failing because the UART pin is wrong (rare, the unsafe-pin guard catches most).
  • led_engine_init failing because led_pin got remapped to an invalid pin via NVS override.
  • auth_init panicking on corrupt NVS auth blob.

Recovery: idf.py erase-flash && idf.py flash.

Can't reach the device by hostname

Symptom

http://ambisense-XXXX.local/ doesn't resolve from your phone or laptop.

Diagnosis

mDNS depends on your router and OS. Most home networks support it; some enterprise / hotel / mesh router setups block it.

Fix

Use the device's IP directly:

  • Check your router's DHCP table for the device.
  • Or open http://<ip>/ after finding it via nmap -sn 192.168.1.0/24 or your router's admin page.

If the device falls back to AP mode (you can see AmbiSense-XXXX SSID), it didn't successfully join your home Wi-Fi. Connect to the AP and reconfigure via captive portal at http://192.168.4.1/.

Lights stop in the middle of the strip and never light the rest

Symptom (v6.x)

Walking the full length of an L-shape or U-shape strip, the LEDs follow you for the first arm but go dark on the second arm.

Cause

Single-sensor mounting position is wrong. v6.x requires the LD2450 to have line-of-sight to both arms of the LED run. If you've mounted at one end of the LED strip, the second arm is past the sensor's 60° cone.

Fix

Move the sensor to the inside corner of the L (or centre-back of the U), broadside facing into the corner so both arms sit inside the 60° cone. See LD2450 Mounting Guide for the geometry rationale and a range-test you should run.

If the geometry genuinely can't be covered by a single sensor (a structural wall between flights, for example), v6.x isn't the right firmware for that install — see Migration from v6.0 → What if I can't get single-sensor coverage.

Wi-Fi disconnects randomly

Symptom

Device joins home Wi-Fi but drops every few minutes / hours, eventually re-joins.

Diagnosis

Most common cause: weak signal at the device's location. Check RSSI on the Live tab.

RSSI Quality
> −65 dBm excellent — should never drop
−65 to −75 good
−75 to −85 weak — drops likely under noise
< −85 very weak — drops constant

Fix

  • Move the router or add a mesh node closer to the device.
  • Lock the device to 2.4 GHz (the C3 is 2.4 GHz only, but some "smart" routers steer between bands and confuse it).
  • Set a static IP if your router's DHCP lease is short.

OTA upload fails

Symptom

Drag-drop a .bin in System → Firmware update; upload begins; either fails partway or completes but the device doesn't come back.

Diagnosis

  • Upload fails partway: usually a Wi-Fi disconnect during transfer. Check RSSI; retry on a stable connection.
  • Upload completes, device doesn't come back: the new firmware crashed before ota_mark_valid(). The bootloader rollback should kick in on the next power cycle.

Fix for crashed-after-OTA

  1. Power cycle the device (unplug + replug).
  2. The bootloader notices the previous boot didn't validate; falls back to the previous slot.
  3. Device should come back online with the previous (working) firmware.
  4. If it doesn't recover, USB-flash the previous binary directly.

My question isn't here

Open an issue describing:

  • What firmware version (System → About → version).
  • What hardware (C3 SuperMini? S3-Zero?).
  • What you did.
  • What you expected.
  • What actually happened.
  • Serial log if you can capture one (idf.py monitor).

We read all of them.

Clone this wiki locally