4 Commits
Author SHA1 Message Date
gronod ccf9c68322 Update waveshare-va.yaml 2026-09-23 19:23:35 +01:00
Michal ZaniewiczandClaude Sonnet 5 083b2954b6 Fix mic gain slider snapping back and restore gain at boot
The mic_gain_db template number had a set_action but no optimistic flag, so
TemplateNumber::control() never published the new value: the ES7210 was
reprogrammed but HA kept showing the old value and the slider snapped back.

TemplateNumber::setup() also only publishes the restored value without running
set_action, so a gain saved in flash showed in HA while the codec booted with
the default from audio_adc. Apply it to the ES7210 in on_boot (-100), which is
safe because set_mic_gain() stores the value even before setup completes.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-20 20:08:01 +02:00
Michal ZaniewiczandClaude Sonnet 5 c59223ee77 Add opt-in deep sleep and un-hide the Restart button
Two lifecycle controls, both requested in an issue.

Restart: the `restart_button` already existed but was `disabled_by_default`,
so it showed up as a disabled entity nobody could press without digging into
the entity settings. Dropped the flag - it now lands ready to use under the
device's config section.

Deep sleep: new `deep_sleep` component plus a `boot_button` GPIO binary_sensor
on GPIO0 (the onboard BOOT key, wired direct, not via the expander). A 2-10 s
long-press calls `deep_sleep.enter`, but only when the new `enable_deep_sleep`
substitution is 'true' - off by default, so the stock build is unchanged and
nobody gets a power toggle on BOOT they did not ask for. Wake is a low level on
GPIO0 (BOOT pressed), handled by the deep_sleep wakeup_pin; `INVERT_WAKEUP`
covers BOOT still being held at sleep time. GPIO0 is shared between the
wakeup_pin and the binary_sensor via `allow_other_uses`.

