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