Troubleshooting¶
Common failure modes, what causes them, and how to recover. For hardware-level diagnostics see the Hardware section.
Boot Issues¶
Symptom: No serial output at boot¶
- Check baud rate — 230 400, 8N1. Not 115 200.
- USB-C cable — must be data-capable (not power-only).
- Try a different USB port — some hubs flake.
- Verify USB power jumper if you removed the battery jumper.
Symptom: Boot loops (repeated === SYSTEM STARTUP ===)¶
Most common causes:
| Cause | Indicator | Fix |
|---|---|---|
FATAL: ... ps_malloc failed |
Boot log shows the failed allocation | PSRAM is missing or mis-detected. Verify the WROOM-1 part has the -N16R8 suffix (16 MB flash, 8 MB PSRAM). Rebuild with PSRAMMode=enabled |
| Watchdog reboot during setup | Guru Meditation Error or rst:0xc reset reason |
A specific setup step is hanging. Comment out subsystems one at a time to bisect — start with initializeHardware() |
| Brownout | rst:0xf (BROWNOUT_RST) |
Power supply can't deliver enough current during boot. Add bulk capacitance at the input |
Stuck on Cannot continue without filesystem |
LittleFS mount failed | A previous flash corrupted the user data partition. Power-cycle once more; if it persists, perform a factory reset via GPIO45 LOW boot |
Symptom: Booted but no WiFi network appears¶
- First boot detection — the firmware enters CONFIG mode automatically on first boot. The AP should be at
ALTERNATOR_WIFI/alternator123. - GPIO46 stuck low — also forces AP mode. Check the boot serial log; "GPIO46 LOW: OPERATIONAL AP MODE" means the pin is being held low.
- GPIO45 stuck low — forces CONFIG mode regardless of saved credentials. Check for "GPIO45 LOW: FORCED CONFIGURATION MODE" in the boot log.
- WiFi hardware fault — rare. Look for "WiFi connection failed" repeats in the serial log.
Forced recovery (any state)¶
| Trick | Effect |
|---|---|
| Hold GPIO45 LOW at boot | Forces CONFIG mode with default AP credentials. Alternator disabled |
| Hold GPIO46 LOW at boot | Forces AP mode with custom credentials. Full alternator operation |
| Hold GPIO41 LOW at boot | Boots from factory partition (recovers from a bad OTA image) |
Each pin has its own dedicated solder pad / pin header on the board — see the schematic for the exact location.
WiFi / Dashboard Issues¶
Symptom: Dashboard won't load¶
- Wrong URL — Client mode uses
http://alternator.local. AP mode useshttp://192.168.4.1. Use HTTP, not HTTPS. - mDNS not resolving — some networks block mDNS. Try the IP directly: in client mode, find the IP from your router's connected-devices list.
- Browser cache — hard-reload (Cmd-Shift-R / Ctrl-F5) once. The dashboard is a single static file, so cache issues are rare but possible.
- Capacitor app — see JavaScript Logic → Reconnect Logic.
Symptom: Dashboard loads but values don't update¶
- Connection indicator (top right) — should be green. Yellow = reconnecting. Red = SSE stream lost. Manual reconnect button forces a retry.
- CSV schema mismatch — open the browser console (F12). A warning like
[CSV1] schema mismatch: ESP32=34, UI=33means the firmware and dashboard versions are out of sync. Re-flash both web files (flashFactoryorflashOTA) and firmware together. - 5+ minutes of disconnects, then auto-retry stops — Reconnect cap hit (
MAX_SSE_RECONNECTS = 10). Press the manual reconnect button.
Symptom: Settings save fails¶
- Password unlocked? — most forms require the password. Enter it in the header.
- Password forgotten — boot with GPIO45 LOW to enter CONFIG mode with default password reset, or perform factory reset via the dashboard.
Charging Issues¶
Symptom: Field never engages (duty stays at 0)¶
Ignitionnot detected — verify wiring to the ignition input (GPIO1, optocoupler). The dashboard showsIGNstatus in the header.OnOfftoggle off — the master alternator-enable toggle in the header.- BMS gate — if
bmsLogic == 1, the BMS input (GPIO42) must be in the active state. CheckbmsLogicLevelOffpolarity setting. - In Idle stage (UseFloat=0 post-absorption) — by design. Will rebulk on voltage sag or discharge current.
- In Lockout — a recent safety event triggered the cooldown (
FIELD_COLLAPSE_DELAY, default 30 s). Wait it out; the dashboard shows remaining seconds. - In Limp Home —
LimpHome == 1is set. Console will show "LIMP HOME MODE" every 30 s. RPM < MinRPMForField— engine not running, or RPM sensor not reading. Check Channel 2 raw voltage on the dashboard.- Weather mode disabled charging —
currentWeatherMode == 1means the forecast says solar is sufficient. Disable in Settings → Weather to override.
Symptom: Field engages but voltage doesn't reach bulk¶
uTargetAmpscapped by RPM table — at low RPM the cap table is low by design. Increase the cap-table entry for your operating RPM if your alternator can sustain it.- Thermal derate —
thermalPenaltyAmps > 0. The temperature loop is reducing current to protect the alternator. Look atAlternatorTemperatureFandprojectedTempF. MaxTableValueceiling — sanity cap on the cap table. Increase only if you understand the consequences.
Symptom: Voltage overshoots target¶
- Group 1/2/3 overvoltage supervisors not tuned — if the dashboard shows frequent
fastOvClampCountincrements andcv_Icollapses, the CV loop is over-correcting. Run the CV Tuning test to find betterVoltageKp/VoltageKivalues. - Load dump —
g_loadDumpCountincrementing means loads are switching off and the current spike is being caught. Working as intended. - System voltage class mismatch — verify
BulkVoltageis in the right range for your battery (e.g. 14.4 V on a 12 V system, not 14.4 V on a 24 V system).
Symptom: Repeated lockouts¶
- Sensor disagreement —
BatteryV(ADS) vsIBV(INA) differ by more thanVoltageDisagreeThresholdforVoltageDisagreeTimeout. Check wiring, calibration, and noise on both inputs. - Voltage spike —
AlternatorHardShutdownVexceeded. This is by design; it means the system saw a dangerous voltage. Look at the cv-log for what happened. - Temperature warning sustained —
TempToUse > TemperatureLimitF + TempWarnExcesscontinuously forTempSustainedTimeout(default 2 min). Reduce alternator load, improve cooling, or raiseTemperatureLimitFif your alternator is rated for higher.
Sensor Issues¶
Symptom: Temperature stale / 20 s cut¶
- TempTask hung — Console will show "CRITICAL: TempTask hung up". Indicates Core 0 has stalled. Most often caused by I²C bus issues affecting other Core 0 work.
- DS18B20 read failures — open Live Data → Stats, look at
tempReadFailCount,tempCrcFailCount,tempCrcRecoveredCount. Climbing CRC failures = noisy bus, marginal pull-up, or corroded crimp. - Auto-disable — after enumeration failure, the task retries every 5 s. If the sensor was hot-unplugged, it stays disabled until reconnected.
Symptom: ADS1115 errors¶
adsI2CErrorCountclimbing — bus contention or wiring fault. Inspect cabling.adsSlowReadCountnon-zero —I2Coperation took > 5 ms. Indicates bus stall. Bench-test with a logic analyzer.ADS1115Disconnected = 1(auto) — 5 consecutive failures. Re-enabling requires reboot, or set to 0 via/getafter fixing the wiring.
Symptom: INA228 errors¶
INA228 read failedin console — the I²C transaction threw an exception. Throttled to one per 10 s.INADisconnected = 1— manual disable (no auto-disable for INA228 right now). Voltage/current freeze at last value.
Symptom: IMU disabled¶
imuEnabled = falsewith "IMU disabled: N I2C errors in 60s" — 10+ I²C failures in any rolling minute. Check IMU wiring and I²C bus integrity. Bus speed is intentionally 800 kHz which is out of spec for the LSM6DSOX — if errors persist, drop to 400 kHz (Wire.setClock(400000)ininitializeHardware()).
Crash / Reset Investigation¶
Reading the reset reason¶
The dashboard's Stats panel shows LastResetReason. Values:
| Reason | Meaning |
|---|---|
POWERON_RESET |
Normal cold boot |
SW_RESET |
Firmware called ESP.restart() (factory reset, scheduled maintenance, post-OTA) |
INT_WDT, TASK_WDT |
Watchdog timeout — Core 1 hung |
PANIC |
Crash — see coredump partition |
BROWNOUT |
Supply voltage dipped below brownout threshold |
Decoding a crash backtrace¶
When the device prints Guru Meditation Error followed by a backtrace, use the addr2line workflow from Configuration → Backtrace Decoding.
Cloud / OTA Issues¶
Symptom: Cloud upload says "queued" but never completes¶
- WiFi RSSI — uploads gate on RSSI ≥ −76 dBm. Weak signal blocks uploads.
fieldOffSettled(10 s)gate — the field must be off for 70 s before uploads run. Cycling the engine on/off resets the timer.- Backoff active — after 5 consecutive failures, uploads suspend for 30 s. Console shows "Cloud sync paused, too many failures."
Symptom: OTA update fails¶
- Signature verification fail — wrong bundle for this device, or the public key in firmware doesn't match the signing private key. Check
OTA_PUBLIC_KEYinXregulator.inoagainst the build pipeline. - Heap integrity fail — system is in a degraded state. Boot from factory partition (GPIO41 LOW) to clear, then retry.
- Mid-download disconnect — automatic rollback. Factory partition keeps running.
Recovery from a bad OTA image¶
- Power off the regulator.
- Ground GPIO41.
- Power on. Boot log will show "We are in factory partition."
- Connect to the dashboard normally and clear the bad OTA from the Cloud → Firmware tab.
Last-Resort Recovery¶
Factory reset (preserves nothing)¶
- Via dashboard — Settings → System → Factory Reset (requires password). Wipes all LittleFS settings, clears all NVS, restarts.
- Via GPIO45 boot — enters CONFIG mode with default credentials so you can at least reach the device, but does NOT wipe settings. Use to recover from a lost password without losing data.
Re-flashing firmware over USB¶
If OTA is broken and GPIO41 boot doesn't help, fall back to USB-C:
- Connect USB-C.
- Hold GPIO0 LOW, press Reset, release GPIO0. The chip enters bootloader mode.
- Run
flashFactoryfrom the project shell.
Firmware re-flash never touches user settings — LittleFS and NVS partitions are preserved.
Getting more help¶
- GitHub Issues — github.com/markliquid1/Regulator2026-public/issues for bug reports and feature requests.
- Console output — the dashboard's Console tab is the live serial-equivalent log. Save it before reporting an issue.
- Stats panel — Live Data → Stats shows error counters and runtime diagnostics. Include them in bug reports.