Untested on hardware, hence the beta branch. The power saving on this board is
limited: the ES8311/ES7210 codecs and the WS2812 strip have no hardware
shutdown line and stay powered, so deep sleep here is a low-power idle rather
than a true off. Sleep current not yet measured.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-09 07:10:40 +02:00
Michal Zaniewicz 935b513fb9 Loosen wake-word VAD to reduce premature STT cutoff
Default vad model (cutoff 0.50, window 5) was ending STT capture after
~1.2-1.4s of a brief pause, truncating longer commands
(stt-no-text-recognized). Untested on hardware, hence beta branch.
2026-08-01 15:32:35 +02:00
5 changed files with 56 additions and 32 deletions
-19
View File
@@ -1,24 +1,5 @@
# Changelog
## [1.0.1] - 2026-09-20
Patch release fixing the mic gain control. Tagged `v1.0.1`; the example config
now pins this tag.
### Fixed
- **Mic gain slider snapped back to its old value in Home Assistant.** The
`Mic gain (ES7210)` number had a `set_action` but was not `optimistic`, so the
new value was never published back. The ES7210 was reprogrammed correctly (the
device log showed the new gain), but HA kept displaying the previous value and
reset the slider on the next visit. The number now publishes its state after
every change.
- **A saved mic gain was not applied to the ES7210 after a reboot.** A template
number restores its value from flash in `setup()` and publishes it, but does
not run `set_action`, so HA showed the saved gain while the codec started at
the default from `audio_adc`. `on_boot` (priority -100) now pushes the restored
value to the ES7210. `set_mic_gain()` is safe to call there because the driver
stores the value even before its own setup completes.
## [1.0.0] - 2026-07-18
First stable release. The full voice assistant is confirmed on hardware, the
+2 -2
View File
@@ -12,7 +12,7 @@ core you pull as a package, plus one thin config file you actually edit.
<video src="https://github.com/user-attachments/assets/0eae0230-de47-4f20-a6ea-47f65af35f86" controls width="400"></video>
</div>
> **Status: stable (v1.0.1).** Wake word, STT/TTS, clean playback and the LED
> **Status: stable (v1.0.0).** Wake word, STT/TTS, clean playback and the LED
> ring are confirmed on-device. Full docs are in the
> [Wiki](https://github.com/MichalZaniewicz/esphome-waveshare-esp32-s3-audio-va/wiki);
> the release history is in [CHANGELOG.md](CHANGELOG.md).
@@ -71,7 +71,7 @@ You ──▶ Waveshare ESP32-S3 ──▶ Home Assistant Assist
assign an Assist pipeline.
5. Say "Alexa" (or "OK Nabu"). The ring should go violet.
The example config pins the `v1.0.1` release tag, so a build is reproducible. To
The example config pins the `v1.0.0` release tag, so a build is reproducible. To
move to a newer release, bump `ref:` in the `packages:` block to a later tag (or
`main` to track the latest), then `esphome clean waveshare-va.yaml` (clears the
package cache) and `esphome run waveshare-va.yaml`.
+53 -1
View File
@@ -56,6 +56,13 @@ substitutions:
# ---------------------------------------------------------------------------
hidden_ssid: 'false' # true = fast_connect, required for a hidden SSID
# Software off: long-press the onboard BOOT button (GPIO0) for ~2 s to enter
# deep sleep; a short press wakes the board again. Off by default - set to
# 'true' in your thin config to enable it. Note the savings on this board are
# modest: the ES8311/ES7210 codecs and the LED strip stay powered (no hardware
# shutdown line), so this is closer to a low-power idle than a true power off.
enable_deep_sleep: 'false'
# Media player volume clamps (the onboard amp distorts near the top).
volume_min: '0.4'
volume_max: '0.8'
@@ -209,6 +216,19 @@ ota:
- platform: esphome
id: ota_esphome
# Software off. No run_duration / sleep_duration, so the node never sleeps on
# its own: the only path in is the BOOT-button long-press below, which calls
# deep_sleep.enter only when ${enable_deep_sleep} is 'true'. Wake is a low level
# on GPIO0 (BOOT pressed). GPIO0 is a strapping pin - holding BOOT through a
# power cycle still drops the chip into the serial bootloader, unavoidably.
deep_sleep:
id: deep_sleep_ctrl
wakeup_pin:
number: GPIO0
inverted: true # BOOT is active-low; wake when it is pulled low
allow_other_uses: true # GPIO0 is also the boot_button binary_sensor
wakeup_pin_mode: INVERT_WAKEUP # BOOT still held at sleep time -> flip, don't loop
i2c:
- id: internal_i2c
sda: ${i2c_sda}
@@ -402,6 +422,11 @@ micro_wake_word:
id: okay_nabu
vad:
model: https://github.com/esphome/micro-wake-word-models/raw/main/models/v2/vad.json
# Defaults (cutoff 0.50, window 5) end STT capture after ~1.2-1.4s of a
# short pause, cutting off longer commands. Looser cutoff + wider window
# = more tolerance for pauses/breaths before "end of speech" fires.
probability_cutoff: 0.3
sliding_window_size: 10
on_wake_word_detected:
# Muted (software mute switch)? Do nothing at all.
- if:
@@ -1361,7 +1386,6 @@ button:
id: restart_button
name: "Restart"
entity_category: config
disabled_by_default: true
icon: "mdi:restart"
binary_sensor:
@@ -1391,3 +1415,31 @@ binary_sensor:
inverted: true
on_press:
- media_player.volume_up: external_media_player
# Onboard BOOT button (GPIO0, a strapping pin, direct - not via the expander).
# Held for 2 to 10 s it enters deep sleep, but only when ${enable_deep_sleep}
# is 'true'; otherwise the long-press does nothing. A short press wakes the
# board from deep sleep (handled by the deep_sleep wakeup_pin, not this
# sensor). Disabled in HA by default - it exists here for the sleep gesture.
- platform: gpio
id: boot_button
name: "BOOT button"
entity_category: diagnostic
disabled_by_default: true
pin:
number: GPIO0
mode:
input: true
pullup: true
inverted: true
allow_other_uses: true
on_click:
min_length: 2s
max_length: 10s
then:
- if:
condition:
lambda: 'return strcmp("${enable_deep_sleep}", "true") == 0;'
then:
- logger.log: "BOOT long-press: entering deep sleep"
- deep_sleep.enter: deep_sleep_ctrl
-9
View File
@@ -170,15 +170,6 @@ word. The ESP-mastered two-bus layout needs no patched component.
leaves `media_player.is_announcing` stuck true, and `on_wake_word_detected`
then only ever stops that phantom announcement instead of starting Assist
(wake word detected, nothing happens).
- **HTTPS-only Home Assistant stalls the pipeline.** If HA serves port 8123 over
HTTPS with a certificate that does not cover the LAN address the device reaches
it by, every announcement/TTS fetch fails certificate verification and the
device holds in `STREAMING_MICROPHONE` with no `Starting STT by VAD` line. In
the log this is **identical** to a too-tight `vad` threshold; the tell is
`esp-x509-crt-bundle: Failed to verify certificate` /
`mbedtls_ssl_handshake returned -0x3000` / `Connection failed, sock < 0`. The
fix is HA-side, not firmware: set the HA Internal URL to `http://<ip>:8123`, or
terminate TLS at a reverse proxy and keep HA's own `http:` server plain.
- **Battery monitoring is effectively unavailable**: the divider needs a 0 Ω
resistor soldered (depopulated by default) and **enabling it kills the camera**.
Ratio 3.0. Pin is GPIO1 per schematic, not GPIO8, which is stale demo code.
+1 -1
View File
@@ -44,7 +44,7 @@ substitutions:
packages:
core:
url: https://git.i3omb.com/gronod/esphome-waveshare-esp32-s3-audio-va
ref: v1.0.1 # pinned release; bump to a newer tag, or use 'main' to track latest
ref: v1.0.0 # pinned release; bump to a newer tag, or use 'main' to track latest
files:
- base/core.yaml
refresh: 1d # re-check the ref daily (a pinned tag never moves anyway)