Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compilation Error (m5stack Atom Echo) #67

Open
jarodwsams opened this issue Sep 7, 2024 · 2 comments
Open

Compilation Error (m5stack Atom Echo) #67

jarodwsams opened this issue Sep 7, 2024 · 2 comments

Comments

@jarodwsams
Copy link

jarodwsams commented Sep 7, 2024

Let me start off by saying that I do not claim to be an expert of any sort with this stuff. I'm really good at researching and making copy/paste Frankenstein monsters.

I'm trying to incorporate the ADF Pipeline and Media Player (m5stack-atom-echo-adf.yaml) into my existing Atom Echo config, which is based on the examples from ESPHome's Wake Word Voice Assistants repo. My own updated configuration that I'm trying to deploy is below.

The config I've written validates ok, and starts the compile/deploy process. After about 4 minutes, I get an error that I can't find good information on and that I do not understand. I'm hoping someone here can help me identify and resolve the issue.

I'm trying to add the media player component to my existing config so I can keep all the latest updates from ESPHome's sample config (microWakeWord and timers) and have the media player for TTS notifications.

One other thing I'll note. The config that's failing has the esp_adf component commented out. I ran into earlier issues that were resolved by doing this, and I assumed it would be ok since the samples here do not include that component in the config.

Error First

Compiling .pioenvs/my-device-name/driver/sdmmc_host.o
Compiling .pioenvs/my-device-name/driver/sdmmc_transaction.o
Compiling .pioenvs/my-device-name/driver/touch_sensor_common.o
Compiling .pioenvs/my-device-name/driver/esp32/touch_sensor.o
Compiling .pioenvs/my-device-name/driver/adc.o
Compiling .pioenvs/my-device-name/driver/esp32/adc.o
*** [.pioenvs/my-device-name/src/main.o] Error 1
========================= [FAILED] Took 272.00 seconds =========================

My Config

Where config from the atom echo adf example replaced current config, I added line comments so I could easily compare in place.

substitutions:
  name: my-device-name
  friendly_name: My Device Name
  micro_wake_word_model: hey_jarvis

esphome:
  name: ${name}
  name_add_mac_suffix: false
  friendly_name: ${friendly_name}
  min_version: 2024.7.1

esp32:
  board: m5stack-atom
  framework:
    type: esp-idf

logger:

api:
  encryption:
    key: !secret ha_encryption_key

ota:
  - platform: esphome
    id: ota_esphome
    password: !secret ota_password

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
  fast_connect: true
  on_connect:
    - delay: 5s
  ap:
    ssid: !secret fallback_ap_ssid
    password: !secret fallback_ap_password

captive_portal:

button:
  - platform: factory_reset
    id: factory_reset_btn
    name: Factory reset

i2s_audio:
#  - id: i2s_audio_bus
#    i2s_lrclk_pin: GPIO33
#    i2s_bclk_pin: GPIO19
  - id: i2s_dplx
    i2s_lrclk_pin: GPIO33
    i2s_bclk_pin: GPIO19
    access_mode: exclusive

adf_pipeline:
  - platform: i2s_audio
    type: audio_out
    id: adf_i2s_out
    i2s_audio_id: i2s_dplx
    i2s_dout_pin: GPIO22
    fixed_settings: false

  - platform: i2s_audio
    type: audio_in
    id: adf_i2s_in
    i2s_audio_id: i2s_dplx
    i2s_din_pin: GPIO23
    pdm: true
    bits_per_sample: 32bit
    channel: right
    fixed_settings: true

microphone:
#  - platform: i2s_audio
#    id: echo_microphone
#    i2s_din_pin: GPIO23
#    adc_type: external
#    pdm: true
  - platform: adf_pipeline
    id: echo_microphone
    keep_pipeline_alive: false
    pipeline:
      - adf_i2s_in
      - self

#speaker:
#  - platform: i2s_audio
#    id: echo_speaker
#    i2s_dout_pin: GPIO22
#    dac_type: external
#    mode: mono

media_player:
  - platform: adf_pipeline
    id: adf_media_player
    name: m5stack-atom-echo
    keep_pipeline_alive: false
    internal: false
    pipeline:
      - self
      - adf_i2s_out

voice_assistant:
  id: va
  microphone: echo_microphone
#  speaker: echo_speaker
  media_player: adf_media_player
  noise_suppression_level: 2
  auto_gain: 31dBFS
#  volume_multiplier: 2.0
  volume_multiplier: 4.0
