11substitutions :
22 name : m5stack-atom-echo
33 friendly_name : M5Stack Atom Echo
4- micro_wake_word_model : okay_nabu # alexa, hey_jarvis, hey_mycroft are also supported
54
65esphome :
76 name : ${name}
87 name_add_mac_suffix : true
98 friendly_name : ${friendly_name}
10- min_version : 2025.2 .0
9+ min_version : 2025.5 .0
1110
1211esp32 :
1312 board : m5stack-atom
13+ cpu_frequency : 240MHz
1414 framework :
1515 type : esp-idf
1616
@@ -42,14 +42,17 @@ microphone:
4242 i2s_din_pin : GPIO23
4343 adc_type : external
4444 pdm : true
45+ sample_rate : 16000
46+ correct_dc_offset : true
4547
4648speaker :
4749 - platform : i2s_audio
4850 id : echo_speaker
4951 i2s_dout_pin : GPIO22
5052 dac_type : external
51- bits_per_sample : 32bit
52- channel : right
53+ bits_per_sample : 16bit
54+ sample_rate : 16000
55+ channel : stereo # The Echo has poor playback audio quality when using mon audio
5356 buffer_duration : 60ms
5457
5558media_player :
@@ -70,14 +73,7 @@ media_player:
7073 condition :
7174 - microphone.is_capturing :
7275 then :
73- - if :
74- condition :
75- lambda : return id(wake_word_engine_location).state == "On device";
76- then :
77- - micro_wake_word.stop :
78- else :
79- - voice_assistant.stop :
80- - script.execute : reset_led
76+ - script.execute : stop_wake_word
8177 - light.turn_on :
8278 id : led
8379 blue : 100%
@@ -87,14 +83,18 @@ media_player:
8783 effect : none
8884 on_idle :
8985 - script.execute : start_wake_word
86+ - script.execute : reset_led
9087
9188voice_assistant :
9289 id : va
93- microphone : echo_microphone
90+ micro_wake_word :
91+ microphone :
92+ microphone : echo_microphone
93+ channels : 0
94+ gain_factor : 4
9495 media_player : echo_media_player
9596 noise_suppression_level : 2
9697 auto_gain : 31dBFS
97- volume_multiplier : 2.0
9898 on_listening :
9999 - light.turn_on :
100100 id : led
@@ -118,8 +118,25 @@ voice_assistant:
118118 brightness : 100%
119119 effect : none
120120 on_end :
121- - delay : 100ms
122- - script.execute : start_wake_word
121+ # Handle the "nevermind" case where there is no announcement
122+ - wait_until :
123+ condition :
124+ - media_player.is_announcing :
125+ timeout : 0.5s
126+ # Restart only mWW if enabled; streaming wake words automatically restart
127+ - if :
128+ condition :
129+ - lambda : return id(wake_word_engine_location).state == "On device";
130+ then :
131+ - wait_until :
132+ - and :
133+ - not :
134+ voice_assistant.is_running :
135+ - not :
136+ speaker.is_playing :
137+ - lambda : id(va).set_use_wake_word(false);
138+ - micro_wake_word.start :
139+ - script.execute : reset_led
123140 on_error :
124141 - light.turn_on :
125142 id : led
@@ -134,11 +151,9 @@ voice_assistant:
134151 - delay : 2s # Give the api server time to settle
135152 - script.execute : start_wake_word
136153 on_client_disconnected :
137- - voice_assistant.stop :
138- - micro_wake_word.stop :
154+ - script.execute : stop_wake_word
139155 on_timer_finished :
140- - voice_assistant.stop :
141- - micro_wake_word.stop :
156+ - script.execute : stop_wake_word
142157 - wait_until :
143158 not :
144159 microphone.is_capturing :
@@ -241,27 +256,37 @@ script:
241256 - light.turn_off : led
242257 - id : start_wake_word
243258 then :
244- - wait_until :
245- and :
246- - media_player.is_idle :
247- - speaker.is_stopped :
248259 - if :
249260 condition :
250- lambda : return id(wake_word_engine_location).state == "On device";
261+ and :
262+ - not :
263+ - voice_assistant.is_running :
264+ - lambda : return id(wake_word_engine_location).state == "On device";
251265 then :
252- - voice_assistant.stop
253- - micro_wake_word.stop :
254- - delay : 1s
255- - script.execute : reset_led
256- - script.wait : reset_led
266+ - lambda : id(va).set_use_wake_word(false);
257267 - micro_wake_word.start :
258- else :
259- - if :
260- condition : voice_assistant.is_running
261- then :
262- - voice_assistant.stop :
263- - script.execute : reset_led
268+ - if :
269+ condition :
270+ and :
271+ - not :
272+ - voice_assistant.is_running :
273+ - lambda : return id(wake_word_engine_location).state == "In Home Assistant";
274+ then :
275+ - lambda : id(va).set_use_wake_word(true);
264276 - voice_assistant.start_continuous :
277+ - id : stop_wake_word
278+ then :
279+ - if :
280+ condition :
281+ lambda : return id(wake_word_engine_location).state == "In Home Assistant";
282+ then :
283+ - lambda : id(va).set_use_wake_word(false);
284+ - voice_assistant.stop :
285+ - if :
286+ condition :
287+ lambda : return id(wake_word_engine_location).state == "On device";
288+ then :
289+ - micro_wake_word.stop :
265290
266291switch :
267292 - platform : template
@@ -321,7 +346,7 @@ select:
321346 condition :
322347 lambda : return x == "In Home Assistant";
323348 then :
324- - micro_wake_word.stop
349+ - micro_wake_word.stop :
325350 - delay : 500ms
326351 - lambda : id(va).set_use_wake_word(true);
327352 - voice_assistant.start_continuous :
@@ -330,14 +355,16 @@ select:
330355 lambda : return x == "On device";
331356 then :
332357 - lambda : id(va).set_use_wake_word(false);
333- - voice_assistant.stop
358+ - voice_assistant.stop :
334359 - delay : 500ms
335- - micro_wake_word.start
360+ - micro_wake_word.start :
336361
337362micro_wake_word :
338363 on_wake_word_detected :
339364 - voice_assistant.start :
340365 wake_word : !lambda return wake_word;
341366 vad :
342367 models :
343- - model : ${micro_wake_word_model}
368+ - model : okay_nabu
369+ - model : hey_mycroft
370+ - model : hey_jarvis
0 commit comments