Atomic Echo Base

The following products are supported:

Atomic Echo Base

Below is the detailed support for Atomic Echo Base on the host:

Controller

Atomic Echo Base

Atom Echo

Atom Lite

Atom Matrix

AtomS3

AtomS3 Lite

AtomS3R

AtomS3R-CAM

AtomS3R-Ext

UiFlow2 Example

Play WAV file

Open the atoms3_play_wav_example.m5f2 project in UiFlow2.

66.wav

This example reads an audio file from the file system and plays it.

UiFlow2 Code Block:

atoms3_play_wav_example.png

Example output:

None

Playback Controls

Open the atoms3_playback_controls_example.m5f2 project in UiFlow2.

66.wav

This example demonstrates how to control playback using the AtomicEchoBase class.

Play the audio for 1 second, pause for 1 second, and then resume playing.

UiFlow2 Code Block:

atoms3_playback_controls_example.png

Example output:

None

Record Audio

Open the atoms3_record_audio_example.m5f2 project in UiFlow2.

This example records audio from the microphone and saves it to a PCM buffer, then plays it out through the speaker.

UiFlow2 Code Block:

atoms3_record_audio_example.png

Example output:

None

MicroPython Example

Play WAV file

This example reads an audio file from the file system and plays it.

MicroPython Code Block:

 1# SPDX-FileCopyrightText: 2025 M5Stack Technology CO LTD
 2#
 3# SPDX-License-Identifier: MIT
 4
 5import os, sys, io
 6import M5
 7from M5 import *
 8from hardware import I2C
 9from hardware import Pin
10from base import AtomicEchoBase
11import time
12
13
14i2c1 = None
15base_echo = None
16
17
18def setup():
19    global i2c1, base_echo
20
21    M5.begin()
22    i2c1 = I2C(1, scl=Pin(39), sda=Pin(38), freq=100000)
23    base_echo = AtomicEchoBase(i2c1, 0x18, 1, 16000, 8, 6, 7, 5)
24    base_echo.play_wav_file("/flash/res/audio/66.wav")
25    time.sleep(1)
26    base_echo.pause()
27    time.sleep(1)
28    base_echo.resume()
29
30
31def loop():
32    global i2c1, base_echo
33    M5.update()
34
35
36if __name__ == "__main__":
37    try:
38        setup()
39        while True:
40            loop()
41    except (Exception, KeyboardInterrupt) as e:
42        try:
43            from utility import print_error_msg
44
45            print_error_msg(e)
46        except ImportError:
47            print("please update to latest firmware")

Example output:

None

Playback Controls

This example demonstrates how to control playback using the AtomicEchoBase class.

Play the audio for 1 second, pause for 1 second, and then resume playing.

MicroPython Code Block:

 1# SPDX-FileCopyrightText: 2025 M5Stack Technology CO LTD
 2#
 3# SPDX-License-Identifier: MIT
 4
 5import os, sys, io
 6import M5
 7from M5 import *
 8from hardware import I2C
 9from hardware import Pin
10from base import AtomicEchoBase
11import time
12
13
14i2c1 = None
15base_echo = None
16
17
18def setup():
19    global i2c1, base_echo
20
21    M5.begin()
22    i2c1 = I2C(1, scl=Pin(39), sda=Pin(38), freq=100000)
23    base_echo = AtomicEchoBase(i2c1, 0x18, 1, 16000, 8, 6, 7, 5)
24    base_echo.play_wav_file("/flash/res/audio/66.wav")
25    time.sleep(1)
26    base_echo.pause()
27    time.sleep(1)
28    base_echo.resume()
29
30
31def loop():
32    global i2c1, base_echo
33    M5.update()
34
35
36if __name__ == "__main__":
37    try:
38        setup()
39        while True:
40            loop()
41    except (Exception, KeyboardInterrupt) as e:
42        try:
43            from utility import print_error_msg
44
45            print_error_msg(e)
46        except ImportError:
47            print("please update to latest firmware")

Example output:

None

Record Audio

This example records audio from the microphone and saves it to a PCM buffer, then plays it out through the speaker.