#  vad_threshold: 3

  on_listening:
    - light.turn_on:
        id: led
        blue: 100%
        red: 0%
        green: 0%
        effect: "Slow Pulse"

  on_stt_vad_end:
    - light.turn_on:
        id: led
        blue: 100%
        red: 0%
        green: 0%
        effect: "Fast Pulse"

  on_tts_start:
    - light.turn_on:
        id: led
        blue: 100%
        red: 0%
        green: 0%
        brightness: 100%
        effect: none

  on_end:
    - delay: 100ms
    - voice_assistant.stop:
    - wait_until:
        not:
          - voice_assistant.is_running:
          - switch.is_on: timer_ringing
          - media_player.is_playing:
    - if:
        condition:
          switch.is_on: use_wake_word
        then:
        - if:
            condition:
              lambda: return id(wake_word_engine_location).state == "On device";
            then:
              - micro_wake_word.start:
              - script.execute: reset_led
            else:
              - voice_assistant.start_continuous:
              - script.execute: reset_led

  on_error:
    - light.turn_on:
        id: led
        red: 100%
        green: 0%
        blue: 0%
        brightness: 100%
        effect: none
    - delay: 2s
    - script.execute: reset_led

  on_client_connected:
    - delay: 2s  # Give the api server time to settle
    - if:
        condition:
          switch.is_on: use_wake_word
        then:
        - if:
            condition:
              - lambda: return id(wake_word_engine_location).state == "On device";
            then:
              - micro_wake_word.start:
              - script.execute: reset_led
            else:
              - voice_assistant.start_continuous:
              - script.execute: reset_led

  on_client_disconnected:
    - if:
        condition:
          switch.is_on: use_wake_word
        then:
          - voice_assistant.stop:
          - micro_wake_word.stop:

  on_timer_finished:
    - voice_assistant.stop:
    - micro_wake_word.stop:
    - switch.turn_on: timer_ringing
    - wait_until:
        not:
          microphone.is_capturing:
    - light.turn_on:
        id: led
        red: 0%
        green: 100%
        blue: 0%
        brightness: 100%
        effect: "Fast Pulse"
    - while:
        condition:
          switch.is_on: timer_ringing
        then:
#          - lambda: id(echo_speaker).play(id(timer_finished_wave_file), sizeof(id(timer_finished_wave_file)));
          - lambda: id(adf_media_player).play(id(timer_finished_wave_file), sizeof(id(timer_finished_wave_file)));
          - delay: 1s
    - wait_until:
        not:
#          speaker.is_playing:
          media_player.is_playing:
    - light.turn_off: led
    - switch.turn_off: timer_ringing
    - if:
        condition:
          switch.is_on: use_wake_word
        then:
          - if:
              condition:
                - lambda: return id(wake_word_engine_location).state == "On device";
              then:
                - micro_wake_word.start:
                - script.execute: reset_led
              else:
                - voice_assistant.start_continuous:
                - script.execute: reset_led

binary_sensor:
  # button does the following:
  # short click - stop a timer
  # if no timer then restart either microwakeword or voice assistant continuous
  - platform: gpio
    pin:
      number: GPIO39
      inverted: true
    name: Button
    disabled_by_default: true
    entity_category: diagnostic
    id: echo_button
    on_multi_click:
      - timing:
          - ON for at least 50ms
          - OFF for at least 50ms
        then:
          - if:
              condition:
                switch.is_on: timer_ringing
              then:
                - switch.turn_off: timer_ringing
              else:
                - if:
                    condition:
                      switch.is_on: use_wake_word
                    then:
                      - if:
                          condition:
                            - lambda: return id(wake_word_engine_location).state == "On device";
                          then:
                            - voice_assistant.stop
                            - micro_wake_word.stop:
                            - delay: 1s
                            - script.execute: reset_led
                            - script.wait: reset_led
                            - micro_wake_word.start:
                          else:
                            - if:
                                condition: voice_assistant.is_running
                                then:
                                  - voice_assistant.stop:
                                  - script.execute: reset_led
                            - voice_assistant.start_continuous:
      - timing:
          - ON for at least 10s
        then:
          - button.press: factory_reset_btn

light:
  - platform: esp32_rmt_led_strip
    id: led
    name: None
    disabled_by_default: true
    entity_category: config
    pin: GPIO27
    default_transition_length: 0s
    chipset: SK6812
    num_leds: 1
    rgb_order: grb
    rmt_channel: 0
    effects:
      - pulse:
          name: "Slow Pulse"
          transition_length: 250ms
          update_interval: 250ms
          min_brightness: 50%
          max_brightness: 100%
      - pulse:
          name: "Fast Pulse"
          transition_length: 100ms
          update_interval: 100ms
          min_brightness: 50%
          max_brightness: 100%

