11 Commits
Author SHA1 Message Date
gronod 1b428898bf Update waveshare-va.yaml 2026-09-23 19:22:30 +01:00
Michal ZaniewiczandClaude Sonnet 5 52d4a878b0 release: v1.0.1
Date the changelog entry for the mic gain fixes and move the pinned release tag
in the example config and README from v1.0.0 to v1.0.1.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-20 20:28:04 +02:00
Michal ZaniewiczandClaude Sonnet 5 bef7bf5e59 docs(changelog): note the mic gain slider and restore fixes
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-20 20:26:22 +02:00
Michal ZaniewiczandClaude Sonnet 5 4dd9a86c16 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:26:06 +02:00
MichalZaniewiczandClaude Sonnet 5 1d0db5df08 skill: note the HTTPS-only Home Assistant pipeline stall
A Home Assistant that forces HTTPS on 8123 with a certificate that does not
cover the LAN IP makes every announcement/TTS fetch fail certificate
verification, and the device holds in STREAMING_MICROPHONE with no "Starting
STT by VAD", identical in the log to a too-tight vad threshold. Add the log
signature and the HA-side fix to the gotchas list. Reported in issue #3.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-10 14:27:54 +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
7 changed files with 83 additions and 7 deletions
+19
View File
@@ -1,5 +1,24 @@
# Changelog # 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 ## [1.0.0] - 2026-07-18
First stable release. The full voice assistant is confirmed on hardware, the First stable release. The full voice assistant is confirmed on hardware, the
+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.
+21 -5
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 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. core you pull as a package, plus one thin config file you actually edit.
> **Status: stable (v1.0.0).** Wake word, STT/TTS, clean playback and the LED <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.1).** Wake word, STT/TTS, clean playback and the LED
> ring are confirmed on-device. Full docs are in the > ring are confirmed on-device. Full docs are in the
> [Wiki](https://github.com/MichalZaniewicz/esphome-waveshare-esp32-s3-audio-va/wiki); > [Wiki](https://github.com/MichalZaniewicz/esphome-waveshare-esp32-s3-audio-va/wiki);
> the release history is in [CHANGELOG.md](CHANGELOG.md). > 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 ## 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 - **Voice assistant**: on-device wake word (`alexa`, `okay_nabu`) via
`micro_wake_word`, the full Home Assistant Assist pipeline (STT / LLM / TTS), `micro_wake_word`, the full Home Assistant Assist pipeline (STT / LLM / TTS),
a wake beep and music ducking while it listens. 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, - **LED ring**: one state machine drives it. Boot, no-Wi-Fi, no-HA, listening,
thinking, replying, timer counting, ringing, volume changed - each a distinct thinking, replying, timer counting, ringing, volume changed - each a distinct
colour/effect. Brightness and the animation for the listening / thinking / colour/effect. Brightness and the animation for the listening / thinking /
replying phases are pickable from HA, from 15 effects: solid, pulses, breathe, replying phases are pickable from HA: solid plus 14 animations - pulses,
wipe, scan, spinner, comet, twinkle, fireworks, fire, rainbows. breathe, wipe, scan, spinner, comet, twinkle, fireworks, fire, rainbows.
- **Timers**: set by voice, with an on-ring countdown and a "Next timer" sensor - **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.) 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. - **Buttons**: the three onboard keys do volume down, play-pause, volume up.
@@ -55,7 +71,7 @@ core you pull as a package, plus one thin config file you actually edit.
assign an Assist pipeline. assign an Assist pipeline.
5. Say "Alexa" (or "OK Nabu"). The ring should go violet. 5. Say "Alexa" (or "OK Nabu"). The ring should go violet.
The example config pins the `v1.0.0` release tag, so a build is reproducible. To The example config pins the `v1.0.1` release tag, so a build is reproducible. To
move to a newer release, bump `ref:` in the `packages:` block to a later tag (or 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 `main` to track the latest), then `esphome clean waveshare-va.yaml` (clears the
package cache) and `esphome run waveshare-va.yaml`. package cache) and `esphome run waveshare-va.yaml`.
@@ -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. - **[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. - **[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. - **[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. - **[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)**. - **[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)**.
+11
View File
@@ -104,6 +104,11 @@ esphome:
- lambda: |- - lambda: |-
setenv("TZ", id(saved_time_zone).c_str(), 1); setenv("TZ", id(saved_time_zone).c_str(), 1);
tzset(); 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. # Diagnostics: an explicit OFF switch that silences the mic completely.
# ON = microphone disabled. (This used to be inverted, so the mic was # ON = microphone disabled. (This used to be inverted, so the mic was
# stopped on every boot with the switch in its default OFF position.) # stopped on every boot with the switch in its default OFF position.)
@@ -1286,6 +1291,12 @@ number:
restore_value: true restore_value: true
initial_value: 24 initial_value: 24
mode: slider 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: set_action:
- lambda: |- - lambda: |-
id(adc_mic).set_mic_gain(x); id(adc_mic).set_mic_gain(x);
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

+9
View File
@@ -170,6 +170,15 @@ word. The ESP-mastered two-bus layout needs no patched component.
leaves `media_player.is_announcing` stuck true, and `on_wake_word_detected` leaves `media_player.is_announcing` stuck true, and `on_wake_word_detected`
then only ever stops that phantom announcement instead of starting Assist then only ever stops that phantom announcement instead of starting Assist
(wake word detected, nothing happens). (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 Ω - **Battery monitoring is effectively unavailable**: the divider needs a 0 Ω
resistor soldered (depopulated by default) and **enabling it kills the camera**. 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. Ratio 3.0. Pin is GPIO1 per schematic, not GPIO8, which is stale demo code.
+2 -2
View File
@@ -43,8 +43,8 @@ substitutions:
packages: packages:
core: 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 ref: v1.0.1 # pinned release; bump to a newer tag, or use 'main' to track latest
files: files:
- base/core.yaml - base/core.yaml
refresh: 1d # re-check the ref daily (a pinned tag never moves anyway) refresh: 1d # re-check the ref daily (a pinned tag never moves anyway)