Skip to content

support@quartzcomponents.com

Free Shipping Over INR 500

Electronics Projects

Voice Control Automation using INMP441 I2S Module and ESP32

by RISHABH JANGID 28 Apr 2026 0 Comments

This project allows you to control hardware—like motors and LEDs—using sound! By pairing an ESP32 Development Board with an INMP441 I2S Digital Microphone Module, the system listens to its environment and reacts to specific audio signal.
While we use a simple "clap" to trigger the LED and DC motor in this project, this setup is fully capable of complex voice control. Because we are using an I2S digital microphone, the ESP32 receives raw digital audio data, making it the perfect foundation for advanced speech recognition and keyword spotting.

Components Required

About the Components

ESP32 Development Board

The brain of the project. It reads the digital audio data from the microphone, processes the sound levels, and controls the output devices.

  • Microcontroller: Dual-core Tensilica LX6 microprocessor.
  • Operating Voltage: 3.3V.
  • Input Voltage: 7V - 12V (via VIN pin).
  • Clock Frequency: Up to 240 MHz.
  • Flash Memory: 4MB.
  • Connectivity: Integrated Wi-Fi (802.11 b/g/n) and Dual-mode Bluetooth (Classic & BLE).
  • I/O Pins: 30 pins with support for PWM, ADC, DAC, SPI, I2C, and I2S.

INMP441 I2S Digital Mic

A high-performance, low-power digital microphone.

  • Interface: Digital I2S (Inter-IC Sound) with high precision.
  • Directionality: Omnidirectional (har direction se sound capture karta hai).
  • SNR (Signal-to-Noise Ratio): 61 dBA.
  • Sensitivity: -26 dBFS.
  • Frequency Response: 60 Hz to 15 kHz.
  • Current Consumption: Very low (600 µA).
  • Digital Output: 24-bit data for high-quality audio processing.

Why not a basic analog sound sensor? Analog sensors only detect loud noises and act like a simple on/off switch. The INMP441 captures clear, actual audio waveforms. If you want to build true voice control, a digital I2S mic is mandatory!

L293D Motor Driver

A compact dual DC motor driver. Microcontrollers like the ESP32 cannot provide enough current to spin a motor directly. The L293D acts as a bridge, taking small control signals from the ESP32 to deliver higher current from the battery to the motor.

  • Driver Type: Dual H-Bridge motor driver.
  • Supply Voltage (Vcc1 - Logic): 5V.
  • Output Current: 600mA per channel (1.2A Peak current).
  • Motor Voltage (Vcc2): 4.5V to 36V.
  • Protection: Internal ESD protection and thermal shutdown.
  • Capability: Can drive 2 DC motors or 1 Stepper motor simultaneously.

System Architecture

  1. Listen: The INMP441 continuously monitors the room for sound.
  2. Transmit: It sends high-quality, digital I2S audio data directly to the ESP32.
  3. Process: The ESP32 code analyzes the audio samples in real-time. For this project, it looks for the specific amplitude spike of a clap.
  4. Actuate: Once detected, the ESP32 signals the MX1508 motor driver and toggles the LED.
  5. Result: The motor spins and the LED turns on or off instantly.

Circuit Connection

Fig. Circuit Diagram

Fig. Schemetic Diagram

INMP441 to ESP32:

  • VDD → 3.3V
  • GND → GND
  • L/R → GND (Sets channel to Left)
  • WS → GPIO 25 (or your chosen pin)
  • SCK → GPIO 33 (or your chosen pin)
  • SD → GPIO 32 (or your chosen pin)

Outputs to ESP32 & Power:

  • Motor Driver IN1 / IN2 → ESP32 Motor Control GPIOs
  • Motor → Driver Motor Outputs (A+ / A-)
  • LED → ESP32 GPIO (with a resistor)
  • Power → Li-ion battery connects directly to the Motor Driver power input to handle the motor load safely.

Code Explanation

Libraries Used

Arduino · C++
#include <driver/i2s.h>
#include <math.h>

Purpose of Library

#include <driver/i2s.h> → Enables ESP32 I2S peripheral to receive digital audio from INMP441.
#include <math.h> → Provides mathematical operations like sqrt() for signal processing.

Pin Definitions

Arduino · C++
#define I2S_WS 22
#define I2S_SD 21
#define I2S_SCK 19
#define I2S_PORT I2S_NUM_0

Defines I2S communication lines:

  • WS → Channel sync
  • SD → Audio data input
  • SCK → Clock signal

I2S_PORT selects hardware I2S module.

Audio Configuration

Arduino · C++
#define SAMPLE_RATE 16000
#define BUFFER_LEN 256

SAMPLE_RATE → Audio sampled at 16 kHz.
BUFFER_LEN → Number of samples processed per cycle.

Timing Control

Arduino · C++
#define DEBOUNCE_MS 250
#define CLAP_GAP_MS 400

DEBOUNCE_MS → Prevents multiple triggers from one clap.
CLAP_GAP_MS → Max interval for detecting double clap.

Output Pins

Arduino · C++
#define IN1 5
#define IN2 18
#define LED_PIN 2
  • IN1, IN2 → Motor driver control
  • LED_PIN → LED output