MicroPython Code Block:

 1# SPDX-FileCopyrightText: 2025 M5Stack Technology CO LTD
 2#
 3# SPDX-License-Identifier: MIT
 4
 5import os, sys, io
 6import M5
 7from M5 import *
 8from hardware import I2C
 9from hardware import Pin
10from base import AtomicEchoBase
11
12
13i2c1 = None
14base_echo = None
15
16
17def setup():
18    global i2c1, base_echo
19
20    M5.begin()
21    i2c1 = I2C(1, scl=Pin(39), sda=Pin(38), freq=100000)
22    base_echo = AtomicEchoBase(i2c1, 0x18, 1, 16000, 8, 6, 7, 5)
23    base_echo.record(rate=16000, bits=16, channel=AtomicEchoBase.STEREO, duration=500)
24    base_echo.play_raw(
25        base_echo.pcm_buffer, rate=16000, bits=16, channel=AtomicEchoBase.STEREO, duration=-1
26    )
27
28
29def loop():
30    global i2c1, base_echo
31    M5.update()
32
33
34if __name__ == "__main__":
35    try:
36        setup()
37        while True:
38            loop()
39    except (Exception, KeyboardInterrupt) as e:
40        try:
41            from utility import print_error_msg
42
43            print_error_msg(e)
44        except ImportError:
45            print("please update to latest firmware")

Example output:

None

AtomicEchoBase

class base.echo.AtomicEchoBase(*args, **kwargs)

Bases: object

Create an AtomicEchoBase object.

Parameters:
  • i2c (I2C) – I2C object

  • address (int) – The I2C address of the ES8311. Default is 0x18.

  • i2s_port (int) – The I2S port number. Default is 1.

  • sample_rate (int) – The sample rate of the audio. Default is 16000.

  • i2s_sck (int) – The I2S SCK pin. Default is -1.

  • i2s_ws (int) – The I2S WS pin. Default is -1.

  • i2s_di (int) – The I2S DI pin. Default is -1.

  • i2s_do (int) – The I2S DO pin. Default is -1.

UIFLOW2:

init.png

Micropython:

from hardware import I2C
from hardware import Pin
from base import AtomicEchoBase

# atom echo
i2c1 = I2C(1, scl=Pin(21), sda=Pin(25), freq=100000)
base_echo = AtomicEchoBase(i2c1, address=0x18, i2s_port=1, sample_rate=44100, i2s_sck=33, i2s_ws=19, i2s_di=23, i2s_do=22)

# atom lite
i2c1 = I2C(1, scl=Pin(21), sda=Pin(25), freq=100000)
base_echo = AtomicEchoBase(i2c1, address=0x18, i2s_port=1, sample_rate=44100, i2s_sck=33, i2s_ws=19, i2s_di=23, i2s_do=22)

# atom matrix
i2c1 = I2C(1, scl=Pin(21), sda=Pin(25), freq=100000)
base_echo = AtomicEchoBase(i2c1, address=0x18, i2s_port=1, sample_rate=44100, i2s_sck=33, i2s_ws=19, i2s_di=23, i2s_do=22)

# atoms3 / atoms3 lite
i2c1 = I2C(1, scl=Pin(39), sda=Pin(38), freq=100000)
base_echo = AtomicEchoBase(i2c1, address=0x18, i2s_port=1, sample_rate=44100, i2s_sck=8, i2s_ws=6, i2s_di=7, i2s_do=5)

# atoms3r / atoms3r-cam / atoms3-ext
i2c1 = I2C(1, scl=Pin(39), sda=Pin(38), freq=100000)
base_echo = AtomicEchoBase(i2c1, address=0x18, i2s_port=1, sample_rate=44100, i2s_sck=8, i2s_ws=6, i2s_di=7, i2s_do=5)

base_echo.speaker.tone(2000, 1000)
base_echo.speaker.playWavFile('res/audio/66.wav')
MONO = 1

Mono

STEREO = 2

Stereo

play_wav_file(file)

Play a WAV file.

Parameters:

