Implement INMP441 noise indicator with RGB LED feedback and update project configuration

This commit is contained in:
2026-10-13 18:36:38 -05:00
parent 5a3b03edc4
commit 7da1c2119d
17 changed files with 185 additions and 142 deletions
+3 -1
View File
@@ -31,5 +31,7 @@
"--background-index",
"--query-driver=**",
"--compile-commands-dir=c:\\Users\\Mitchell\\cpp\\buzz_detector\\build"
]
],
"idf.flashType": "UART",
"idf.port": "COM6"
}
+25 -62
View File
@@ -1,69 +1,32 @@
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H21 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | --------- | -------- | -------- | -------- | -------- |
# ESP32-S3 INMP441 noise indicator
# Blink Example
This ESP-IDF sample reads audio from an INMP441 I2S microphone and indicates
the smoothed sound level (RMS) using the ESP32-S3 board's onboard RGB LED. The
microphone's left channel is used because its L/R pin is grounded.
(See the README.md file in the upper level 'examples' directory for more information about examples.)
The LED fades from off to green as the smoothed RMS rises from 0 to 100,000.
From 100,000 to 1,000,000 RMS, it smoothly changes from green to red; at or
above 1,000,000 it remains red. These thresholds are 10 times higher than the
previous settings to make red less likely during ordinary background noise.
This example demonstrates how to blink a LED by using the GPIO driver or using the [led_strip](https://components.espressif.com/component/espressif/led_strip) library if the LED is addressable e.g. [WS2812](https://cdn-shop.adafruit.com/datasheets/WS2812B.pdf). The `led_strip` library is installed via [component manager](main/idf_component.yml).
The thresholds are defined by `GREEN_NOISE_RMS` and `RED_NOISE_RMS` near the
top of [main/main.c](main/main.c). Adjust them after checking the RMS values in
the serial monitor for your microphone and environment.
## How to Use Example
## Wiring
Before project configuration and build, be sure to set the correct chip target using `idf.py set-target <chip_name>`.
| Module | Pin | ESP32-S3 |
| --- | --- | --- |
| INMP441 | SCK / BCLK | GPIO 3 |
| INMP441 | WS / LRCLK | GPIO 4 |
| INMP441 | SD | GPIO 5 |
| INMP441 | L/R | GND |
| INMP441 | VDD | 3.3V |
| INMP441 | GND | GND |
| Onboard RGB LED | Data | GPIO 48 (on supported board variants) |
### Hardware Required
## Build and run
* A development board with normal LED or addressable LED on-board (e.g., ESP32-S3-DevKitC, ESP32-C6-DevKitC etc.)
* A USB cable for Power supply and programming
See [Development Boards](https://www.espressif.com/en/products/devkits) for more information about it.
### Configure the Project
Open the project configuration menu (`idf.py menuconfig`).
In the `Example Configuration` menu:
* Select the LED type in the `Blink LED type` option.
* Use `GPIO` for regular LED
* Use `LED strip` for addressable LED
* If the LED type is `LED strip`, select the backend peripheral
* `RMT` is only available for ESP targets with RMT peripheral supported
* `SPI` is available for all ESP targets
* Set the GPIO number used for the signal in the `Blink GPIO number` option.
* Set the blinking period in the `Blink period in ms` option.
### Build and Flash
Run `idf.py -p PORT flash monitor` to build, flash and monitor the project.
(To exit the serial monitor, type ``Ctrl-]``.)
See the [Getting Started Guide](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/index.html) for full steps to configure and use ESP-IDF to build projects.
## Example Output
As you run the example, you will see the LED blinking, according to the previously defined period. For the addressable LED, you can also change the LED color by setting the `led_strip_set_pixel(led_strip, 0, 16, 16, 16);` (LED Strip, Pixel Number, Red, Green, Blue) with values from 0 to 255 in the [source file](main/blink_example_main.c).
```text
I (315) example: Example configured to blink addressable LED!
I (325) example: Turning the LED OFF!
I (1325) example: Turning the LED ON!
I (2325) example: Turning the LED OFF!
I (3325) example: Turning the LED ON!
I (4325) example: Turning the LED OFF!
I (5325) example: Turning the LED ON!
I (6325) example: Turning the LED OFF!
I (7325) example: Turning the LED ON!
I (8325) example: Turning the LED OFF!
```
Note: The color order could be different according to the LED model.
The pixel number indicates the pixel position in the LED strip. For a single LED, use 0.
## Troubleshooting
* If the LED isn't blinking, check the GPIO or the LED type selection in the `Example Configuration` menu.
For any technical queries, please open an [issue](https://github.com/espressif/esp-idf/issues) on GitHub. We will get back to you soon.
Open this folder as an ESP-IDF project, select the `esp32s3` target, then build,
flash, and open the serial monitor. The firmware uses ESP-IDF's I2S driver and
the `espressif/led_strip` component.
+20
View File
@@ -0,0 +1,20 @@
dependencies:
espressif/led_strip:
component_hash: 28621486f77229aaf81c71f5e15d6fbf36c2949cf11094e07090593e659e7639
dependencies:
- name: idf
require: private
version: '>=5.0'
source:
registry_url: https://components.espressif.com/
type: service
version: 3.0.3
idf:
source:
type: idf
version: 6.0.0
direct_dependencies:
- espressif/led_strip
manifest_hash: cdcc77aff1f56b906c61e51c8f438577513c8d92aa9dfd7bf655f126d2b2d320
target: esp32s3
version: 3.0.0
+2 -1
View File
@@ -1,2 +1,3 @@
idf_component_register(SRCS "main.c"
INCLUDE_DIRS ".")
INCLUDE_DIRS "."
REQUIRES esp_driver_gpio esp_driver_i2s led_strip)
-49
View File
@@ -1,49 +0,0 @@
menu "Example Configuration"
orsource "$IDF_PATH/examples/common_components/env_caps/$IDF_TARGET/Kconfig.env_caps"
choice BLINK_LED
prompt "Blink LED type"
default BLINK_LED_GPIO
help
Select the LED type. A normal level controlled LED or an addressable LED strip.
The default selection is based on the Espressif DevKit boards.
You can change the default selection according to your board.
config BLINK_LED_GPIO
bool "GPIO"
config BLINK_LED_STRIP
bool "LED strip"
endchoice
choice BLINK_LED_STRIP_BACKEND
depends on BLINK_LED_STRIP
prompt "LED strip backend peripheral"
default BLINK_LED_STRIP_BACKEND_RMT if SOC_RMT_SUPPORTED
default BLINK_LED_STRIP_BACKEND_SPI
help
Select the backend peripheral to drive the LED strip.
config BLINK_LED_STRIP_BACKEND_RMT
depends on SOC_RMT_SUPPORTED
bool "RMT"
config BLINK_LED_STRIP_BACKEND_SPI
bool "SPI"
endchoice
config BLINK_GPIO
int "Blink GPIO number"
range ENV_GPIO_RANGE_MIN ENV_GPIO_OUT_RANGE_MAX
default 8
help
GPIO number (IOxx) to blink on and off the LED.
Some GPIOs are used for other purposes (flash connections, etc.) and cannot be used to blink.
config BLINK_PERIOD
int "Blink period in ms"
range 10 3600000
default 1000
help
Define the blinking period in milliseconds.
endmenu
+132 -6
View File
@@ -1,13 +1,139 @@
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include <math.h>
#include <stdint.h>
#include "driver/gpio.h"
#include "driver/i2s_std.h"
#include "esp_err.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "led_strip.h"
#include "sdkconfig.h"
#define I2S_BCLK_GPIO GPIO_NUM_3
#define I2S_WS_GPIO GPIO_NUM_4
#define I2S_DATA_GPIO GPIO_NUM_5
#define RGB_LED_GPIO GPIO_NUM_48
#define SAMPLE_RATE_HZ 16000
#define SAMPLES_PER_READ 256
#define GREEN_NOISE_RMS 100000.0f
#define RED_NOISE_RMS 1000000.0f
#define LED_BRIGHTNESS 64
static const char *TAG = "buzz_detector";
void app_main(void) {
println("Hello, ESP32!");
static led_strip_handle_t init_rgb_led(void)
{
const led_strip_config_t strip_config = {
.strip_gpio_num = RGB_LED_GPIO,
.max_leds = 1,
.led_model = LED_MODEL_WS2812,
.color_component_format = LED_STRIP_COLOR_COMPONENT_FMT_GRB,
.flags = {
.invert_out = false,
},
};
const led_strip_rmt_config_t rmt_config = {
.clk_src = RMT_CLK_SRC_DEFAULT,
.resolution_hz = 10 * 1000 * 1000,
.mem_block_symbols = 64,
.flags = {
.with_dma = false,
},
};
led_strip_handle_t strip = NULL;
ESP_ERROR_CHECK(led_strip_new_rmt_device(&strip_config, &rmt_config, &strip));
ESP_ERROR_CHECK(led_strip_clear(strip));
return strip;
}
static void update_rgb_led(led_strip_handle_t strip, float rms)
{
float red = 0.0f;
float green = 0.0f;
if (rms < GREEN_NOISE_RMS) {
green = LED_BRIGHTNESS * rms / GREEN_NOISE_RMS;
} else {
float red_fraction = (rms - GREEN_NOISE_RMS) /
(RED_NOISE_RMS - GREEN_NOISE_RMS);
if (red_fraction > 1.0f) {
red_fraction = 1.0f;
}
red = LED_BRIGHTNESS * red_fraction;
green = LED_BRIGHTNESS * (1.0f - red_fraction);
}
ESP_ERROR_CHECK(led_strip_set_pixel(strip, 0, (uint8_t)red,
(uint8_t)green, 0));
ESP_ERROR_CHECK(led_strip_refresh(strip));
}
static i2s_chan_handle_t init_microphone(void)
{
i2s_chan_handle_t rx_channel = NULL;
const i2s_chan_config_t channel_config =
I2S_CHANNEL_DEFAULT_CONFIG(I2S_NUM_0, I2S_ROLE_MASTER);
ESP_ERROR_CHECK(i2s_new_channel(&channel_config, NULL, &rx_channel));
i2s_std_config_t standard_config = {
.clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(SAMPLE_RATE_HZ),
.slot_cfg = I2S_STD_PHILIPS_SLOT_DEFAULT_CONFIG(
I2S_DATA_BIT_WIDTH_32BIT, I2S_SLOT_MODE_MONO),
.gpio_cfg = {
.mclk = I2S_GPIO_UNUSED,
.bclk = I2S_BCLK_GPIO,
.ws = I2S_WS_GPIO,
.dout = I2S_GPIO_UNUSED,
.din = I2S_DATA_GPIO,
.invert_flags = {
.mclk_inv = false,
.bclk_inv = false,
.ws_inv = false,
},
},
};
standard_config.slot_cfg.slot_mask = I2S_STD_SLOT_LEFT;
ESP_ERROR_CHECK(i2s_channel_init_std_mode(rx_channel, &standard_config));
ESP_ERROR_CHECK(i2s_channel_enable(rx_channel));
return rx_channel;
}
void app_main(void)
{
led_strip_handle_t rgb_led = init_rgb_led();
i2s_chan_handle_t microphone = init_microphone();
int32_t samples[SAMPLES_PER_READ];
float smoothed_rms = 0.0f;
uint32_t log_counter = 0;
ESP_LOGI(TAG, "INMP441 ready on BCLK=%d, WS=%d, SD=%d; RGB LED on GPIO %d",
I2S_BCLK_GPIO, I2S_WS_GPIO, I2S_DATA_GPIO, RGB_LED_GPIO);
while (true) {
size_t bytes_read = 0;
ESP_ERROR_CHECK(i2s_channel_read(microphone, samples, sizeof(samples),
&bytes_read, portMAX_DELAY));
const size_t sample_count = bytes_read / sizeof(samples[0]);
if (sample_count == 0) {
continue;
}
int64_t sum_squares = 0;
for (size_t i = 0; i < sample_count; ++i) {
// INMP441 provides 24-bit signed samples in the upper bits of each 32-bit slot.
const int32_t sample = samples[i] >> 8;
sum_squares += (int64_t)sample * sample;
}
const float rms = sqrtf((float)sum_squares / sample_count);
smoothed_rms += 0.2f * (rms - smoothed_rms);
update_rgb_led(rgb_led, smoothed_rms);
if (++log_counter == 16) {
ESP_LOGI(TAG, "sound RMS: %.0f", smoothed_rms);
log_counter = 0;
}
}
}
+3 -3
View File
@@ -10,8 +10,8 @@ from pytest_embedded_idf.utils import idf_parametrize
@pytest.mark.generic
@idf_parametrize('target', ['supported_targets'], indirect=['target'])
def test_blink(dut: IdfDut) -> None:
def test_buzz_detector(dut: IdfDut) -> None:
# check and log bin size
binary_file = os.path.join(dut.app.binary_path, 'blink.bin')
binary_file = os.path.join(dut.app.binary_path, 'buzz_detector.bin')
bin_size = os.path.getsize(binary_file)
logging.info('blink_bin_size : {}KB'.format(bin_size // 1024))
logging.info('buzz_detector_bin_size : {}KB'.format(bin_size // 1024))
-2
View File
@@ -1,2 +0,0 @@
CONFIG_BLINK_LED_GPIO=y
CONFIG_BLINK_GPIO=8
-1
View File
@@ -1 +0,0 @@
CONFIG_BLINK_GPIO=5
-1
View File
@@ -1 +0,0 @@
CONFIG_BLINK_LED_STRIP=y
-2
View File
@@ -1,2 +0,0 @@
CONFIG_BLINK_GPIO=27
CONFIG_BLINK_LED_STRIP=y
-1
View File
@@ -1 +0,0 @@
CONFIG_BLINK_LED_STRIP=y
-1
View File
@@ -1 +0,0 @@
CONFIG_BLINK_LED_STRIP=y
-1
View File
@@ -1 +0,0 @@
CONFIG_BLINK_LED_STRIP=y
-2
View File
@@ -1,2 +0,0 @@
CONFIG_BLINK_GPIO=44
CONFIG_BLINK_LED_STRIP=y
-2
View File
@@ -1,2 +0,0 @@
CONFIG_BLINK_LED_STRIP=y
CONFIG_BLINK_GPIO=18
-7
View File
@@ -1,7 +0,0 @@
CONFIG_BLINK_LED_STRIP=y
#
# Please Note:
# ESP32-S3-DevKitC v1.1 uses GPIO38 for the on-board LED
# ESP32-S3-DevKitC v1.0 uses GPIO48 for the on-board LED
#
CONFIG_BLINK_GPIO=38