ESP32-LyraTD-MSC x ESPHome

Hi all,

In an effort to free myself from the Google shackles, I came upon the board in the title that looked like a perfect replacement for my Google Home minis, which sadly still haven’t been hacked to run custom firmwares to this day. It has a newer sibling (ESP32-S3-Korvo-1) but it doesn’t seem to bring much to the table and is a bit pricier, I may give it a go later if my current POC is a success.

First a few links:

Does anyone have any experience with this board?

So far I was able to get wifi and audio output working, and I’m trying to figure out how to get the button array to work (they are all tied to a single GPIO pin with specific voltages between 0.3V and 2.8V, I can already read them with an adc sensor). Also trying to figure out how to get some input from the microphone array, this is my first esp project, it’s kind of a lot to take in.

Below my esphome config:

esphome:
  name: lyratd
  friendly_name: lyratd

esp32:
  board: esp-wrover-kit
  framework:
    type: arduino

logger:
  level: debug

api:
  encryption:
    key: ""

ota:
  password: ""

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

i2c:
  sda: GPIO18
  scl: GPIO23

i2s_audio:
  i2s_lrclk_pin: GPIO25
  i2s_bclk_pin: GPIO5

media_player:
  - platform: i2s_audio
    name: LyraTD
    id: zl38063_out
    dac_type: external
    i2s_dout_pin: GPIO26
    mode: stereo

microphone:
  - platform: i2s_audio
    id: zl38063_in
    adc_type: external
    i2s_din_pin: GPIO35
    pdm: false

voice_assistant:
  microphone: zl38063_in

switch:
  - platform: gpio
    pin: 
      number: GPIO21
      inverted: true
    name: speaker
    id: power_switch
    restore_mode: ALWAYS_ON

sensor:
  - platform: adc
    pin: GPIO39
    name: buttons
    update_interval: 100ms
    attenuation: auto

Here was my configuration for ESP32-S3-Korvo-1 buttons:

sensor:
  platform: adc
  internal: true
  pin: 39
  attenuation: 11db
  name: Button ADC
  update_interval: 15ms
  id: adc_adcsensor
  unit_of_measurement: V
  accuracy_decimals: 2
  filters:
    - median:
        window_size: 5
    - delta: 0.1  
  on_value_range:
    - below: 0.55
      then:
          #VOL+
        - lambda: "id(btn_volup).publish_state(true);"
    - above: 0.65
      below: 0.92
      then:
          #VOL-
        - lambda: "id(btn_voldwn).publish_state(true);"
    - above: 1.02
      below: 1.33
      then:
          #Set
        - lambda: "id(btn_set).publish_state(true);"
    - above: 1.43
      below: 1.77
      then:
          #Play
        - lambda: "id(btn_play).publish_state(true);"
    - above: 1.87
      below: 2.15
      then:
          #Mode
        - lambda: "id(btn_mode).publish_state(true);"
    - above: 2.25
      below: 2.56
      then:
          #Rec
        - lambda: "id(btn_rec).publish_state(true);"                      
    - above: 2.8
      then:
          #None
        - lambda: "id(btn_volup).publish_state(false);"
        - lambda: "id(btn_voldwn).publish_state(false);"
        - lambda: "id(btn_set).publish_state(false);"
        - lambda: "id(btn_play).publish_state(false);"
        - lambda: "id(btn_mode).publish_state(false);"
        - lambda: "id(btn_rec).publish_state(false);"  

binary_sensor:
  - platform: template
    name: "Vol Up"
    id: btn_volup        
  - platform: template
    name: "Vol Down"
    id: btn_voldwn        
  - platform: template
    name: "Set"
    id: btn_set        
  - platform: template
    name: "Play"
    id: btn_play        
  - platform: template
    name: "Mode"
    id: btn_mode                        
  - platform: template
    name: "Record"
    id: btn_rec    

I also have this ESP32-LyraTD-MSC board but didn’t have the time to work on it. If I get something working I’ll let you know. By the way, do you have a repository or something to track the project and make contributions?

Edit: Adjusting the value for the button sensor provided @mulcmu I managed to get all the buttons working. Here is the code:

