From 7da1c2119d8b6fb9b8f7afc57edcab81bb8bdb84 Mon Sep 17 00:00:00 2001 From: Mitchell M Date: Tue, 13 Oct 2026 18:36:38 -0500 Subject: [PATCH] Implement INMP441 noise indicator with RGB LED feedback and update project configuration --- .vscode/settings.json | 4 +- README.md | 87 ++++--------- dependencies.lock | 20 +++ main/CMakeLists.txt | 3 +- main/Kconfig.projbuild | 49 -------- main/main.c | 138 ++++++++++++++++++++- pytest_blink.py => pytest_buzz_detector.py | 6 +- sdkconfig.defaults | 2 - sdkconfig.defaults.esp32 | 1 - sdkconfig.defaults.esp32c3 | 1 - sdkconfig.defaults.esp32c5 | 2 - sdkconfig.defaults.esp32c6 | 1 - sdkconfig.defaults.esp32c61 | 1 - sdkconfig.defaults.esp32h2 | 1 - sdkconfig.defaults.esp32p4 | 2 - sdkconfig.defaults.esp32s2 | 2 - sdkconfig.defaults.esp32s3 | 7 -- 17 files changed, 185 insertions(+), 142 deletions(-) create mode 100644 dependencies.lock delete mode 100644 main/Kconfig.projbuild rename pytest_blink.py => pytest_buzz_detector.py (68%) delete mode 100644 sdkconfig.defaults delete mode 100644 sdkconfig.defaults.esp32 delete mode 100644 sdkconfig.defaults.esp32c3 delete mode 100644 sdkconfig.defaults.esp32c5 delete mode 100644 sdkconfig.defaults.esp32c6 delete mode 100644 sdkconfig.defaults.esp32c61 delete mode 100644 sdkconfig.defaults.esp32h2 delete mode 100644 sdkconfig.defaults.esp32p4 delete mode 100644 sdkconfig.defaults.esp32s2 delete mode 100644 sdkconfig.defaults.esp32s3 diff --git a/.vscode/settings.json b/.vscode/settings.json index 9fa5202..c2db395 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -31,5 +31,7 @@ "--background-index", "--query-driver=**", "--compile-commands-dir=c:\\Users\\Mitchell\\cpp\\buzz_detector\\build" - ] + ], + "idf.flashType": "UART", + "idf.port": "COM6" } diff --git a/README.md b/README.md index 29f9e68..bc33071 100644 --- a/README.md +++ b/README.md @@ -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 `. +| 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. diff --git a/dependencies.lock b/dependencies.lock new file mode 100644 index 0000000..66198b1 --- /dev/null +++ b/dependencies.lock @@ -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 diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index 8a9d914..419d3f2 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -1,2 +1,3 @@ idf_component_register(SRCS "main.c" - INCLUDE_DIRS ".") + INCLUDE_DIRS "." + REQUIRES esp_driver_gpio esp_driver_i2s led_strip) diff --git a/main/Kconfig.projbuild b/main/Kconfig.projbuild deleted file mode 100644 index 58dad49..0000000 --- a/main/Kconfig.projbuild +++ /dev/null @@ -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 diff --git a/main/main.c b/main/main.c index 6ff73f7..a151240 100644 --- a/main/main.c +++ b/main/main.c @@ -1,13 +1,139 @@ -#include -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" +#include +#include + #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; + } + } } diff --git a/pytest_blink.py b/pytest_buzz_detector.py similarity index 68% rename from pytest_blink.py rename to pytest_buzz_detector.py index 55be95a..8733cc6 100644 --- a/pytest_blink.py +++ b/pytest_buzz_detector.py @@ -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)) diff --git a/sdkconfig.defaults b/sdkconfig.defaults deleted file mode 100644 index 66e7f24..0000000 --- a/sdkconfig.defaults +++ /dev/null @@ -1,2 +0,0 @@ -CONFIG_BLINK_LED_GPIO=y -CONFIG_BLINK_GPIO=8 diff --git a/sdkconfig.defaults.esp32 b/sdkconfig.defaults.esp32 deleted file mode 100644 index 263ec93..0000000 --- a/sdkconfig.defaults.esp32 +++ /dev/null @@ -1 +0,0 @@ -CONFIG_BLINK_GPIO=5 diff --git a/sdkconfig.defaults.esp32c3 b/sdkconfig.defaults.esp32c3 deleted file mode 100644 index da04430..0000000 --- a/sdkconfig.defaults.esp32c3 +++ /dev/null @@ -1 +0,0 @@ -CONFIG_BLINK_LED_STRIP=y diff --git a/sdkconfig.defaults.esp32c5 b/sdkconfig.defaults.esp32c5 deleted file mode 100644 index faee357..0000000 --- a/sdkconfig.defaults.esp32c5 +++ /dev/null @@ -1,2 +0,0 @@ -CONFIG_BLINK_GPIO=27 -CONFIG_BLINK_LED_STRIP=y diff --git a/sdkconfig.defaults.esp32c6 b/sdkconfig.defaults.esp32c6 deleted file mode 100644 index da04430..0000000 --- a/sdkconfig.defaults.esp32c6 +++ /dev/null @@ -1 +0,0 @@ -CONFIG_BLINK_LED_STRIP=y diff --git a/sdkconfig.defaults.esp32c61 b/sdkconfig.defaults.esp32c61 deleted file mode 100644 index da04430..0000000 --- a/sdkconfig.defaults.esp32c61 +++ /dev/null @@ -1 +0,0 @@ -CONFIG_BLINK_LED_STRIP=y diff --git a/sdkconfig.defaults.esp32h2 b/sdkconfig.defaults.esp32h2 deleted file mode 100644 index da04430..0000000 --- a/sdkconfig.defaults.esp32h2 +++ /dev/null @@ -1 +0,0 @@ -CONFIG_BLINK_LED_STRIP=y diff --git a/sdkconfig.defaults.esp32p4 b/sdkconfig.defaults.esp32p4 deleted file mode 100644 index cc80f60..0000000 --- a/sdkconfig.defaults.esp32p4 +++ /dev/null @@ -1,2 +0,0 @@ -CONFIG_BLINK_GPIO=44 -CONFIG_BLINK_LED_STRIP=y diff --git a/sdkconfig.defaults.esp32s2 b/sdkconfig.defaults.esp32s2 deleted file mode 100644 index 25fd93b..0000000 --- a/sdkconfig.defaults.esp32s2 +++ /dev/null @@ -1,2 +0,0 @@ -CONFIG_BLINK_LED_STRIP=y -CONFIG_BLINK_GPIO=18 diff --git a/sdkconfig.defaults.esp32s3 b/sdkconfig.defaults.esp32s3 deleted file mode 100644 index f97c4ba..0000000 --- a/sdkconfig.defaults.esp32s3 +++ /dev/null @@ -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