Table of Contents
- Troubleshooting
- A change I made was not picked up
- The device does not come back after flashing
- Boot loop, safe mode, or "OTA rollback detected"
- Wake word is detected but nothing happens
- Stuck in STREAMING_MICROPHONE, speech-to-text never starts
- Home Assistant is HTTPS-only and the device cannot fetch audio
- End-of-speech detection (VAD) closes the stream late or never
- Wake word is never detected
- Playback is noise or static
- A faint hiss at boot
- A Pulse effect shows a steady colour instead of pulsing
- Cannot flash over USB
- Getting logs
Troubleshooting
A change I made was not picked up
The core is pulled from GitHub and cached. After editing the ref: in
waveshare-va.yaml (or after a new release), clear the cache before building:
esphome clean waveshare-va.yaml
esphome run waveshare-va.yaml
In the dashboard: Clean Build Files, then Install. Skipping this is the single most common reason a build seems unchanged.
The device does not come back after flashing
Right after an OTA reboot, the API port is closed for a few seconds while the device boots. That is normal. Give it up to a minute.
If it never returns and pings but refuses the API port, or you see repeated resets, it is crash-looping. Read on.
Boot loop, safe mode, or "OTA rollback detected"
The firmware has two safety nets:
- Safe mode: after several failed boots in a row the device boots a minimal
safe mode (Wi-Fi and OTA only) so you can flash a fix. The log says
SAFE MODE IS ACTIVE. - OTA rollback: if a freshly flashed image resets before the boot is marked
successful, ESP-IDF automatically reverts to the previous working image. The log
says
OTA rollback detected.
Both mean the new firmware crashed early. To recover and diagnose:
- Flash a known-good build. Over USB is most reliable, and it also gives you the serial boot log.
- Watch the serial console during boot and look for
Guru Meditation Error,abort()or aBacktrace:line just before the reset. That names the cause.
If you customised the config, the usual culprits are actions that run during
setup before their components exist (for example a select or switch trigger
that touches the LED ring or the voice assistant at boot). Guard such triggers
with the firmware's init_in_progress flag so they only run after on_boot.
Wake word is detected but nothing happens
- The most common cause: no Assist pipeline is assigned. On the device page in Home Assistant, choose Configure and pick a pipeline.
- If you added a standalone boot announcement, note that playing one at boot can leave the media player stuck "announcing", after which a wake word only stops that phantom announcement. This firmware avoids it by playing the boot chime only after the mic is clocking; do not move that logic earlier.
- If the device reaches
STREAMING_MICROPHONEand then stalls with noStarting STT by VADline, see Stuck in STREAMING_MICROPHONE, speech-to-text never starts.
Stuck in STREAMING_MICROPHONE, speech-to-text never starts
Symptom: the wake word is detected, the chime plays, the microphone starts and
the device reaches STREAMING_MICROPHONE, then stalls. Starting STT by VAD and
STT by VAD end never appear in the log. The session ends only on a second wake
word or on the Home Assistant pipeline timeout (around five minutes).
Two unrelated causes produce a near-identical log. Rule out the first before touching the second.
Home Assistant is HTTPS-only and the device cannot fetch audio
If Home Assistant is served over HTTPS on port 8123 with a certificate that
covers a public domain (a DuckDNS or Let's Encrypt hostname, say) but not the LAN
address the device connects to, every announcement and text-to-speech fetch fails
certificate verification. The pipeline never completes, so the device holds in
STREAMING_MICROPHONE. The signature in the device log is:
esp-x509-crt-bundle: Failed to verify certificate
esp-tls-mbedtls: mbedtls_ssl_handshake returned -0x3000
HTTP_CLIENT: Connection failed, sock < 0
The media player validates the server certificate against a bundled CA set and cannot accept a certificate issued for a hostname while it is reaching Home Assistant by bare IP.
Give the device a plain-HTTP path to Home Assistant:
- Set the Home Assistant Internal URL (Settings, System, Network) to
http://<home-assistant-ip>:8123and leave the built-in HTTP server unencrypted. - If the local network must use HTTPS, terminate TLS at a reverse proxy (the
Nginx Proxy Manager add-on, for example) and keep the Home Assistant
http:server plain behind it.
Once the device can reach Home Assistant over plain HTTP the whole round trip works: chime, streaming, speech-to-text, response.
End-of-speech detection (VAD) closes the stream late or never
End of speech is decided on the device by the vad model under
micro_wake_word, not by Home Assistant. The v1.0.0 defaults
(probability_cutoff: 0.50, sliding_window_size: 5) are not reliable in every
room: depending on the noise floor they either cut a speaker off after a short
pause, or never fall below the threshold and hold the stream open until the Home
Assistant timeout.
Looser values are on the beta branch (probability_cutoff: 0.3,
sliding_window_size: 10). To try them, set ref: beta in the packages:
block, run Clean Build Files, then Install.
Wake word is never detected
- Check Microphone Mute is off.
- Raise Wake word sensitivity.
- Speak the wake word clearly:
alexaorokay_nabu. - Confirm the mic came up in the boot log (
ES7210 audio ADC). If it did not, see the cold-boot note in Hardware.
Playback is noise or static
On the stock config this should not happen. If you changed the audio section, the mic must stay pinned to 16-bit: as the I2S master it sets the frame width, and a 32-bit frame against the 16-bit DAC plays back as noise. See Audio architecture.
A faint hiss at boot
The amplifier is gated off until the first playback for exactly this reason. A
hiss before any sound has played usually means the amp gating was changed; the
amp_enable switch should be ALWAYS_OFF at boot and turned on by the media
player on_state.
A Pulse effect shows a steady colour instead of pulsing
Its update_interval is shorter than its transition. Set update_interval to
roughly twice transition_length. The bundled effects are already tuned.
Cannot flash over USB
- Hold BOOT while plugging the board in to force download mode.
- Make sure nothing in your config drives expander pins EXIO6 or EXIO7; driving them can disable USB. A camera left in the DVP connector can also block boot (it sits on strapping pins).
Getting logs
Use the ESPHome dashboard log view, or stream over the native API with
scripts/esplog.py from the repository, which reads the API key from
secrets.yaml and is better for catching boot-time races than the dashboard view.
For a crash backtrace, use the USB serial console.