sensor:
  platform: adc
  internal: true
  pin: GPIO39
  attenuation: 11db
  name: buttons
  update_interval: 15ms
  id: adc_adcsensor
  unit_of_measurement: V
  accuracy_decimals: 2
  filters:
    - median:
        window_size: 5
    - delta: 0.1  
  on_value_range:
    - below: 0.4
      then:
          #SET
        - lambda: "id(btn_set).publish_state(true);"
    - above: 0.7
      below: 1
      then:
          #PLAY
        - lambda: "id(btn_play).publish_state(true);"
    - above: 1.2
      below: 1.5
      then:
          #REC
        - lambda: "id(btn_rec).publish_state(true);"
    - above: 1.7
      below: 2
      then:
          #MODE
        - lambda: "id(btn_mode).publish_state(true);"
    - above: 2.15
      below: 2.5
      then:
          #VOL-
        - lambda: "id(btn_voldwn).publish_state(true);"
    - above: 2.7
      below: 3
      then:
          #VOL+
        - lambda: "id(btn_volup).publish_state(true);"                      
    - above: 3
      then:
          #None
        - lambda: "id(btn_volup).publish_state(false);"
        - lambda: "id(btn_voldwn).publish_state(false);"
        - lambda: "id(btn_set).publish_state(false);"
        - lambda: "id(btn_play).publish_state(false);"
        - lambda: "id(btn_mode).publish_state(false);"
        - lambda: "id(btn_rec).publish_state(false);"  

binary_sensor:
  - platform: template
    name: "Vol Up"
    id: btn_volup        
  - platform: template
    name: "Vol Down"
    id: btn_voldwn        
  - platform: template
    name: "Set"
    id: btn_set        
  - platform: template
    name: "Play"
    id: btn_play        
  - platform: template
    name: "Mode"
    id: btn_mode                        
  - platform: template
    name: "Record"
    id: btn_rec 
1 Like

hi… has anyone managed to add the esp32-s3-korvo-1 to esphome and have the microphones and audio output work as a media player? please someone help me with this

Thank you all for the replies, didn’t see the notification, sorry about the delay.

Since then I had made some progress, was able to get the microphone to work, but everytime I try to play audio, either via media player, or the assistant reply, the board crashes and reboots.

My current config:

esphome:
  name: lyratd
  friendly_name: LyraTD
  on_boot: 
    then:
      - media_player.volume_set: 50%

esp32:
  board: esp-wrover-kit
  framework:
    type: arduino
#    version: 2.0.9
#    platform_version: 6.3.0

logger:
  level: DEBUG
  logs:
    adc: INFO
    sensor: INFO

debug:
  update_interval: 5s

i2c:
  sda: GPIO18
  scl: GPIO23

i2s_audio:
  i2s_lrclk_pin: GPIO25
  i2s_bclk_pin: GPIO5

media_player:
  - platform: i2s_audio
    name: Media Player
    dac_type: external
    i2s_dout_pin: GPIO26
    mode: stereo

speaker:
  - platform: i2s_audio
    id: zl38063_out
    dac_type: external
    i2s_dout_pin: GPIO26
    mode: stereo

microphone:
  - platform: i2s_audio
    id: zl38063_in
    adc_type: external
    i2s_din_pin: GPIO35
    pdm: false

voice_assistant:
  speaker: zl38063_out
  microphone: zl38063_in

switch:
  - platform: gpio
    pin: 
      number: GPIO21
      inverted: true
    name: None
    id: power_switch
    restore_mode: ALWAYS_ON
  - platform: gpio
    pin: GPIO22
    id: amp_switch
    name: Speakers
    restore_mode: ALWAYS_ON

button:
  - platform: template
    id: set_button
    on_press:
      - logger.log: Set button pressed
  - platform: template
    id: play_button
    on_press:
      - logger.log: Play button pressed
  - platform: template
    id: rec_button
    name: Record
    on_press:
      - voice_assistant.start:
      - logger.log: Record button pressed
  - platform: template
    id: mode_button
    on_press:
      - logger.log: Mode button pressed
  - platform: template
    id: vol_down_button
    on_press:
      - media_player.volume_down:
      - logger.log: Volume Down button pressed
  - platform: template
    id: vol_up_button
    on_press:
      - media_player.volume_up:
      - logger.log: Volume Up button pressed

