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); }
Hello! It looks like you're interested in this conversation, but you don't have an account yet.
Getting fed up of having to scroll through the same posts each visit? When you register for an account, you'll always come back to exactly where you were before, and choose to be notified of new replies (either via email, or push notification). You'll also be able to save bookmarks and upvote posts to show your appreciation to other community members.
With your input, this post could be even better 💗
Register Login