A decibel meter themed after Fallout is a nice addition to my pedalboard for tracking room noise levels. The initial display features the vault logo and indicates the current decibels. The second screen presents system information against a Pip-Boy backdrop. The third screen offers a clock, calendar, and a cheerful thumbs-up icon. There’s also a 4th screen I use to write simple notes like uncommon tunings. I rarely use the last anymore after buying a strobestomp. It can be easily altered or removed via the code below.
I coated the enclosure with a spray on textured rubber making it difficult to identify the buttons that are on the right side. They still function normally and should add some life to them. The above image looks a little washed in this pic. Image clarity on the device is identical to what is shown below.
It’s worth downloading a mobile app to calibrate(ballpark) your specific mic. There are notable variations in these types.
Materials:
- HiLetgo ESP32 LCD WiFi Kit ESP-32 1.14 Inch LCD Display
- Omnidirectional Microphone Module I2S Interface INMP441 MEMS
- (Optional) 2000mAh 103454 Lipo Rechargeable Battery Pack with Wire JST Connector
Usage:
- Upper Button: Turns device on and resets
- Top Button : Scrolls through multiple pages
- Lower Button : Long press powers off the device
Place these 5 images in the root of your homeassistant / esphome dir.
esphome:
name: decibel-monitor
platform: esp32
board: ttgo-t7-v13-mini32
external_components:
- source: github://stas-sl/esphome-sound-level-meter
# Enable logging
logger:
level: DEBUG
# Enable Home Assistant API
api:
encryption:
key: "your key here"
ota:
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "Esphome-Web-90E240"
password: "your pw here"
captive_portal:
# ---------------------------
# INMP441 I2S MEMS microphone
# VDD 3V3
# GND GND
# SD D26
# L/R GND
# WS D25
# SCK D5
status_led:
pin: 2
i2s:
bck_pin: GPIO15 # SCK
ws_pin: GPIO17 # WS
din_pin: GPIO39 # SD
sample_rate: 48000 # default: 48000
bits_per_sample: 32 # default: 32
# 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: 1s # default: 60s
# 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
# see your mic datasheet to find sensitivity and reference SPL.
# those are used to convert dB FS to db SPL
mic_sensitivity: 5dB # default: empty
mic_sensitivity_ref: 90dB # default: empty
# for flexibility sensors are organized hierarchically into groups.
# each group can have any number of filters, sensors and nested groups.
# for examples if there is a top level group A with filter A and nested
# group B with filter B, then for sensors inside group B filters A
# and then B will be applied:
# groups:
# # group A
# - filters:
# - filter A
# groups:
# # group B
# - filters:
# - filter B
# sensors:
# - sensor X
groups:
- sensors:
- type: eq
name: Leq_1s
# automation
# available actions:
# - sound_level_meter.turn_on
# - sound_level_meter.turn_off
# - sound_level_meter.toggle
switch:
- platform: template
name: "ON / OFF"
lambda: |-
return id(sound_level_meter1).is_on();
turn_on_action:
then: sound_level_meter.turn_on
turn_off_action:
then: sound_level_meter.turn_off
restore_mode: RESTORE_DEFAULT_ON
- platform: restart
name: "Reset"
button:
- platform: shutdown
name: "Shutdown"
id: ttgo_off
sensor:
- platform: internal_temperature
name: "Temp"
- platform: homeassistant
id: dmeter
entity_id: sensor.Leq_1s
internal: true
filters:
- filter_out: "nan"
- platform: wifi_signal
name: "Signal dB"
id: wifi_signal_db
update_interval: 60s
entity_category: "diagnostic"
- platform: copy
source_id: wifi_signal_db
name: "Signal Percent"
filters:
- lambda: return min(max(2 * (x + 100.0), 0.0), 100.0);
unit_of_measurement: "%"
entity_category: "diagnostic"
device_class: ""
- platform: adc
pin: 33
name: "Battery Voltage"
attenuation: 11db
unit_of_measurement: 'V'
update_interval: 60s
filters:
- calibrate_linear:
# Map 0.0 (from sensor) to 0.0 (true value)
- 0.0 -> 0.0
- 2.06 -> 1.89
- lambda: return x * 2.0;
- platform: adc
pin: 34
name: "Battery Charge"
update_interval: 60s
unit_of_measurement: '%'
filters:
- sliding_window_moving_average:
window_size: 15
send_every: 15
- calibrate_linear:
# Map 0.0 (from sensor) to 0.0 (true value)
- 0.0 -> 0.0
- 1.1 -> 100.0
binary_sensor:
- platform: status
name: "Status"
id: system_status
- platform: gpio
pin:
number: GPIO0
inverted: true
name: dmeter bottom push
id: tdisplay_button_input_0
on_click:
- min_length: 100ms
max_length: 350ms
then:
- button.press: ttgo_off
- platform: gpio
pin:
number: GPIO35
inverted: true
id: tdisplay_button_input_1
name: dmeter top push
on_click:
- min_length: 50ms
max_length: 350ms
then:
- display.page.show_next: my_display
- component.update: my_display
text_sensor:
- platform: wifi_info
ip_address:
name: "IP"
id: addy
ssid:
name: "SSID"
id: base
mac_address:
name: "Mac"
id: mac
color:
- id: my_red
red: 100%
green: 0%
blue: 0%
- id: my_yellow
hex: dfb843
- id: my_green
hex: 4b931b
- id: my_blue
red: 0%
green: 0%
blue: 100%
- id: my_dblue
red: 0%
green: 0%
blue: 70%
- id: my_orange
red: 80%
green: 20%
blue: 0%
- id: my_gray
red: 50%
green: 50%
blue: 50%
- id: my_wht
red: 75%
green: 75%
blue: 75%
font:
- file: "OpenSans-Bold.ttf"
id: helvetica_48
size: 84
- file: "OpenSans-Bold.ttf"
id: helvetica_T
size: 60
- file: "OpenSans-Bold.ttf"
id: helvetica_24
size: 32
- file: "OpenSans-Bold.ttf"
id: helvetica_S
size: 12
- file: "OpenSans-Bold.ttf"
id: helvetica_M
size: 24
- file: "NotoMusic-Regular.ttf"
id: music_M
size: 24
glyphs: ♯♪!"%()+=,-_.:°/?0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz
# put a ttf font called Helvetica.ttf in the esphome folder
time:
- platform: homeassistant
id: esptime
spi:
clk_pin: GPIO18
mosi_pin: GPIO19
#interval:
# - interval: 30s
# then:
# - display.page.show: page1
# - component.update: my_display
image:
- file: "wifi-on.png"
id: wifion
type: RGB24
- file: "wifi-off.png"
id: wifioff
type: RGB24
- file: "vaultbkg.jpg"
id: vaultbkg
type: RGB24
- file: "pboy.jpg"
id: pboy
type: RGB24
- file: "fobk.jpg"
id: fobk
type: RGB24
display:
- platform: st7789v
model: TTGO TDisplay 135x240
backlight_pin: GPIO4
update_interval: 1s
eightbitcolor: False
cs_pin: GPIO5
dc_pin: GPIO16
reset_pin: GPIO23
rotation: 90
id: my_display
pages:
- id: page1
lambda: |-
it.image(0, 0, id(vaultbkg));
it.printf(169, 64, id(helvetica_48), id(my_yellow), TextAlign::CENTER_RIGHT, "%.0f", id(dmeter).state);
it.printf(236, 120, id(helvetica_M), id(my_gray), TextAlign::CENTER_RIGHT, "dB");
if (id(system_status).state) {
it.image(207, 0, id(wifion));
}
else {
it.image(207, 0, id(wifioff));
}
- id: page2
lambda: |-
it.image(0, 0, id(pboy));
it.printf( 50, 70, id(helvetica_S), id(my_green),"Signal: %.0fdB", id(wifi_signal_db).state);
it.printf( 50, 40, id(helvetica_S), id(my_green), "%s", id(addy).state.c_str());
it.printf( 50, 55, id(helvetica_S), id(my_green), "%s", id(mac).state.c_str());
it.printf( 50, 25, id(helvetica_S), id(my_green), "%s", id(base).state.c_str());
- id: page3
lambda: |-
it.image(0, 0, id(fobk));
it.strftime(0, 0, id(helvetica_T), id(my_wht), "%I:%M:%S", id(esptime).now());
it.strftime(10, 68, id(helvetica_M), id(my_gray), "%m-%d-%Y", id(esptime).now());
it.strftime(10, 98, id(helvetica_M), id(my_blue), "%A", id(esptime).now());
- id: page4
lambda: |-
it.printf(10, 0, id(helvetica_M), id(my_gray), "STD C:");
it.printf(10, 30, id(music_M), id(my_gray), "C - F - A♯ - D♯ - G - C");