🤖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

    Scheduled Pinned Locked Moved Bases
    4 Posts 1 Posters 235 Views
    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 Offline
      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 Offline
        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 Offline
          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 Offline
            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

            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
            • First post
              Last post