script:
  - id: reset_led
    then:
      - if:
          condition:
            - lambda: return id(wake_word_engine_location).state == "On device";
            - switch.is_on: use_listen_light
            - switch.is_on: use_wake_word
          then:
            - light.turn_on:
                id: led
                red: 100%
                green: 89%
                blue: 71%
                brightness: 60%
                effect: none
          else:
            - if:
                condition:
                  - lambda: return id(wake_word_engine_location).state != "On device";
                  - switch.is_on: use_listen_light
                then:
                  - light.turn_on:
                      id: led
                      red: 0%
                      green: 100%
                      blue: 100%
                      brightness: 60%
                      effect: none
                else:
                  - light.turn_off: led

switch:
  - platform: template
    name: Use wake word
    id: use_wake_word
    optimistic: true
    restore_mode: RESTORE_DEFAULT_ON
    entity_category: config
    on_turn_on:
      - if:
          condition:
            switch.is_on: use_wake_word
          then:
            - if:
                condition:
                  - lambda: return id(wake_word_engine_location).state == "On device";
                then:
                  - micro_wake_word.start:
                  - script.execute: reset_led
                else:
                  - voice_assistant.start_continuous:
                  - script.execute: reset_led
    on_turn_off:
      - voice_assistant.stop
      - micro_wake_word.stop:
      - lambda: id(va).set_use_wake_word(false);
      - script.execute: reset_led

  - platform: template
    name: Use listen light
    id: use_listen_light
    optimistic: true
    restore_mode: RESTORE_DEFAULT_ON
    entity_category: config
    on_turn_on:
      - script.execute: reset_led
    on_turn_off:
      - script.execute: reset_led

  - platform: template
    id: timer_ringing
    optimistic: true
    internal: true
    restore_mode: ALWAYS_OFF
    on_turn_on:
      - delay: 15min
      - switch.turn_off: timer_ringing

select:
  - platform: template
    entity_category: config
    name: Wake word engine location
    id: wake_word_engine_location
    optimistic: true
    restore_value: true
    options:
      - In Home Assistant
      - On device
    initial_option: On device
    on_value:
      - if:
          condition:
            switch.is_on: use_wake_word
          then:
            - if:
                condition:
                  lambda: return x == "In Home Assistant";
                then:
                  - micro_wake_word.stop
                  - delay: 500ms
                  - lambda: id(va).set_use_wake_word(true);
                  - voice_assistant.start_continuous:
            - if:
                condition:
                  lambda: return x == "On device";
                then:
                  - lambda: id(va).set_use_wake_word(false);
                  - voice_assistant.stop
                  - delay: 500ms
                  - micro_wake_word.start

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

  - source: github://jesserockz/esphome-components
    components: [file]
    refresh: 0s

  - source:
      type: git
      url: https://github.com/gnumpi/esphome_audio
      ref: main
    components: [ adf_pipeline, i2s_audio ]

#esp_adf:

file:
  - id: timer_finished_wave_file
    file: https://github.com/esphome/wake-word-voice-assistants/raw/main/sounds/timer_finished.wav

micro_wake_word:
  on_wake_word_detected:
    - voice_assistant.start:
        wake_word: !lambda return wake_word;
  vad:
  models:
    - model: ${micro_wake_word_model}
@Rep-Hueman
Copy link

My working version: https://github.com/Rep-Hueman/ESPHome

@jarodwsams
Copy link
Author

jarodwsams commented Sep 8, 2024

I think I found the issue. After clearing build files and trying again, I get the following. The message is pretty clear, just not quite sure off the top of my head how to adjust.

/config/esphome/office-voice-assist-b83ea8.yaml: In lambda function:
/config/esphome/office-voice-assist-b83ea8.yaml:215:25: error: 'class esphome::esp_adf::ADFMediaPlayer' has no member named 'play'
- delay: 1s

The error is from this block, where it's trying to play the "timer finished" audio file.

  on_timer_finished:
    - voice_assistant.stop:
    - micro_wake_word.stop:
    - switch.turn_on: timer_ringing
    - wait_until:
        not:
          microphone.is_capturing:
    - light.turn_on:
        id: led
        red: 0%
        green: 100%
        blue: 0%
        brightness: 100%
        effect: "Fast Pulse"
    - while:
        condition:
          switch.is_on: timer_ringing
        then:
#          - lambda: id(echo_speaker).play(id(timer_finished_wave_file), sizeof(id(timer_finished_wave_file)));
          - lambda: id(adf_media_player).play(id(timer_finished_wave_file), sizeof(id(timer_finished_wave_file)));
          - delay: 1s
    - wait_until:

Looking at the adf_media_player component file, it looks like there's a ADFMediaPlayer::set_stream_uri function that takes a URL parameter. I wonder if I can use that, instead.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants