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
+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;
}
}
}