file (str) – The path of the WAV file to play.

Returns:

None

Return type:

None

UiFlow2 Code Block:

play_wav_file.png

MicroPython Code Block:

base_echo.play_wav_file("/flash/res/audio/test.wav")
tone(freq, duration)

Play simple tone sound.

Parameters:
  • freq (int) – Frequency of the tone in Hz.

  • duration (int) – Duration of the tone in milliseconds.

Returns:

None

Return type:

None

UiFlow2 Code Block:

tone.png

MicroPython Code Block:

base_echo.tone(2000, 50)
play_wav(buf, duration=-1)

Play a WAV buffer.

Parameters:
  • buf (bytes) – The WAV buffer to play.

  • duration (int) – Duration of the WAV buffer in milliseconds. when duration is -1, it will play until stopped. (default is -1).

Returns:

None

Return type:

None

UiFlow2 Code Block:

play_wav.png

MicroPython Code Block:

base_echo.play_wav(wav_buffer, duration=1000)
play_raw(buf, rate=16000, bits=16, channel=2, duration=-1)

Play a pcm buffer.

Parameters:
  • buf (bytes) – The PCM buffer to play.

  • rate (int) – Sample rate (default is 16000).

  • bits (int) – Bit depth (default is 16).

  • channel (int) – Number of channels (default is 2).

  • duration (int) – Duration of the PCM buffer in milliseconds. when duration is -1, it will play until stopped. (default is -1).

Returns:

None

Return type:

None

UiFlow2 Code Block:

play_raw.png

MicroPython Code Block:

base_echo.play_raw(pcm_buffer, rate=16000, bits=16, channel=2, duration=1000)
pause()

Pause the playback.

UiFlow2 Code Block:

pause.png

MicroPython Code Block:

audio.tone(2000, 100)
time.sleep(0.05)
base_echo.pause()
time.sleep(0.05)
base_echo.resume()
Return type:

None

resume()

Resume the playback.

UiFlow2 Code Block:

resume.png

MicroPython Code Block:

audio.tone(2000, 100)
time.sleep(0.05)
base_echo.pause()
time.sleep(0.05)
base_echo.resume()
stop()

Stop the playback.

UiFlow2 Code Block:

stop.png

MicroPython Code Block:

audio.tone(2000, 100)
time.sleep(0.05)
base_echo.stop()
get_volume()

Get the speaker volume level.

Returns:

The volume level (0-100).

Return type:

int

UiFlow2 Code Block:

get_volume.png

MicroPython Code Block:

base_echo.get_volume()
set_volume(volume)

Set the speaker volume level.

Parameters:

volume (int) – The volume level (0-100).

UiFlow2 Code Block:

set_volume.png

MicroPython Code Block:

base_echo.set_volume(50)
record_wav_file(path, rate=16000, bits=16, channel=2, duration=3000)

Record audio to a WAV file.

Parameters:
  • path (str) – The path to save the WAV file.

  • rate (int) – Sample rate (default is 16000).

  • bits (int) – Bit depth (default is 16).

  • channel (int) – Number of channels (default is 2).

  • duration (int) – Duration of the recording in milliseconds (default is 3000).

UiFlow2 Code Block:

record_wav_file.png

MicroPython Code Block:

base_echo.record_wav_file("/flash/res/audio/test.wav", rate=16000, bits=16, channel=2, duration=3000)
record(rate=16000, bits=16, channel=2, duration=3000)

Record audio to a PCM buffer.

Parameters:
  • rate (int) – Sample rate (default is 16000).

  • bits (int) – Bit depth (default is 16).

  • channel (int) – Number of channels (default is 2).

  • duration (int) – Duration of the recording in milliseconds (default is 3000).

UiFlow2 Code Block:

record.png

MicroPython Code Block:

base_echo.record(rate=16000, bits=16, channel=2, duration=3000)
property pcm_buffer: bytes

Get the PCM buffer.

Returns:

The PCM buffer.

UiFlow2 Code Block:

pcm_buffer.png

MicroPython Code Block:

base_echo.pcm_buffer