10 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
Michal ZaniewiczandClaude Opus 4.8 58dafd795e docs(readme): add star CTA and pipeline diagram
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-25 10:33:41 +02:00
Michał Zaniewicz c4d23fca16 Create LICENSE 2026-07-24 07:25:19 +02:00
Michal ZaniewiczandClaude Opus 4.8 fdeac8dfd2 Count the ring effects as solid plus 14 animations
Matches the features image, which counts animations only.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-22 22:26:37 +02:00
Michal ZaniewiczandClaude Opus 4.8 7e8e34e6f1 Update the README features image
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-22 22:24:30 +02:00
Michal ZaniewiczandClaude Opus 4.8 b0adf849aa Add a features image to the README
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-22 22:21:46 +02:00
Michał Zaniewicz ae54fc8ae8 Update README.md 2026-07-22 14:18:57 +02:00
5 changed files with 105 additions and 5 deletions
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2026 Michał Zaniewicz
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+19 -3
View File
@@ -8,13 +8,29 @@ the little AI smart-speaker devkit with a dual-mic array, an ES8311 codec, three
buttons and a 7-LED RGB ring. Pure ESPHome, no custom C firmware: an always-on
core you pull as a package, plus one thin config file you actually edit.
<div align="center">
<video src="https://github.com/user-attachments/assets/0eae0230-de47-4f20-a6ea-47f65af35f86" controls width="400"></video>
</div>
> **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).
```
You ──▶ Waveshare ESP32-S3 ──▶ Home Assistant Assist
(wake word + audio) (STT / LLM / TTS)
```
> [!TIP]
> ⭐ **Enjoying this project?** Every star is real motivation to keep it going.
>
> [![Star this repo](https://img.shields.io/github/stars/MichalZaniewicz/esphome-waveshare-esp32-s3-audio-va?style=social)](https://github.com/MichalZaniewicz/esphome-waveshare-esp32-s3-audio-va)
## What it does
![Home Assistant entities, the LED ring animation picker, the media player and the wake-word controls](docs/features.jpg)
- **Voice assistant**: on-device wake word (`alexa`, `okay_nabu`) via
`micro_wake_word`, the full Home Assistant Assist pipeline (STT / LLM / TTS),
a wake beep and music ducking while it listens.
@@ -24,8 +40,8 @@ core you pull as a package, plus one thin config file you actually edit.
- **LED ring**: one state machine drives it. Boot, no-Wi-Fi, no-HA, listening,
thinking, replying, timer counting, ringing, volume changed - each a distinct
colour/effect. Brightness and the animation for the listening / thinking /
replying phases are pickable from HA, from 15 effects: solid, pulses, breathe,
wipe, scan, spinner, comet, twinkle, fireworks, fire, rainbows.
replying phases are pickable from HA: solid plus 14 animations - pulses,
breathe, wipe, scan, spinner, comet, twinkle, fireworks, fire, rainbows.
- **Timers**: set by voice, with an on-ring countdown and a "Next timer" sensor
in HA. (A daily-alarm engine is present but its entities are hidden by default.)
- **Buttons**: the three onboard keys do volume down, play-pause, volume up.
@@ -68,7 +84,7 @@ has the full guide:
- **[Installation](https://github.com/MichalZaniewicz/esphome-waveshare-esp32-s3-audio-va/wiki/Installation)**: first flash, Home Assistant setup, updating.
- **[Configuration](https://github.com/MichalZaniewicz/esphome-waveshare-esp32-s3-audio-va/wiki/Configuration)**: every substitution and every Home Assistant entity.
- **[Audio architecture](https://github.com/MichalZaniewicz/esphome-waveshare-esp32-s3-audio-va/wiki/Audio-architecture)**: the shared-I2S two-bus design, in depth.
- **[LED ring](https://github.com/MichalZaniewicz/esphome-waveshare-esp32-s3-audio-va/wiki/LED-ring)**: the state machine and all 15 effects.
- **[LED ring](https://github.com/MichalZaniewicz/esphome-waveshare-esp32-s3-audio-va/wiki/LED-ring)**: the state machine and every ring effect.
- **[Hardware](https://github.com/MichalZaniewicz/esphome-waveshare-esp32-s3-audio-va/wiki/Hardware)**: pinout, I2C map, and sourced gotchas.
- **[Troubleshooting](https://github.com/MichalZaniewicz/esphome-waveshare-esp32-s3-audio-va/wiki/Troubleshooting)** and **[FAQ](https://github.com/MichalZaniewicz/esphome-waveshare-esp32-s3-audio-va/wiki/FAQ)**.
+64 -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'
@@ -104,6 +111,11 @@ esphome:
- lambda: |-
setenv("TZ", id(saved_time_zone).c_str(), 1);
tzset();
# Push the mic gain restored from flash into the ES7210. The codec boots
# with `mic_gain` from audio_adc, so without this a saved value would show
# in HA while the hardware sat at the default.
- lambda: |-
id(adc_mic).set_mic_gain(id(mic_gain_db).state);
# Diagnostics: an explicit OFF switch that silences the mic completely.
# ON = microphone disabled. (This used to be inverted, so the mic was
# stopped on every boot with the switch in its default OFF position.)
@@ -204,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}
@@ -397,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:
@@ -1286,6 +1316,12 @@ number:
restore_value: true
initial_value: 24
mode: slider
# Without `optimistic`, a template number with only a set_action never
# publishes the new value back: the slider snapped back to 24 dB in HA even
# though the ES7210 had already been reprogrammed. The restored value is
# applied to the codec in on_boot (-100), since TemplateNumber::setup() only
# publishes it and does not run set_action.
optimistic: true
set_action:
- lambda: |-
id(adc_mic).set_mic_gain(x);
@@ -1350,7 +1386,6 @@ button:
id: restart_button
name: "Restart"
entity_category: config
disabled_by_default: true
icon: "mdi:restart"
binary_sensor:
@@ -1380,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
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

+1 -1
View File
@@ -43,7 +43,7 @@ substitutions:
packages:
core:
url: https://github.com/MichalZaniewicz/esphome-waveshare-esp32-s3-audio-va
url: https://git.i3omb.com/gronod/esphome-waveshare-esp32-s3-audio-va
ref: v1.0.0 # pinned release; bump to a newer tag, or use 'main' to track latest
files:
- base/core.yaml