INMP441 on ESP32 — Mic outputs values but doesn’t respond to voice or sound amplitude

Hi everyone,

I’ve been trying to get a simple INMP441 microphone working with my ESP32 for the past week and I’m stuck. The mic gives me numbers, but it doesn’t seem to react to voice or sound at all — the values just drift around a few thousand and never spike when I speak, clap, or tap near the mic.


Hardware Setup

  • ESP32 Dev Module
  • INMP441 I²S microphone
  • Breadboard + jumper wires (no extra components)

Wiring (INMP441 → ESP32):

INMP441 Pin ESP32 Pin Description
VDD 3.3 V Mic powered from ESP32
GND GND Common ground
L/R GND (on the mic itself) Forces left channel
WS (LRCLK) GPIO 25 Word Select
SCK (BCLK) GPIO 32 Bit Clock
SD (DOUT) GPIO 33 Serial Data

I’ve triple-checked the wiring, tried multiple breadboards, and even bought three new INMP441 modules — same result every time.


The Problem

I’m getting valid numeric readings (no zeros, no NANs).
Values float around a few thousand, so data is clearly being read — but it never changes significantly with sound. Talking, clapping, tapping — the numbers hardly move.

I’ve seen example projects where speech produces smooth waveforms and amplitudes in the tens or hundreds of thousands, but I can’t get anywhere near that.

I even suspected the mic hole might be blocked and bought new ones, but the behaviour is identical.


Code I’m Using

#include <driver/i2s.h>

#define I2S_WS   25
#define I2S_SCK  32
#define I2S_SD   33
#define I2S_PORT I2S_NUM_0
#define SAMPLE_RATE 16000
#define BUFFER_LEN 256

void setup() {
  Serial.begin(115200);
  delay(500);
  Serial.println("INMP441 clean voice waveform");

  i2s_config_t cfg = {
    .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX),
    .sample_rate = SAMPLE_RATE,
    .bits_per_sample = I2S_BITS_PER_SAMPLE_32BIT,
    .channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
    .communication_format = I2S_COMM_FORMAT_STAND_I2S,
    .intr_alloc_flags = 0,
    .dma_buf_count = 8,
    .dma_buf_len = 64,
    .use_apll = false,
    .tx_desc_auto_clear = false,
    .fixed_mclk = 0
  };

  i2s_pin_config_t pins = {
    .bck_io_num = I2S_SCK,
    .ws_io_num = I2S_WS,
    .data_out_num = I2S_PIN_NO_CHANGE,
    .data_in_num = I2S_SD
  };

  i2s_driver_install(I2S_PORT, &cfg, 0, NULL);
  i2s_set_pin(I2S_PORT, &pins);
  i2s_zero_dma_buffer(I2S_PORT);
}

void loop() {
  int32_t raw[BUFFER_LEN];
  size_t bytes_read;
  i2s_read(I2S_PORT, raw, sizeof(raw), &bytes_read, portMAX_DELAY);
  int n = bytes_read / sizeof(int32_t);

  for (int i = 0; i < n; i++) {
    int32_t v = (raw[i] >> 8) & 0xFFFFFF;
    if (v & 0x800000) v |= 0xFF000000;  // sign-extend
    int16_t sample = v >> 8;            // downscale to 16-bit
    Serial.println(sample);
  }
}

It runs fine — Serial Plotter shows a line and changing values — but there’s almost no reaction when I speak near the mic.


What I’ve Tried

  • Swapped WS and SCK pins (no difference)
  • Tried both .I2S_COMM_FORMAT_I2S and .I2S_COMM_FORMAT_STAND_I2S
  • Different sample rates (8 kHz → 44.1 kHz)
  • Verified power (3.3 V stable)
  • Grounded L/R directly to mic GND pad
  • Tested three separate INMP441 modules
  • Tried two ESP32 boards

Same outcome each time — low-level changing numbers, no voice sensitivity.

Any insight, working code snippet, would be hugely appreciated.

Thanks,

I think the INMP441 is 24 bits not 32

I2S_BITS_PER_SAMPLE_24BIT

There are lots of variations of this, we cannot see which one you are using.

Post an annotated schematic Showing how you built your project, show all connections, hardware and power sources.

good catch on the 24-bit format. I had been using I2S_BITS_PER_SAMPLE_32BIT because most examples online show 32-bit words with the 24-bit sample packed inside. I’ll try switching explicitly to I2S_BITS_PER_SAMPLE_24BIT and see if that makes a difference to the amplitude scaling.

here’s the exact hardware:

  • Board: AITRIP ESP-WROOM-32 (CP2102 USB-C, 30-pin)
  • Mic: INMP441 breakout (no extra resistors or caps)
  • Power: direct from the ESP32’s 3V3 pin
  • Wiring:
INMP441 ESP32
VDD → 3V3
GND → GND
L/R → GND (on the mic)
WS → GPIO 25
SCK → GPIO 32
SD → GPIO 33

It’s all on a breadboard with short Dupont jumpers (ELEGOO 120-piece kit). I’ve tested three identical INMP441 modules, same issue on all.



There is another caveat when using 24 bit:

From the ESP documentation-

Normally, MCLK should be the multiple of sample rate and BCLK at the same time. The field i2s_std_clk_config_t::mclk_multiple indicates the multiple of MCLK to the sample rate. In most cases, I2S_MCLK_MULTIPLE_256 should be enough. However, if slot_bit_width is set to I2S_SLOT_BIT_WIDTH_24BIT, to keep MCLK a multiple to the BCLK, i2s_std_clk_config_t::mclk_multiple should be set to multiples that are divisible by 3 such as I2S_MCLK_MULTIPLE_384. Otherwise, WS will be inaccurate.

Ah — that’s super helpful, thanks @jim-p!

That could definitely explain what I’m seeing — my waveform is all over the place, and I’d suspected some kind of clocking or WS sync issue.

I’ll try setting

clk_cfg.mclk_multiple = I2S_MCLK_MULTIPLE_384;

alongside

slot_cfg.slot_bit_width = I2S_SLOT_BIT_WIDTH_24BIT;

If I understand correctly, this should keep MCLK aligned as a clean multiple of both the BCLK and the sample rate, right?

One thing I’m still a bit unsure about — does this also affect the clk_cfg.mclk_div or the actual master clock pin assignment (mclk = GPIO0)? I’ve been using the standard internal MCLK with no external wire, so I assume the division just happens internally?

Can't answer any of your other questions.
I'm using version 3.3.0 and everything involving I2S from the old version has totally changed. I can't even compile your code without alot of errors.

A post was split to a new topic: Random values from INMP441 when used with ESP32-DEV-38P board