sensor:
  - platform: wifi_signal
    name: WiFi Signal
  - platform: uptime
    name: Uptime
  - platform: debug
    free:
      name: "Heap Free"
    block:
      name: "Heap Max Block"
    loop_time:
      name: "Loop Time"
  - platform: adc
    pin: GPIO39
    id: button_array
    accuracy_decimals: 1
    update_interval: 200ms
    attenuation: auto
    on_value_range:
      - above: 0.2
        below: 0.4
        then:
          - button.press: set_button
      - above: 0.7
        below: 0.9
        then:
          - button.press: play_button
      - above: 1.2
        below: 1.4
        then:
          - button.press: rec_button
      - above: 1.7
        below: 1.9
        then:
          - button.press: mode_button
      - above: 2.2
        below: 2.4
        then:
          - button.press: vol_down_button
      - above: 2.7
        below: 2.9
        then:
          - button.press: vol_up_button

text_sensor:
  - platform: debug
    device:
      name: "Device Info"
    reset_reason:
      name: "Reset Reason"

Playing tts sometimes works fine, but it’s very rare compared to crashes. Haven’t found out why it’s so unstable yet.

I see work happening to add ADF support from the espressif framework for the S3 box into ESPHome, hopefully that will also work for the LyraTD. ADF also supports wake words, that would be cool to have compared to having to press a button.

3 Likes

Hey @alucryd,

Thank you for sharing your progress! I’ve tried your config and I’m facing the opposite behavior. Audio playing works flawlessly but recording works 1 out of 10 times. Most of the time I get a pipeline timeout.

By the way, do you have any place to track your progress like a repository or something where contributions could be made??

Kind Regards

1 Like

Hi!

Got it and would like to use it for voice assistant. Managed to configure it as ESPHome with working microphone. Assist works but I have to manually press Rec button. Any hints how to enable Wake word on this device?

This is the last thing I came up with. Wake word working! Other things like volume control is not working as I’m using speaker component rather than media_player.

esphome:
  name: smart-speaker-lyratd
  min_version: 2023.11.0b5

esp32:
  board: esp-wrover-kit
  framework:
    type: esp-idf

debug:
  update_interval: 5s

api:
  encryption:
    key: "YOUR_KEY"

ota:
  password: "YOUR_OTA_PASS"

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password


logger:
  level: DEBUG
  logs:
    adc: INFO
    sensor: INFO

i2c:
  sda: GPIO18
  scl: GPIO23

i2s_audio:
  i2s_lrclk_pin: GPIO25
  i2s_bclk_pin: GPIO5

speaker:
  - platform: i2s_audio
    id: echo_speaker
    dac_type: external
    i2s_dout_pin: GPIO26
    mode: stereo

microphone:
  - platform: i2s_audio
    id: echo_microphone
    adc_type: external
    i2s_din_pin: GPIO35
    pdm: false

voice_assistant:
  id: va
  speaker: echo_speaker
  microphone: echo_microphone
  noise_suppression_level: 2
  auto_gain: 31dBFS
  volume_multiplier: 2.0
  vad_threshold: 3
  on_end:
    - delay: 100ms
    - wait_until:
        not:
          speaker.is_playing:
  on_client_connected:
    - if:
        condition:
          switch.is_on: use_wake_word
        then:
          - voice_assistant.start_continuous:
  on_client_disconnected:
    - if:
        condition:
          switch.is_on: use_wake_word
        then:
          - voice_assistant.stop:

switch:
  - platform: gpio
    pin: 
      number: GPIO21
      inverted: true
    name: None
    id: power_switch
    restore_mode: ALWAYS_ON
  - platform: gpio
    pin: GPIO22
    id: amp_switch
    name: Speakers
    restore_mode: ALWAYS_ON
  - platform: template
    name: Use wake word
    id: use_wake_word
    optimistic: true
    restore_mode: RESTORE_DEFAULT_ON
    entity_category: config
    on_turn_on:
      - lambda: id(va).set_use_wake_word(true);
      - if:
          condition:
            not:
              - voice_assistant.is_running
          then:
            - voice_assistant.start_continuous
    on_turn_off:
      - voice_assistant.stop
      - lambda: id(va).set_use_wake_word(false);

