Audio output now works with the following settings (I had previously confused the GPIOs for speaker and mic):
# 1. I2C
i2c:
id: bus_a
sda: GPIO13
scl: GPIO14
scan: True
frequency: 100kHz
# 2. I2S
i2s_audio:
- id: i2s_bus
i2s_lrclk_pin: GPIO45
i2s_bclk_pin: GPIO9
i2s_mclk_pin: GPIO16
# 3. DAC
audio_dac:
- platform: es8311
id: es8311_dac
i2c_id: bus_a
address: 0x18
use_microphone: False
use_mclk: True
sample_rate: 48000
# 4. Speaker
speaker:
- platform: i2s_audio
id: rlcd_speaker_hw
i2s_audio_id: i2s_bus
i2s_dout_pin: GPIO8
dac_type: external
audio_dac: es8311_dac
sample_rate: 48000
- platform: resampler
id: rtttl_resampler
output_speaker: rlcd_speaker_hw
sample_rate: 48000
bits_per_sample: 16
# 5. Media Player
media_player:
- platform: speaker
name: "RLCD Speaker"
id: rlcd_media_player
announcement_pipeline:
speaker: rlcd_speaker_hw
# 6. Power Amplifier Switch
switch:
- platform: gpio
pin: GPIO46
name: "Audio Power"
id: audio_pa_ctrl
restore_mode: ALWAYS_ON
on_turn_off:
- logger.log: "WARNING: Audio Power was turned OFF unexpectedly!"
# 7. tone generator for testing
rtttl:
id: rlcd_buzzer
speaker: rtttl_resampler
gain: 90%
I have added a sound test to the boot sequence:
esphome:
name: rlcd
friendly_name: RLCD
on_boot:
priority: 800
then:
# turn on PA before initializing es8311
- switch.turn_on: audio_pa_ctrl
- delay: 100ms
- speaker.volume_set:
id: rlcd_speaker_hw
volume: 75%
- rtttl.stop
- rtttl.play: "scale:d=4,o=5,b=120:c,d,e,f,g,a,b,c6"
and a doorbell sound on GPIO0
binary_sensor:
- platform: gpio
name: "Boot Button"
id: button_boot
pin:
number: GPIO0
inverted: true
mode: INPUT
on_press:
- component.update: my_display #refresh screen
- logger.log: "Playing direct doorbell..."
- rtttl.stop #interrupt any songs from RTTTL
- rtttl.play: "doorbell:d=8,o=5,b=120:e6,c6,p". #sample doorbell chime
Without the resampler for RTTTL, I only get noise. The 48kHz match the TTS output.
EDIT 2: Microphone via ES7210:
# 8. ADC
audio_adc:
- platform: es7210
id: es7210_adc
i2c_id: bus_a
address: 0x40 # confirmed in your I²C scan
bits_per_sample: 16bit
sample_rate: 16000
# 9. microphone
microphone:
- platform: i2s_audio
id: board_mic
i2s_audio_id: i2s_bus
i2s_din_pin: GPIO10
adc_type: external
pdm: false
bits_per_sample: 16bit # must match ES7210
sample_rate: 16000 # must match ES7210
channel: left # ES7210 default output channel
Tested with voice assistant triggered by pressing User button (GPIO18)
- platform: gpio
name: "Button Key (GPIO18)"
id: button_key
pin:
number: GPIO18
inverted: true
mode: INPUT
on_multi_click:
# Single press → toggle voice assistant
- timing:
- ON for 50ms to 350ms
- OFF for at least 400ms
then:
- if:
condition:
voice_assistant.is_running:
then:
- voice_assistant.stop:
else:
- rtttl.stop
- rtttl.play: "listen:d=16,o=6,b=180:c,e" # tone BEFORE mic starts
- delay: 200ms # wait for tone to finish
- voice_assistant.start:
- globals.set:
id: is_inverted
value: !lambda 'return !id(is_inverted);'
# 2. Force the display to redraw immediately with new colors
- component.update: my_display
If you use one button to trigger VA like here, no need to press it again after talking. That will likely stop the pipeline before any voice commands have been recognized, so it’s there to cancel things.
I am inverting the display while the pipeline is active as a visual indicator.