🤖Have you ever tried Chat.M5Stack.com before asking??😎
    M5Stack Community
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Register
    • Login

    Atomic Audio Base with M5ATOMS3R

    Bases
    1
    4
    81
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • J
      jimruxton
      last edited by

      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");
          }
      }
      
      J 1 Reply Last reply Reply Quote 0
      • J
        jimruxton @jimruxton
        last edited by

        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");
          }
        }
        
        J 1 Reply Last reply Reply Quote 0
        • J
          jimruxton @jimruxton
          last edited by

          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.

          J 1 Reply Last reply Reply Quote 0
          • J
            jimruxton @jimruxton
            last edited by

            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);
            }
            
            
            1 Reply Last reply Reply Quote 0
            • First post
              Last post