button:
  - platform: template
    id: set_button
    on_press:
      - logger.log: Set button pressed
  - platform: template
    id: play_button
    on_press:
      - logger.log: Play button pressed
  - platform: template
    id: rec_button
    name: Record
    on_press:
      - if:
          condition:
            switch.is_off: use_wake_word
          then:
            - if:
                condition: voice_assistant.is_running
                then:
                  - voice_assistant.stop:
                else:
                  - voice_assistant.start:
          else:
            - voice_assistant.stop
            - delay: 1s
            - voice_assistant.start_continuous:
      - logger.log: Record button pressed
  - platform: template
    id: mode_button
    on_press:
      - logger.log: Mode button pressed
  - platform: template
    id: vol_down_button
    on_press:
      #- media_player.volume_down:
      - logger.log: Volume Down button pressed
  - platform: template
    id: vol_up_button
    on_press:
      #- media_player.volume_up:
      - logger.log: Volume Up button pressed

sensor:
  - platform: adc
    pin: GPIO39
    id: button_array
    accuracy_decimals: 1
    update_interval: 200ms
    attenuation: auto
    on_value_range:
      - above: 0.2
        below: 0.4
        then:
          - button.press: set_button
      - above: 0.7
        below: 0.9
        then:
          - button.press: play_button
      - above: 1.2
        below: 1.4
        then:
          - button.press: rec_button
      - above: 1.7
        below: 1.9
        then:
          - button.press: mode_button
      - above: 2.2
        below: 2.4
        then:
          - button.press: vol_down_button
      - above: 2.7
        below: 2.9
        then:
          - button.press: vol_up_button

external_components:
  - source: github://pr#5230
    components:
      - esp_adf
    refresh: 0s

esp_adf:
1 Like

Thanks for your config, @rikman122 . I was able to run LyraTD as voice assistant with it.
Moreover, I created custom component to control board’s LED’s according to assistant state.
The one thing I can’t resolve is how to debug raw voice data and setup audio parameters to get better results.

Hey @Gromina ! I would love to see your config for running the LED if possible :slight_smile:

It’s quite dirty right now. Just make it possible to turn on|off lights. Will put it on github however.
I thought of making subclass of light or display in future.

@rikman122 Please find my LEDs component here GitHub - Gromina/esphome_devices: my code for esphome devices

There is also LyraTD yaml file with the component’s usage examples.

If you have some ideas on better LEDs component API, please let me know

Thanks for the implementation of LED support. This makes the LyraTD already usable as an assistant without a speaker connected.
Might it be possible to expose the LEDs as a “normal” light / LED strip? Such that we could use the already implemented effects for light components?
This would make using effects depending on the pipeline state much easier, see e.g. this M5tack AtomEcho yaml: https://github.com/esphome/firmware/blob/735ea09e64897b8248baeb2501e524c29e56b3c7/voice-assistant/m5stack-atom-echo.yaml#L68

Just didn’t have enough time to learn this subject. If you have good references and/or PRs. They are welcome! )

Just pushed 1st dirty implementation of monochromatic light for Lyra - https://github.com/Gromina/esphome_devices/tree/master/components/lyratd_light

You can use any specific range of Lyra’s LEDs as one monochromatic light. See readme. And please check if it’s working fine for you

If there are esphome experts, I’m open to suggestions, review, advises on code implementation

Thank you for implementing something that fast! I unfortunately do not have any experience or knowledge regarding programming esphome components. The only thing I found is the deprecated “light.custom” component, which should no longer be used.

Got this mostly working, but had to set the vad_thresold to 1 otherwise it rarely seemed to pickup on the wake word.

Looks like the wake word processing is done server side for these?

Also the light component throws a build error so never did get the lights on the device working.

Edit: still spotty, going to try with the vad_threshold line commented out