I have a M5Stack Cardputer, which has an onboard SPM1423 microphone. In the official example code, it is driven by M5Stack's M5Cardputer.h
and Mic_Class.hpp
, and it works.
In arduino-esp32, it provides another I2S library named ESP_I2S.h
, which provides another way to use ESP32's I2S. I tried its example Record_to_WAV.ino
, and changed the SD_MMC.h
into SD.h
. I modified the pins, set the recording time to 1 second, and it did wrote a WAV file into the TF card. But I cannot find a way to initialize the I2S properly to receive correct data.
Here is my full code:
/*
ESP32-S2-EYE I2S record to WAV example
This simple example demonstrates using the I2S library to record
5 seconds of audio data and write it to a WAV file on the SD card.
Don't forget to select the OPI PSRAM, 8MB flash size and Enable USB CDC
on boot in the Tools menu!
Created for arduino-esp32 on 18 Dec, 2023
by Lucas Saavedra Vaz (lucasssvaz)
*/
#include "ESP_I2S.h"
#include "FS.h"
#include <SD.h>
#include <M5GFX.h>
M5GFX tft;
uint16_t RGB888toRGB565(uint32_t rgb888) {
return ((rgb888 & 0x00F80000) >> 8) | ((rgb888 & 0x0000FC00) >> 5) | ((rgb888 & 0x000000F8) >> 3);
}
const uint8_t I2S_SCK = 43;
const uint8_t I2S_WS = -1;
const uint8_t I2S_DIN = 46;
const uint8_t SD_CMD = 14;
const uint8_t SD_CLK = 40;
const uint8_t SD_DATA0 = 39;
void setup() {
// Create an instance of the I2SClass
I2SClass i2s;
// Create variables to store the audio data
uint8_t *wav_buffer;
size_t wav_size;
// Initialize the serial port
tft.init();
tft.startWrite();
tft.setBrightness(64);
tft.fillScreen(RGB888toRGB565(0x66CCFF));
tft.setCursor(0, 0);
tft.setTextColor(RGB888toRGB565(0x003399));
tft.println("Initializing I2S bus...");
// Set up the pins used for audio input
i2s.setPins(I2S_SCK, -1, -1, I2S_DIN);
// Initialize the I2S bus in standard mode
if (!i2s.begin(I2S_MODE_PDM_RX, 16000, I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_MONO, I2S_STD_SLOT_RIGHT)) {
tft.println("Failed to initialize I2S bus!");
return;
}
tft.println("I2S bus initialized.");
tft.println("Initializing SD card...");
// Set up the pins used for SD card access
SPI.begin(40, 39, 14, 12);/*SCLK, MISO, MOSI, CS*/
SPI.setFrequency(40000000);
// Mount the SD card
if (!SD.begin()) {
tft.println("Failed to initialize SD card!");
return;
}
tft.println("SD card initialized.");
tft.println("Recording 1 second of audio data...");
// Record 5 seconds of audio data
wav_buffer = i2s.recordWAV(1, &wav_size);
// Create a file on the SD card
File file = SD.open("/test.wav", FILE_WRITE);
if (!file) {
tft.println("Failed to open file for writing!");
return;
}
tft.println("Writing audio data to file...");
tft.printf("Size: %d bytes\n", wav_size);
// Write the audio data to the file
if (file.write(wav_buffer, wav_size) != wav_size) {
tft.println("Failed to write audio data to file!");
return;
}
// Close the file
file.close();
free(wav_buffer);
tft.println("Application complete.");
while (true);
}
void loop() {}
Please pay attention to the I2S initialization code.
I tried several different codes to init the I2S, but none of them could get the correct audio data.
if (!i2s.begin(I2S_MODE_PDM_RX, 16000, I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_MONO, I2S_STD_SLOT_RIGHT)) {
This one fills 0x2987 into the WAV file, and it records no sound.
if (!i2s.begin(I2S_MODE_STD, 16000, I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_MONO, I2S_STD_SLOT_RIGHT)) {
This one fills noise into the WAV file.
if (!i2s.begin(I2S_MODE_PDM_TX, 16000, I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_MONO, I2S_STD_SLOT_RIGHT)) {
This one writes a 0 byte WAV file.
I have modified the other options of this function, but failed.
How can I use the onboard microphone with ESP_I2S.h
library?