diff --git a/microphoneSatelite.yaml b/microphoneSatelite.yaml new file mode 100644 index 0000000..43bc7e6 --- /dev/null +++ b/microphoneSatelite.yaml @@ -0,0 +1,382 @@ +substitutions: + name: m5stack-atom-echo + friendly_name: M5Stack Atom Echo + +esphome: + name: ${name} + name_add_mac_suffix: true + friendly_name: ${friendly_name} + min_version: 2025.5.0 + +esp32: + board: m5stack-atom + cpu_frequency: 240MHz + framework: + type: esp-idf + +logger: + +api: + encryption: + key: "q0BKFZS0RQNYuQtSBE63aS7e3R5exeBgn0pWdeCPFs0=" + +ota: + - platform: esphome + id: ota_esphome + +wifi: + ssid: !secret wifi_ssid + password: !secret wifi_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 + +microphone: + - platform: i2s_audio + id: echo_microphone + i2s_din_pin: GPIO23 + adc_type: external + pdm: true + sample_rate: 16000 + correct_dc_offset: true + +speaker: + - platform: i2s_audio + id: echo_speaker + i2s_dout_pin: GPIO22 + dac_type: external + bits_per_sample: 16bit + sample_rate: 16000 + channel: stereo # The Echo has poor playback audio quality when using mon audio + buffer_duration: 60ms + +media_player: + - platform: speaker + name: None + id: echo_media_player + announcement_pipeline: + speaker: echo_speaker + format: WAV + codec_support_enabled: false + buffer_size: 6000 + volume_min: 0.4 + files: + - id: timer_finished_wave_file + file: https://github.com/esphome/wake-word-voice-assistants/raw/main/sounds/timer_finished.wav + on_announcement: + - if: + condition: + - microphone.is_capturing: + then: + - script.execute: stop_wake_word + - light.turn_on: + id: led + blue: 100% + red: 0% + green: 0% + brightness: 100% + effect: none + on_idle: + - script.execute: start_wake_word + - script.execute: reset_led + +voice_assistant: + id: va + micro_wake_word: + microphone: + microphone: echo_microphone + channels: 0 + gain_factor: 4 + media_player: echo_media_player + noise_suppression_level: 2 + auto_gain: 31dBFS + 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_tts_end: + - homeassistant.service: + service: media_player.play_media + data: + entity_id: media_player.smims_voice_assistant + media_content_type: "music" + media_content_id: !lambda 'return x;' + announce: "true" + on_end: + # Handle the "nevermind" case where there is no announcement + - wait_until: + condition: + - media_player.is_announcing: + timeout: 0.5s + # Restart only mWW if enabled; streaming wake words automatically restart + - if: + condition: + - lambda: return id(wake_word_engine_location).state == "On device"; + then: + - wait_until: + - and: + - not: + voice_assistant.is_running: + - not: + speaker.is_playing: + - lambda: id(va).set_use_wake_word(false); + - micro_wake_word.start: + - 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 + - script.execute: start_wake_word + on_client_disconnected: + - script.execute: stop_wake_word + on_timer_finished: + - script.execute: stop_wake_word + - wait_until: + not: + microphone.is_capturing: + - switch.turn_on: timer_ringing + - light.turn_on: + id: led + red: 0% + green: 100% + blue: 0% + brightness: 100% + effect: "Fast Pulse" + - wait_until: + - switch.is_off: timer_ringing + - light.turn_off: led + - switch.turn_off: timer_ringing + +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: + - script.execute: start_wake_word + - 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 + 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 + 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 + - id: start_wake_word + then: + - if: + condition: + and: + - not: + - voice_assistant.is_running: + - lambda: return id(wake_word_engine_location).state == "On device"; + then: + - lambda: id(va).set_use_wake_word(false); + - micro_wake_word.start: + - if: + condition: + and: + - not: + - voice_assistant.is_running: + - lambda: return id(wake_word_engine_location).state == "In Home Assistant"; + then: + - lambda: id(va).set_use_wake_word(true); + - voice_assistant.stop: + - id: stop_wake_word + then: + - if: + condition: + lambda: return id(wake_word_engine_location).state == "In Home Assistant"; + then: + - lambda: id(va).set_use_wake_word(false); + - voice_assistant.stop: + - if: + condition: + lambda: return id(wake_word_engine_location).state == "On device"; + then: + - micro_wake_word.stop: + +switch: + - 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 + restore_mode: ALWAYS_OFF + on_turn_off: + # Turn off the repeat mode and disable the pause between playlist items + - lambda: |- + id(echo_media_player) + ->make_call() + .set_command(media_player::MediaPlayerCommand::MEDIA_PLAYER_COMMAND_REPEAT_OFF) + .set_announcement(true) + .perform(); + id(echo_media_player)->set_playlist_delay_ms(speaker::AudioPipelineType::ANNOUNCEMENT, 0); + # Stop playing the alarm + - media_player.stop: + announcement: true + on_turn_on: + # Turn on the repeat mode and pause for 1000 ms between playlist items/repeats + - lambda: |- + id(echo_media_player) + ->make_call() + .set_command(media_player::MediaPlayerCommand::MEDIA_PLAYER_COMMAND_REPEAT_ONE) + .set_announcement(true) + .perform(); + id(echo_media_player)->set_playlist_delay_ms(speaker::AudioPipelineType::ANNOUNCEMENT, 1000); + - media_player.speaker.play_on_device_media_file: + media_file: timer_finished_wave_file + announcement: true + - 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: + 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: + +micro_wake_word: + on_wake_word_detected: + - voice_assistant.start: + wake_word: !lambda return wake_word; + vad: + models: + - model: okay_nabu + - model: hey_mycroft + - model: hey_jarvis