I’m having an ESP32-C3 doing decibel measurements with an I2S microphone ( GitHub - stas-sl/esphome-sound-level-meter ).
The debug log loop time shows it takes 6000+ ms and the web interface is responding slowly. (15+seconds before all values are loaded)
Another board (same ESP32-C3 from Olimex) runs the bluetooth Proxy for home assistant and has a loop time of 30ms, the web interface is fast there.
Is I2S audio so heavy or is the ESP32-C3 not performant enough? Would a regular ESP32 or an ESP32-S3 be faster?
This is the YAML of the “fast” ESP32-C3 that only does the bluetooth proxy, loop time 30ms:
substitutions:
display_name: bleproxy
esphome:
name: ${display_name}
name_add_mac_suffix: true
project:
name: "ble_proxy"
version: "1.0.0"
platformio_options:
board_build.mcu: esp32c3
board_build.variant: esp32c3
includes:
# should contain single line: #include <esp_task_wdt.h>
- wdt_include.h
on_boot:
then:
- lambda: !lambda |-
// increase watchdog timeout
esp_task_wdt_init(90, false);
preferences:
flash_write_interval: 10min
esp32:
variant: ESP32C3
board: esp32dev
framework:
type: esp-idf
sdkconfig_options:
CONFIG_BT_BLE_50_FEATURES_SUPPORTED: y
CONFIG_BT_BLE_42_FEATURES_SUPPORTED: y
# CONFIG_COMPILER_OPTIMIZATION_PERF: y
CONFIG_ESP_TASK_WDT_TIMEOUT_S: "90"
CONFIG_COMPILER_OPTIMIZATION_SIZE: y
status_led:
pin:
number: GPIO8
inverted: true
logger:
# logs:
# component: ERROR
#level: INFO
debug:
update_interval: 1s
api:
ota:
safe_mode: true
password: !secret ota_password
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
fast_connect: true
reboot_timeout: 60s
ap:
ssid: !secret ap_ssid
password: !secret ap_pass
esp32_ble_tracker:
# scan_parameters:
# interval: 1100ms
# window: 1100ms
# active: false
# continuous: false
bluetooth_proxy:
active: true
sensor:
- platform: internal_temperature
name: "${display_name} Internal Temperature"
update_interval: 1s
- platform: wifi_signal
name: "${display_name} WiFi Signal"
update_interval: 1s
- platform: uptime
name: "${display_name} uptime"
update_interval: 1s
- platform: debug
free:
name: "${display_name} Heap Free"
block:
name: "${display_name} Heap Max Block"
loop_time:
name: "${display_name} Loop Time"
text_sensor:
- platform: version
hide_timestamp: true
name: "${display_name} ESPHome Version"
- platform: wifi_info
ip_address:
name: "${display_name} IP Address"
icon: mdi:wifi
ssid:
name: "${display_name} Connected SSID"
icon: mdi:wifi-strength-2
dns_address:
name: "${display_name} DNS Address"
- platform: debug
device:
name: "${display_name} Device Info"
reset_reason:
name: "${display_name} Reset Reason"
button:
- platform: safe_mode
name: "${display_name} (Safe Mode)"
web_server:
auth:
username: !secret web_username
password: !secret web_password
time:
- platform: sntp
id: sntp_time
timezone: Europe/Amsterdam
servers:
- 0.pool.ntp.org
- 1.pool.ntp.org
- 2.pool.ntp.org
This is the YAML of the decibel meter, the slow ESP32-C3 (6000+ms loop time):
substitutions:
display_name: decibelMeter
esphome:
name: ${display_name}
name_add_mac_suffix: true
project:
name: "decibel_meter"
version: "1.0.0"
platformio_options:
board_build.mcu: esp32c3
board_build.variant: esp32c3
includes:
# should contain single line: #include <esp_task_wdt.h>
- wdt_include.h
on_boot:
then:
- lambda: !lambda |-
// increase watchdog timeout
esp_task_wdt_init(90, false);
external_components:
- source: github://stas-sl/esphome-sound-level-meter # add @tag if you want to use a specific version (e.g @v1.0.0)
esp32:
variant: ESP32C3
board: esp32dev
framework:
type: esp-idf
sdkconfig_options:
CONFIG_BT_BLE_50_FEATURES_SUPPORTED: y
CONFIG_BT_BLE_42_FEATURES_SUPPORTED: y
CONFIG_COMPILER_OPTIMIZATION_PERF: y
CONFIG_ESP_TASK_WDT_TIMEOUT_S: "90"
status_led:
pin:
number: GPIO8
inverted: true
logger:
logs:
component: ERROR # filters out these logs: Component api took a long time for an operation (424 ms).
#level: INFO
debug:
update_interval: 120s
api:
ota:
safe_mode: true
password: !secret ota_password
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
fast_connect: true
reboot_timeout: 60s
ap:
ssid: !secret ap_ssid
password: !secret ap_pass
i2s:
bck_pin: 4
ws_pin: 5
din_pin: 6
sample_rate: 48000 # default: 48000
bits_per_sample: 32 # default: 32
dma_buf_count: 8 # default: 8
dma_buf_len: 256 # default: 256
use_apll: true # default: false
# right shift samples.
# for example if mic has 24 bit resolution, and
# i2s configured as 32 bits, then audio data will be aligned left (MSB)
# and LSB will be padded with zeros, so you might want to shift them right by 8 bits
bits_shift: 8 # default: 0
sound_level_meter:
id: sound_level_meter1
# update_interval specifies over which interval to aggregate audio data
# you can specify default update_interval on top level, but you can also override
# it further by specifying it on sensor level
update_interval: 5s # default: 60s
# you can disable (turn off) component by default (on boot)
# and turn it on later when needed via sound_level_meter.turn_on/toggle actions;
# when used with switch it might conflict/being overriden by
# switch state restoration logic, so you have to either disable it in
# switch config and then is_on property here will have effect,
# or completely rely on switch state restoration/initialization and
# any value set here will be ignored
is_on: true # default: true
# buffer_size is in samples (not bytes), so for float data type
# number of bytes will be buffer_size * 4
buffer_size: 1024 # default: 1024
# ignore audio data at startup for this long
warmup_interval: 500ms # default: 500ms
# audio processing runs in a separate task, you can change its settings below
task_stack_size: 4096 # default: 4096
task_priority: 2 # default: 2
task_core: 1 # default: 1
# see your mic datasheet to find sensitivity and reference SPL.
# those are used to convert dB FS to db SPL
mic_sensitivity: -26dB # default: empty
mic_sensitivity_ref: 94dB # default: empty
# additional offset if needed
offset: 0dB # default: empty
groups:
- filters:
# for now only SOS filter type is supported, see math/filter-design.ipynb
# to learn how to create or convert other filter types to SOS
- type: sos
coeffs:
# INMP441:
# b0 b1 b2 a1 a2
- [ 1.0019784 , -1.9908513 , 0.9889158 , -1.9951786 , 0.99518436]
# nested groups
groups:
# group 1.1 (no weighting)
- sensors:
# 'eq' type sensor calculates Leq (average) sound level over specified period
- type: eq
name: ${display_name}_LZeq_1min
id: ${display_name}_LZeq_1min
unit_of_measurement: dB(Z)
# 'max' sensor type calculates Lmax with specified window_size.
# for example, if update_interval is 60s and window_size is 1s
# then it will calculate 60 Leq values for each second of audio data
# and the result will be max of them
- type: max
name: ${display_name} LZmax_1s_1min
id: ${display_name}_LZmax_1s_1min
window_size: 1s
unit_of_measurement: dB(Z)
# same as 'max', but 'min'
- type: min
name: ${display_name} LZmin_1s_1min
id: ${display_name}_LZmin_1s_1min
window_size: 1s
unit_of_measurement: dB(Z)
# it finds max single sample over whole update_interval
- type: peak
name: ${display_name} LZpeak_1min
id: ${display_name}_LZpeak_1min
unit_of_measurement: dB(Z)
# group 1.2 (A-weighting)
- filters:
# for now only SOS filter type is supported, see math/filter-design.ipynb
# to learn how to create or convert other filter types to SOS
- type: sos
coeffs:
# A-weighting:
# b0 b1 b2 a1 a2
- [ 0.16999495 , 0.741029 , 0.52548885 , -0.11321865 , -0.056549273]
- [ 1. , -2.00027 , 1.0002706 , -0.03433284 , -0.79215795 ]
- [ 1. , -0.709303 , -0.29071867 , -1.9822421 , 0.9822986 ]
sensors:
- type: eq
name: ${display_name} LAeq_1min_1s
id: ${display_name}_LAeq_1min_1s
unit_of_measurement: dB(A)
update_interval: 1s
- type: eq
name: ${display_name} LAeq_1min
id: ${display_name}_LAeq_1min
unit_of_measurement: dB(A)
- type: max
name: ${display_name} LAmax_1s_1min
id: ${display_name}_LAmax_1s_1min
window_size: 1s
unit_of_measurement: dB(A)
- type: min
name: ${display_name} LAmin_1s_1min
id: ${display_name}_LAmin_1s_1min
window_size: 1s
unit_of_measurement: dB(A)
- type: peak
name: ${display_name} LApeak_1min
id: ${display_name}_LApeak_1min
unit_of_measurement: dB(A)
# group 1.3 (C-weighting)
- filters:
# for now only SOS filter type is supported, see math/filter-design.ipynb
# to learn how to create or convert other filter types to SOS
- type: sos
coeffs:
# C-weighting:
# b0 b1 b2 a1 a2
- [-0.49651518 , -0.12296628 , -0.0076134163, -0.37165618 , 0.03453208 ]
- [ 1. , 1.3294908 , 0.44188643 , 1.2312505 , 0.37899444 ]
- [ 1. , -2. , 1. , -1.9946145 , 0.9946217 ]
sensors:
- type: eq
name: ${display_name} 4LCeq_1min
id: ${display_name}_LCeq_1min
unit_of_measurement: dB(C)
- type: max
name: ${display_name} LCmax_1s_1min
id: ${display_name}_LCmax_1s_1min
window_size: 1s
unit_of_measurement: dB(C)
- type: min
name: ${display_name} LCmin_1s_1min
id: ${display_name}_LCmin_1s_1min
window_size: 1s
unit_of_measurement: dB(C)
- type: peak
name: ${display_name} LCpeak_1min
id: ${display_name}_LCpeak_1min
unit_of_measurement: dB(C)
# automation
# available actions:
# - sound_level_meter.turn_on
# - sound_level_meter.turn_off
# - sound_level_meter.toggle
switch:
- platform: template
name: "${display_name} Sound Level Meter Switch"
# if you want is_on property on component to have effect, then set
# restore_mode to DISABLED, or alternatively you can use other modes
# (more on them in esphome docs), then is_on property on the component will
# be overriden by the switch
restore_mode: DISABLED # ALWAYS_OFF | ALWAYS_ON | RESTORE_DEFAULT_OFF | RESTORE_DEFAULT_ON
lambda: |-
return id(sound_level_meter1).is_on();
turn_on_action:
- sound_level_meter.turn_on
turn_off_action:
- sound_level_meter.turn_off
- platform: restart
name: "${display_name} Restart"
sensor:
- platform: internal_temperature
name: "${display_name} Internal Temperature"
update_interval: 300s
- platform: wifi_signal
name: "${display_name} WiFi Signal"
update_interval: 300s
- platform: uptime
name: "${display_name} uptime"
- platform: debug
free:
name: "${display_name} Heap Free"
block:
name: "${display_name} Heap Max Block"
loop_time:
name: "${display_name} Loop Time"
text_sensor:
- platform: version
hide_timestamp: true
name: "${display_name} ESPHome Version"
- platform: wifi_info
ip_address:
name: "${display_name} IP Address"
icon: mdi:wifi
ssid:
name: "${display_name} Connected SSID"
icon: mdi:wifi-strength-2
dns_address:
name: "${display_name} DNS Address"
- platform: debug
device:
name: "${display_name} Device Info"
reset_reason:
name: "${display_name} Reset Reason"
button:
- platform: safe_mode
name: "${display_name} (Safe Mode)"
web_server:
auth:
username: !secret web_username
password: !secret web_password
time:
- platform: sntp
id: sntp_time
timezone: Europe/Amsterdam
servers:
- 0.pool.ntp.org
- 1.pool.ntp.org
- 2.pool.ntp.org