Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

MEMS microphone with ESP32

Ethan25

Junior Member level 3
Junior Member level 3
Joined
Dec 17, 2023
Messages
29
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Activity points
254
Hi,

I have been trying to interface my INMP441 (24bit digital MEMS microphone) with ESP32. It is pretty much a straight forward process but, every code that I find in GitHub or in some blog always gives me the mean value of the obtained data rather than the RAW data and also, this datasheet of this microphone tells us that it is a 24bit microphone but often people only use 16bits, why so ? what am I missing ?
1 - https://dronebotworkshop.com/esp32-i2s/
C++:
/*
  ESP32 I2S Microphone Sample
  esp32-i2s-mic-sample.ino
  Sample sound from I2S microphone, display on Serial Plotter
  Requires INMP441 I2S microphone

  DroneBot Workshop 2022
  https://dronebotworkshop.com
*/
void i2s_install() {
  // Set up I2S Processor configuration
  const i2s_config_t i2s_config = {
    .mode = i2s_mode_t(I2S_MODE_MASTER | I2S_MODE_RX),
    .sample_rate = 44100,
    .bits_per_sample = i2s_bits_per_sample_t(16),
    .channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
    .communication_format = i2s_comm_format_t(I2S_COMM_FORMAT_STAND_I2S),
    .intr_alloc_flags = 0,
    .dma_buf_count = 8,
    .dma_buf_len = bufferLen,
    .use_apll = false
  };

  i2s_driver_install(I2S_PORT, &i2s_config, 0, NULL);
}

void loop() {
  // Get I2S data and place in data buffer
  size_t bytesIn = 0;
  esp_err_t result = i2s_read(I2S_PORT, &sBuffer, bufferLen, &bytesIn, portMAX_DELAY);

  if (result == ESP_OK)
  {
    // Read I2S data buffer
    int16_t samples_read = bytesIn / 8;
    if (samples_read > 0) {
      float mean = 0;
      for (int16_t i = 0; i < samples_read; ++i) {
        mean += (sBuffer[i]);
      }

      // Average the data reading
      mean /= samples_read;

      // Print to serial plotter
      Serial.println(mean);
    }
  }
}


2- https://github.com/0015/ThatProject/tree/master/ESP32_MICROPHONE/ESP32_INMP441_SETUP_ESP-2.X

C++:
void loop() {

  size_t bytesIn = 0;
  esp_err_t result = i2s_read(I2S_PORT, &sBuffer, bufferLen, &bytesIn, portMAX_DELAY);
  if (result == ESP_OK)
  {
    int samples_read = bytesIn / 8;
    if (samples_read > 0) {
      float mean = 0;
      for (int i = 0; i < samples_read; ++i) {
        mean += (sBuffer[i]);
      }
      mean /= samples_read;
      Serial.println(mean);
    }
  }
}

void i2s_install(){
  const i2s_config_t i2s_config = {
    .mode = i2s_mode_t(I2S_MODE_MASTER | I2S_MODE_RX),
    .sample_rate = 44100,
    .bits_per_sample = i2s_bits_per_sample_t(16),
    .channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
    .communication_format = i2s_comm_format_t(I2S_COMM_FORMAT_STAND_I2S),
    .intr_alloc_flags = 0, // default interrupt priority
    .dma_buf_count = 8,
    .dma_buf_len = bufferLen,
    .use_apll = false
  };

  i2s_driver_install(I2S_PORT, &i2s_config, 0, NULL);
}
 
The examples you provided show code that reads the data from the I2S bus, averages it, and then prints the mean value to the serial plotter. This averaging is done to smooth out the signal, which makes it more presentable for visualization in tools like the Serial Plotter, but it hides the raw waveform data. To capture raw I2S samples without averaging, you'll need to skip the averaging part and directly process or print each individual sample.

Here's how you can modify the code to print the raw data instead of the mean value:
Code:
void loop() {
  size_t bytesIn = 0;
  esp_err_t result = i2s_read(I2S_PORT, &sBuffer, bufferLen, &bytesIn, portMAX_DELAY);
  if (result == ESP_OK) {
    int samples_read = bytesIn / sizeof(int16_t);  // Assuming 16-bit samples
    for (int i = 0; i < samples_read; ++i) {
      Serial.println(sBuffer[i]);  // Print raw sample
    }
  }
}
To capture the full 24-bit data, you need to modify the bits_per_sample field in the I2S configuration and handle the data differently:
Code:
void i2s_install() {
  const i2s_config_t i2s_config = {
    .mode = i2s_mode_t(I2S_MODE_MASTER | I2S_MODE_RX),
    .sample_rate = 44100,
    .bits_per_sample = i2s_bits_per_sample_t(32),  // Use 32-bit container to hold 24-bit data
    .channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
    .communication_format = i2s_comm_format_t(I2S_COMM_FORMAT_STAND_I2S),
    .intr_alloc_flags = 0,
    .dma_buf_count = 8,
    .dma_buf_len = bufferLen,
    .use_apll = false
  };

  i2s_driver_install(I2S_PORT, &i2s_config, 0, NULL);
}
In this case, you'll receive 32-bit values, but only the top 24 bits will contain meaningful data from the microphone. You can extract the 24-bit data as follows:
Code:
void loop() {
  size_t bytesIn = 0;
  esp_err_t result = i2s_read(I2S_PORT, &sBuffer, bufferLen, &bytesIn, portMAX_DELAY);
  if (result == ESP_OK) {
    int samples_read = bytesIn / sizeof(int32_t);  // 32-bit container for 24-bit data
    for (int i = 0; i < samples_read; ++i) {
      int32_t raw_data = sBuffer[i] >> 8;  // Shift right to get the upper 24 bits
      Serial.println(raw_data);  // Print the 24-bit data
    }
  }
}

For your convenience in the future, you can make a MEMS microphone breakout board like this:
 

LaTeX Commands Quick-Menu:

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top