Atomic Audio Base with M5ATOMS3R
-
I can't get this base to work with the AtomS3R . The example on the website doesn't work due to an i2s conflict between new and legacy i2s drivers. I finally got the following program to run meaning I see the text on the display however I can't seem to hear anything. Not sure if it isn't recording or not playing back properly. Does anyone have recent working code for this pair? Thanks.
#include "M5Unified.h" // Define buffer size (200KB for ESP32-S3) #define RECORD_SIZE (1024 * 200) static uint8_t *buffer = nullptr; void setup() { auto cfg = M5.config(); // Enable external I2C for ES8311 codec on the audio base cfg.external_imu = true; M5.begin(cfg); M5.Display.setFont(&fonts::FreeMonoBold9pt7b); Serial.begin(115200); // -------------------------- // Speaker Configuration (I2S Output) // AtomS3R I2S pins: BCK=8, WS=6, DOUT=5 // -------------------------- auto spk_cfg = M5.Speaker.config(); spk_cfg.pin_data_out = 5; spk_cfg.pin_bck = 8; spk_cfg.pin_ws = 6; spk_cfg.sample_rate = 44100; spk_cfg.i2s_port = I2S_NUM_0; spk_cfg.stereo = false; // Use mono for the base speaker M5.Speaker.config(spk_cfg); M5.Speaker.begin(); // -------------------------- // Microphone Configuration (I2S Input) // AtomS3R I2S pins: BCK=8, WS=6, DIN=7 // -------------------------- auto mic_cfg = M5.Mic.config(); mic_cfg.pin_data_in = 7; mic_cfg.pin_bck = 8; mic_cfg.pin_ws = 6; mic_cfg.sample_rate = 44100; mic_cfg.i2s_port = I2S_NUM_1; // Use separate I2S port for input M5.Mic.config(mic_cfg); M5.Mic.begin(); // Set volume/gain M5.Speaker.setVolume(50); // For v0.2.14, set mic gain via config if needed (default works for most cases) // mic_cfg.magnification = 2; // Allocate recording buffer buffer = (uint8_t *)malloc(RECORD_SIZE); if (buffer == nullptr) { Serial.println("Memory allocation failed!"); while (true) delay(1000); } Serial.println("Device ready! Press button to record/play"); M5.Display.println("Click to\nRecord & Play"); } void loop() { M5.update(); if (M5.BtnA.wasClicked()) { M5.Display.fillScreen(BLACK); M5.Display.setCursor(0, 0); // -------------------------- // Recording // -------------------------- M5.Display.println("Recording..."); Serial.println("Start recording"); M5.Mic.record(buffer, RECORD_SIZE, 44100); delay(3000); // -------------------------- // Playback // -------------------------- M5.Display.println("Playing..."); Serial.println("Start playing"); M5.Speaker.playRaw(buffer, RECORD_SIZE, 44100, false, 1); while (M5.Speaker.isPlaying()) delay(10); M5.Display.println("Done"); Serial.println("Done"); } } -
The AtomS3R and Atomic Audio Base will work using the RecordPlay example in https://github.com/m5stack/M5Atomic-EchoBase/tree/main/example . Whenever I try to include both M5Unified.h and M5EchoBase in the same sketch I get the i2s conflict between new and legacy i2s drivers . I cant get any sound however when using just the M5Unified.h library. Below is my latest code. Still no sound?
#include "M5Unified.h" #include <Wire.h> // Define buffer size (200KB for ESP32-S3) #define RECORD_SIZE (1024 * 200) static uint8_t *buffer = nullptr; void initES8311() { // AtomS3R I2C pins for the Audio Base are SDA=38, SCL=39 Wire.begin(38, 39); // Helper to write to ES8311 registers auto writeReg = [](uint8_t reg, uint8_t val) { Wire.beginTransmission(0x18); // Default ES8311 I2C address Wire.write(reg); Wire.write(val); Wire.endTransmission(); }; // --- ES8311 Initialization Sequence --- writeReg(0x00, 0x00); // Reset writeReg(0x01, 0x3F); // Power down all writeReg(0x0D, 0x01); // Clock on writeReg(0x01, 0x03); // Power up writeReg(0x02, 0x00); // Master clock writeReg(0x05, 0x00); // DAC power writeReg(0x04, 0x00); // ADC power writeReg(0x14, 0x24); // Set MIC gain writeReg(0x46, 0xFF); // Set Speaker Volume to Max writeReg(0x06, 0x00); // ADC Mute Off writeReg(0x09, 0x00); // Set ADC to I2S format Serial.println("ES8311 Codec Initialized!"); } void setup() { Serial.begin(115200); auto cfg = M5.config(); // Enable external I2C for ES8311 codec on the audio base cfg.external_imu = false; M5.begin(cfg); initES8311(); M5.Display.setFont(&fonts::FreeMonoBold9pt7b); // -------------------------- // Speaker Configuration (I2S Output) // AtomS3R I2S pins: BCK=8, WS=6, DOUT=5 // -------------------------- auto spk_cfg = M5.Speaker.config(); spk_cfg.pin_data_out = 5; spk_cfg.pin_bck = 8; spk_cfg.pin_ws = 6; spk_cfg.sample_rate = 44100; // spk_cfg.i2s_port = I2S_NUM_0; spk_cfg.stereo = false; // Use mono for the base speaker M5.Speaker.config(spk_cfg); M5.Speaker.begin(); // -------------------------- // Microphone Configuration (I2S Input) // AtomS3R I2S pins: BCK=8, WS=6, DIN=7 // -------------------------- auto mic_cfg = M5.Mic.config(); mic_cfg.pin_data_in = 7; mic_cfg.pin_bck = 8; mic_cfg.pin_ws = 6; mic_cfg.sample_rate = 44100; // mic_cfg.i2s_port = I2S_NUM_0; // Use separate I2S port for input mic_cfg.magnification = 2; M5.Mic.config(mic_cfg); M5.Mic.begin(); // Set volume/gain M5.Speaker.setVolume(100); // For v0.2.14, set mic gain via config if needed (default works for most cases) mic_cfg.magnification = 2; // Allocate recording buffer buffer = (uint8_t *)malloc(RECORD_SIZE); if (buffer == nullptr) { Serial.println("Memory allocation failed!"); while (true) delay(1000); } Serial.println("Device ready! Press button to record/play"); M5.Display.println("Click to\nRecord & Play"); } void loop() { M5.update(); if (M5.BtnA.wasClicked()) { M5.Display.fillScreen(BLACK); M5.Display.setCursor(0, 0); // -------------------------- // Recording // -------------------------- M5.Display.println("Recording..."); Serial.println("Start recording"); M5.Mic.record(buffer, RECORD_SIZE, 44100); delay(500); Serial.println(M5.Mic.isRecording()); delay(3000); // while (M5.Mic.isRecording()==1) delay(10); // -------------------------- // Playback // -------------------------- M5.Display.println("Playing..."); Serial.println("Start playing"); M5.Speaker.playRaw(buffer, RECORD_SIZE, 44100, false, 1); Serial.println(M5.Speaker.isRunning()); while (M5.Speaker.isPlaying()) delay(10); M5.Display.println("Done"); Serial.println("Done"); } } -
A quick update. If I use the version of the M5Atomic-EchoBase library on github I no longer have the issue with i2s conflicts between that library and M5Unified. So anyone using these 2 libraries together be sure to use the github version and not the version currently showing up in the Arduino Library Manager.
-
I have been able to get a program to work that uses the M5EchoBase library but no luck using the unified library. For example the simple program below doesn't work.
#include <M5Unified.h> void setup() { // 1. Initialize M5Unified delay(1000); // Delay for a moment to allow the system to stabilize. auto cfg = M5.config(); cfg.serial_baudrate = 115200; M5.begin(cfg); // 2. Configure the Speaker for the Atomic Audio Base (ES8311) // We access the speaker configuration directly via M5.Speaker.config() auto spk_cfg = M5.Speaker.config(); // Set pins for Atomic Audio Base (ES8311) spk_cfg.pin_bck = 8; // BCLK spk_cfg.pin_ws = 6; // LRCK (WS) spk_cfg.pin_data_out = 5; // DAC (DOUT) spk_cfg.i2s_port = I2S_NUM_0; // Configure for external codec (not internal DAC) spk_cfg.use_dac = false; spk_cfg.sample_rate = 44100; // Apply the configuration M5.Speaker.config(spk_cfg); // 3. Start the speaker M5.Speaker.begin(); // 4. Set volume (0-255) M5.Speaker.setVolume(128); } void loop() { M5.update(); // Play a 1000 Hz tone for 1000 milliseconds (1 second) M5.Speaker.tone(1000, 1000); // Wait for the tone to finish delay(1000); // Small delay before next loop delay(1000); }Is there no way to set up the ES8311 codec without using M5EchoBase? strangely if I run the program below then load the above program the tone works? But I can't stick the M5.Speaker.tone(1000, 1000); command in the program below and have it work. Does anyone know how to play a tone using only the Unified library from an AtomS3R into a Atomic Audio Base (ES8311 codec)?
#include <M5Unified.h> #include <M5EchoBase.h> #if defined(CONFIG_IDF_TARGET_ESP32S3) #define RECORD_SIZE (1024 * 400) #elif defined(CONFIG_IDF_TARGET_ESP32) #define RECORD_SIZE (1024 * 400) #endif #if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)) M5EchoBase echobase; #else M5EchoBase echobase(I2S_NUM_0); #endif static uint8_t *buffer = nullptr; // Pointer to hold the audio buffer. void setup() { delay(1000); // Delay for a moment to allow the system to stabilize. auto cfg = M5.config(); cfg.serial_baudrate = 115200; M5.begin(cfg); // Initialize the EchoBase with ATOMS3 pinmap. #if defined(CONFIG_IDF_TARGET_ESP32S3) if (!echobase.init(44100 /*Sample Rate*/, 38 /*I2C SDA*/, 39 /*I2C SCL*/, 7 /*I2S DIN*/, 6 /*I2S WS*/, 5 /*I2S DOUT*/, 8 /*I2S BCK*/, Wire) != 0) { Serial.println("Failed to initialize EchoBase!"); while (true) { delay(1000); } } #elif defined(CONFIG_IDF_TARGET_ESP32) // Initialize the EchoBase with ATOM pinmap. if (!echobase.init(44100 /*Sample Rate*/, 25 /*I2C SDA*/, 21 /*I2C SCL*/, 23 /*I2S DIN*/, 19 /*I2S WS*/, 22 /*I2S DOUT*/, 33 /*I2S BCK*/, Wire) != 0) { Serial.println("Failed to initialize EchoBase!"); while (true) { delay(1000); } } #endif echobase.setSpeakerVolume(80); // Set speaker volume to 70%. echobase.setMicGain(ES8311_MIC_GAIN_0DB); // Set microphone gain to 0dB. buffer = (uint8_t *)malloc(RECORD_SIZE); // Allocate memory for the record buffer. // Check if memory allocation was successful. if (buffer == nullptr) { // If memory allocation fails, enter an infinite loop. while (true) { Serial.println("Failed to allocate memory :("); delay(1000); } } Serial.println("EchoBase ready, start recording and playing!"); // M5.Speaker.tone(2000, 2000); // delay(2000); } void loop() { Serial.println("Start recording..."); // Recording echobase.setMute(false); echobase.record(buffer, RECORD_SIZE); // Record audio into buffer. delay(100); Serial.println("Start playing..."); // Playing echobase.setMute(false); delay(10); echobase.play(buffer, RECORD_SIZE); // Play audio from buffer. //M5.Speaker.playRaw(buffer, RECORD_SIZE, 44100, false, 1, 0); delay(100); }