Global Variables

Arduino · C++
int32_t samples[BUFFER_LEN];

Stores raw I2S audio data.

Arduino · C++
unsigned long lastClapTime = 0;
unsigned long firstClapTime = 0;
int clapStage = 0;

Tracks clap timing and sequence.

Arduino · C++
bool ledState = false;
bool motorState = false;

Stores current output states.

Arduino · C++
float noiseFloor = 500.0;
bool wasAbove = false;
  • noiseFloor → Dynamic background noise level
  • wasAbove → Prevents repeated triggers

Setup I2S function

Arduino · C++
void setupI2S()

Configures ESP32 audio input.

Arduino · C++
i2s_config_t i2s_config = {
.mode = (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 = ESP_INTR_FLAG_LEVEL1,
.dma_buf_count = 4,
.dma_buf_len = BUFFER_LEN
};
  • Master receive mode
  • 32-bit samples
  • Left channel only
  • DMA buffers for continuous streaming
Arduino · C++
i2s_pin_config_t pin_config = {
.bck_io_num = I2S_SCK,
.ws_io_num = I2S_WS,
.data_in_num = I2S_SD
};
  • Maps ESP32 pins to microphone.
Arduino · C++
i2s_driver_install(...)
i2s_set_pin(...)
i2s_zero_dma_buffer(...)
  • Initializes I2S driver and clears buffers.

RMS Calculation

Arduino · C++
float computeRMS(int32_t *buffer, int len)
  • Converts raw audio (>> 14)
  • Squares each sample
  • Computes average
  • Applies square root

Returns average signal energy.

Peak Detection

Arduino · C++
float computePeak(int32_t *buffer, int len)
  • Extracts absolute amplitude
  • Finds maximum value

Detects sudden loud spikes.

Setup Function

Arduino · C++
void setup() {
  Serial.begin(115200);
  setupI2S();

  pinMode(IN1, OUTPUT);
  pinMode(IN2, OUTPUT);
  pinMode(LED_PIN, OUTPUT);

  digitalWrite(IN1, LOW);
  digitalWrite(IN2, LOW);
  digitalWrite(LED_PIN, LOW);
}
  • Initializes serial communication for debugging.
  • Calls setupI2S() to configure audio input.
  • Sets motor and LED pins as output.
  • Ensures all outputs start in OFF state.

Main Loop Function

Arduino · C++
void loop() {
  size_t bytesRead = 0;
  i2s_read(I2S_PORT, (void *)samples, sizeof(samples), &bytesRead, portMAX_DELAY);

  int samplesRead = bytesRead / sizeof(int32_t);

  float rms = computeRMS(samples, samplesRead);
  float peak = computePeak(samples, samplesRead);

  unsigned long now = millis();

  static float prevPeak = 0;
  static float prevRMS = 0;

  noiseFloor = 0.9995 * noiseFloor + 0.0005 * rms;
  float threshold = noiseFloor * 2.5;

  bool strongPeak = peak > threshold;
  bool impulsive = peak > (rms * 2.0);
  bool fastRise = peak > (prevPeak * 1.8);

  bool isImpulse = strongPeak && impulsive && fastRise;

  prevPeak = peak;
  prevRMS = rms;

  if (isImpulse && !wasAbove && (now - lastClapTime) > DEBOUNCE_MS) {

    lastClapTime = now;

    if (clapStage == 0) {
      clapStage = 1;
      firstClapTime = now;
    } 
    else if (clapStage == 1 && (now - firstClapTime) < CLAP_GAP_MS) {
      motorState = !motorState;

      if (motorState) {
        digitalWrite(IN1, HIGH);
        digitalWrite(IN2, LOW);
      } else {
        digitalWrite(IN1, LOW);
        digitalWrite(IN2, LOW);
      }

      Serial.println("Double Clap → Motor Toggle");
      clapStage = 0;
    }
  }

  wasAbove = isImpulse;

  if (clapStage == 1 && (now - firstClapTime) > CLAP_GAP_MS) {
    ledState = !ledState;
    digitalWrite(LED_PIN, ledState);

    Serial.println("Single Clap → LED Toggle");
    clapStage = 0;
  }

  Serial.print("RMS:");
  Serial.print(rms);
  Serial.print(" Peak:");
  Serial.print(peak);
  Serial.print(" Thr:");
  Serial.println(threshold);
}

Working of Loop

  • Reads digital audio data continuously from INMP441 using I2S.
  • Calculates RMS (background noise level) and Peak (sound spikes).
  • Updates adaptive noise floor to filter constant background noise.
  • Detects clap using three conditions: amplitude, impulse, and rapid rise.
  • First clap starts timing window.
  • Second clap within gap toggles motor.
  • If no second clap occurs, single clap toggles LED.
  • Continuously prints signal values for debugging.

System Summary

The ESP32 continuously processes real-time audio from the INMP441 microphone using the I2S protocol. Instead of simple threshold detection, it applies signal analysis using RMS, peak detection, and adaptive noise filtering. This ensures reliable clap recognition even in noisy environments. Based on detected patterns, the system differentiates between single and double claps to control different outputs.

Why this Architecture Works

Using an I2S microphone is a massive upgrade over standard maker sensors. By bringing digital audio directly into the ESP32's memory, you bypass the electrical noise and limitations of analog pins. This split allows you to start simple—like clapping to turn on a fan—while giving you the exact hardware foundation needed to program offline voice assistants and keyword detection later.

Real-Life Applications

  • Smart Home Automation: Turn lights, fans, or appliances on and off hands-free.
  • Interactive Robotics: Build robots that respond to voice commands or turn toward specific acoustic triggers.
  • Security Systems: Detect specific sound anomalies, like breaking glass or alarms.
  • Accessibility Tools: Provide voice or sound-activated environmental controls for users with limited mobility.

Result

The system successfully listens to its environment and reacts instantly! When a sound threshold is met, the ESP32 accurately processes the I2S audio stream and immediately toggles the LED and DC Motor. The hardware runs smoothly without latency, proving that this compact ESP32 + INMP441 setup is highly capable of advancing from simple clap detection to full-scale audio automation.

 

Code

Complete sketch
#include <driver/i2s.h> #include <math.h>

#define I2S_WS 22
#define I2S_SD 21
#define I2S_SCK 19
#define I2S_PORT I2S_NUM_0

#define SAMPLE_RATE 16000
#define BUFFER_LEN 256

#define DEBOUNCE_MS 250
#define CLAP_GAP_MS 400

#define IN1 5
#define IN2 18
#define LED_PIN 2

int32_t samples[BUFFER_LEN];

unsigned long lastClapTime = 0;
unsigned long firstClapTime = 0;

int clapStage = 0;

bool ledState = false;
bool motorState = false;

float noiseFloor = 500.0;
bool wasAbove = false;

void setupI2S() {
i2s_config_t i2s_config = {
.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 = ESP_INTR_FLAG_LEVEL1,
.dma_buf_count = 4,
.dma_buf_len = BUFFER_LEN,
.use_apll = false,
.tx_desc_auto_clear = false,
.fixed_mclk = 0
};

i2s_pin_config_t pin_config = {
.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, &i2s_config, 0, NULL);
i2s_set_pin(I2S_PORT, &pin_config);
i2s_zero_dma_buffer(I2S_PORT);
}

float computeRMS(int32_t *buffer, int len) {
float sum = 0;
for (int i = 0; i < len; i++) {
float s = (buffer[i] >> 14);
sum += s * s;
}
return sqrt(sum / len);
}

float computePeak(int32_t *buffer, int len) {
float peak = 0;
for (int i = 0; i < len; i++) {
float s = abs(buffer[i] >> 14);
if (s > peak) peak = s;
}
return peak;
}

void setup() {
Serial.begin(115200);
setupI2S();

pinMode(IN1, OUTPUT);
pinMode(IN2, OUTPUT);
pinMode(LED_PIN, OUTPUT);

digitalWrite(IN1, LOW);
digitalWrite(IN2, LOW);
digitalWrite(LED_PIN, LOW);
}

void loop() {
size_t bytesRead = 0;
i2s_read(I2S_PORT, (void *)samples, sizeof(samples), &bytesRead, portMAX_DELAY);

int samplesRead = bytesRead / sizeof(int32_t);

float rms = computeRMS(samples, samplesRead);
float peak = computePeak(samples, samplesRead);

unsigned long now = millis();

static float prevPeak = 0;
static float prevRMS = 0;

noiseFloor = 0.9995 * noiseFloor + 0.0005 * rms;
float threshold = noiseFloor * 2.5;

bool strongPeak = peak > threshold;
bool impulsive = peak > (rms * 2.0);
bool fastRise = peak > (prevPeak * 1.8);

bool isImpulse = strongPeak && impulsive && fastRise;

prevPeak = peak;
prevRMS = rms;

if (isImpulse && !wasAbove && (now - lastClapTime) > DEBOUNCE_MS) {

lastClapTime = now;

if (clapStage == 0) {
  clapStage = 1;
  firstClapTime = now;
} 
else if (clapStage == 1 && (now - firstClapTime) < CLAP_GAP_MS) {
  motorState = !motorState;

  if (motorState) {
    digitalWrite(IN1, HIGH);
    digitalWrite(IN2, LOW);
  } else {
    digitalWrite(IN1, LOW);
    digitalWrite(IN2, LOW);
  }

  Serial.println("Double Clap → Motor Toggle");
  clapStage = 0;
}

}

wasAbove = isImpulse;

if (clapStage == 1 && (now - firstClapTime) > CLAP_GAP_MS) {
ledState = !ledState;
digitalWrite(LED_PIN, ledState);

Serial.println("Single Clap → LED Toggle");
clapStage = 0;

}

Serial.print("RMS:");
Serial.print(rms);
Serial.print(" Peak:");
Serial.print(peak);
Serial.print(" Thr:");
Serial.println(threshold);
}
Prev Post
Next Post

Leave a comment

Please note, comments need to be approved before they are published.

Thanks for subscribing!

This email has been registered!

Shop the look

Choose Options

Edit Option
Back In Stock Notification
is added to your shopping cart.
this is just a warning
Login