ESPhome Decibel Meter - HW-484/KY-037/KY-038

A few months ago I requested a new feature from Amazon to make sure my Echo doesn’t yell at me in the silence of the night when I talk to it. Unfortunately they sent me a standard email and did nothing. So, hating it, I installed the home assistant, bought my first ESP8266, went back to studying programming, learned logarithm function, fell in love with ESPhome.

Now that I’ve been using it for a few days I decided to bring my “sensor” to make it easier for anyone who has any similar problem or want to make some use with a decibelimeter with the HW-484/KY-037 or any other sound sensor, because I believe it doesn’t have much difference.

You should be able to adjust the sensitivity of the same through the potentiometer, but as the exact sensitivity of each microphone can vary, I left a sensitivity slider on the sensor that should approximate the values ​​of the decibelimeter, if you want to try to get it right, you can use some application in the your smartphone that should make it easier, my initial setting was at 36.5 sensitivity. If you do too, share which sensitivity was good for you and so we can build a pattern.
If you prefer to just use the sensor in its raw version, I’m already exporting this data to the home assistant.

The connection was made on analog port 0 and the power supply was made through 3.3v, I believe that the voltage can bring a lot of difference to your measurements.

I hope it’s useful for someone else. Feedback and suggestions to change the code are very welcome.

esphome:
  name: volume-sensor

esp8266:
  board: nodemcuv2

logger:

api:
  encryption:
    key: !secret apikey

ota:
  password: !secret ota

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

  ap:
    ssid: "Volume-Sensor Fallback Hotspot"
    password: !secret wifi_password

captive_portal:
    

globals:

  - id: esphome_sensitivity
    type: float
    initial_value: '36.5'
    restore_value: yes

  - id: esphome_volume
    type: int

sensor:
  - platform: adc
    pin: A0
    id: esphome_db
    device_class: signal_strength
    name: "Db SoundEsp"
    icon: "mdi:volume-vibrate"
    unit_of_measurement: "db"
    update_interval: 5s
    raw: true
    filters:
      - lambda: |-
          unsigned int sample;
          unsigned long startMillis= millis(); 
          float peakToPeak = 0; 
          unsigned int signalMax = 0;
          unsigned int signalMin = 1024;
          while (millis() - startMillis < 500) {
            sample = analogRead(A0);
            if (sample < 1024){
                if (sample > signalMax){
                    signalMax = sample;
                }
                else if (sample < signalMin){
                    signalMin = sample;
                }
              }
          }
          peakToPeak = map((signalMax - signalMin),1,1024,1.5,1024);
          id(esphome_volume) = peakToPeak;
          float state = id(esphome_sensitivity)*log10(peakToPeak)+15;  
          return(state);

  - platform: template
    name: "Volume SoundEsp"
    icon: "mdi:volume-high"
    unit_of_measurement: "%"
    update_interval: 5s
    lambda: return(map((id(esphome_db).state),15,150,0,100));

  - platform: template
    name: "RAW SoundEsp"
    icon: "mdi:volume-source"
    unit_of_measurement: "%"
    update_interval: 5s
    lambda: return(map(id(esphome_volume),1,1024,0,100));

number:
  - platform: template
    id: sensitivity_slider
    name: "Sensitivity SoundEsp"
    icon: "mdi:knob"
    update_interval: 5s
    initial_value: "36.5"
    step: 0.1
    min_value: 20
    max_value: 40
    mode: slider
    set_action:
      then:
        - lambda:  id(esphome_sensitivity) = x;

20 Likes

Put this thing in a cheap box or make a stealth version (like a hidden camera), do some iterations on KickStarter (for example, adding a calibration feature that is legally recognized), and you have a viable business.

If it’s just your hobby: Congratulations, you are smarter than the average human and potentially someone will use it someday.

6 Likes

Hi, how is this holding up to now?
Im trying to get something like this in a bathroom environment, when the running shower is going
Do you think it will pick up on this?
How far does it need to be from the noise?
I got myself a GY-MAX4466 sensor but i cant figure this one out.
Which one out of the 3 sensor that you tried in your project? I might give yours a shot

Keen for a device for homeassistant as I currently use minut noise monitor for our Airbnb’s but it gets expensive with the subscription for 5 homes when I seldom use it

1 Like

@Reubertt: I try to make a similar thing (here, observing laundry noise), simply reading ADC values from the same microphone KY-038. But I have severe issues in getting a good sensitivity: Sound amplitudes of silence and noise differ only by a small margin in the resolution of the ADC.

I placed some measurements here: Reading a Microphone - ESPHome - Home Assistant Community (home-assistant.io)

Can you confirm the same measurement quality, or could I assume that your code is superior in getting reasonable measurements?

1 Like

Hmm. I just tried your code. I think the 500ms high frequency sampling in the lambda are really a good idea. However, I still have to yell into the mic to get a signalMax to signalMin span that is usefull. Normal talking in a 50cm distance is in the magnitude of AC noise :frowning:

Any hint?

1 Like

Thank you very much for the effort, I had an unused vibration sensor, I changed the component for an electric microphone that I had lying around and it worked perfectly with your code

1 Like

Thanks for the great job.
Bye
Claudio

Anyone got this to work with a KY-038? I get 15db and 0% Raw sound unless I clap really loudly beside the mic

@Reubertt thanks for sharing the code. I used it in my “detect when house fire alarm is on” project, works good for detecting normal vs loud.

I added two tweaks.

A binary sensor to detect “loudness has reached predefined level”:

binary_sensor:
  - platform: analog_threshold
    name: ATS alarm triggered
    sensor_id: volume_soundesp
    threshold:
      upper: 110.0
      lower: 80.0
    device_class: smoke

A sliding window sensor to smoothe out peaks:

  - platform: copy
    source_id: esphome_db
    name: "Db SoundEsp Average"
    filters:
      - sliding_window_moving_average:
          window_size: 15
          send_every: 5

I’m using D1 mini (v4) for this. Encountered an issue where at times the board would not connect to WiFi (password correct, but “auth token failure”). Reducing the update_interval of the ADC sensor from 5s to 10s solved this issue. Possibly related to computation/CPU interference with wifi on short reads.

Also created a case for ESP+MAX4466 if someone finds it useful to deploy a standalone sensor: Printables

1 Like

sama problem here did you resolve that ?

Thanks planning on using this to measure the sound of air pumps for fish rooms as I adjust their available power

lot of people start fish room and keep needing larger pumps as they expand, I have been playing around with a variac and it’s working a dream adjusting the pumps speed and pressure changing the AC voltage from 20v - 240v

now I just want to log the volts , watts , air flow rates , pressure and db levels and throw it all in a chart

as there is jack all price difference between the cost of pumps to double their capacities ~$10 increase from 20lpm to 40lpm to 60lpm to 100lpm to 200lpm

I normally settle for stocking ~100 lpm pumps

tho finding somewhere quiet at home is going to be hard

bathrooms quietest place and it’s over 40db

manufacture rated airpump 45db and I get 60db under load and 70db no load and pc sits at 60db

1 Like

Same problem here with KY-037

how is this holding up for you? Does it work well to detect a smoke alarm?

Wonder if we can rework the code to use the M5STACK Atom Echo?

It’s working fine for smoke alarm detection (basically a binary sensor, set with a high trigger compared to normal). We’ve had some real alarm triggers (but false-positive luckily), the detector caught them and notified. Downside is any kind of sustained high level noise (vacuum) also triggers it. Matter of tuning perhaps.

Hello can this work with esp 32?
what must be change in the code?

Hermen, Did you manage to get this done?

I want to use ESPNow to send a results to a receiver unit to show if a room at work is occupied or not (meeting room without windows) based on the noise in the room.

Thanks

Hey @sqroot,

I too would want to use KY-037 to detect smoke alarms. I’ve got a few ESP32 boards lying around. Would the code be exactly the same?

Furthermore, as I’m far from an expert, would you mind posting your entire code? I’m not really sure how your tweaks fit in (or maybe which parts of the original code are obsolete for just detecting smoke alarms).

(I assume this would also help @Hermenthuis.)

Thanks in advance!

I didn’t get it to work for now…

I tried with this yaml code:

sensor:
  - platform: adc
    pin: GPIO32
    name: "Rookmelder tuinhuis"
    update_interval: 250ms
binary_sensor:
  - platform: gpio
    pin: GPIO33
    name: "Sound level"
    filters:
      - delayed_off: 1s

The analog output is constant, there’s no change in voltage, whether I make noise or not. The digital output works:

[18:05:20][D][sensor:094]: 'Rookmelder tuinhuis': Sending state 4095.00000 V with 2 decimals of accuracy
[18:05:20][D][sensor:094]: 'Rookmelder tuinhuis': Sending state 4095.00000 V with 2 decimals of accuracy
[18:05:20][D][sensor:094]: 'Rookmelder tuinhuis': Sending state 4095.00000 V with 2 decimals of accuracy
[18:05:20][D][sensor:094]: 'Rookmelder tuinhuis': Sending state 4095.00000 V with 2 decimals of accuracy
[18:05:20][D][sensor:094]: 'Rookmelder tuinhuis': Sending state 4095.00000 V with 2 decimals of accuracy
[18:05:21][D][sensor:094]: 'Rookmelder tuinhuis': Sending state 4095.00000 V with 2 decimals of accuracy
[18:05:21][D][sensor:094]: 'Rookmelder tuinhuis': Sending state 4095.00000 V with 2 decimals of accuracy
[18:05:21][D][sensor:094]: 'Rookmelder tuinhuis': Sending state 4095.00000 V with 2 decimals of accuracy
[18:05:21][D][sensor:094]: 'Rookmelder tuinhuis': Sending state 4095.00000 V with 2 decimals of accuracy
[18:05:22][D][sensor:094]: 'Rookmelder tuinhuis': Sending state 4095.00000 V with 2 decimals of accuracy
[18:05:22][D][sensor:094]: 'Rookmelder tuinhuis': Sending state 4095.00000 V with 2 decimals of accuracy
[18:05:22][D][binary_sensor:036]: 'Sound level': Sending state ON
[18:05:22][D][sensor:094]: 'Rookmelder tuinhuis': Sending state 4095.00000 V with 2 decimals of accuracy
[18:05:22][D][sensor:094]: 'Rookmelder tuinhuis': Sending state 4095.00000 V with 2 decimals of accuracy
[18:05:23][D][sensor:094]: 'Rookmelder tuinhuis': Sending state 4095.00000 V with 2 decimals of accuracy
[18:05:23][D][sensor:094]: 'Rookmelder tuinhuis': Sending state 4095.00000 V with 2 decimals of accuracy
[18:05:23][D][sensor:094]: 'Rookmelder tuinhuis': Sending state 4095.00000 V with 2 decimals of accuracy
[18:05:24][D][sensor:094]: 'Rookmelder tuinhuis': Sending state 4095.00000 V with 2 decimals of accuracy
[18:05:24][D][sensor:094]: 'Rookmelder tuinhuis': Sending state 4095.00000 V with 2 decimals of accuracy
[18:05:24][D][sensor:094]: 'Rookmelder tuinhuis': Sending state 4095.00000 V with 2 decimals of accuracy
[18:05:24][D][binary_sensor:036]: 'Sound level': Sending state OFF
[18:05:24][D][sensor:094]: 'Rookmelder tuinhuis': Sending state 4095.00000 V with 2 decimals of accuracy
[18:05:24][D][sensor:094]: 'Rookmelder tuinhuis': Sending state 4095.00000 V with 2 decimals of accuracy
[18:05:25][D][sensor:094]: 'Rookmelder tuinhuis': Sending state 4095.00000 V with 2 decimals of accuracy
[18:05:25][D][sensor:094]: 'Rookmelder tuinhuis': Sending state 4095.00000 V with 2 decimals of accuracy
[18:05:25][D][sensor:094]: 'Rookmelder tuinhuis': Sending state 4095.00000 V with 2 decimals of accuracy
[18:05:25][D][sensor:094]: 'Rookmelder tuinhuis': Sending state 4095.00000 V with 2 decimals of accuracy
[18:05:26][D][sensor:094]: 'Rookmelder tuinhuis': Sending state 4095.00000 V with 2 decimals of accuracy
[18:05:26][D][sensor:094]: 'Rookmelder tuinhuis': Sending state 4095.00000 V with 2 decimals of accuracy
[18:05:26][D][sensor:094]: 'Rookmelder tuinhuis': Sending state 4095.00000 V with 2 decimals of accuracy

Does anyone have any idea what the issue is? This guy (https://www.youtube.com/watch?v=ySSpbg1OWGU) got it to work… I don’t have any Arduino knowledge, but he must get some raw data, which I should be getting as well?


Earlier, I noticed some unexpected changes, but I later realized they probably were the result of turning the screw of the potentiometer:

There’s no change in voltage, whether I make noise or not. Weirdly, I first saw this:

[14:06:25][D][sensor:094]: 'Rookmelder tuinhuis': Sending state 0.10600 V with 2 decimals of accuracy
[14:06:26][D][sensor:094]: 'Rookmelder tuinhuis': Sending state 0.10700 V with 2 decimals of accuracy
[14:06:27][D][sensor:094]: 'Rookmelder tuinhuis': Sending state 0.10700 V with 2 decimals of accuracy
[14:06:28][D][sensor:094]: 'Rookmelder tuinhuis': Sending state 0.10700 V with 2 decimals of accuracy
[14:06:29][D][sensor:094]: 'Rookmelder tuinhuis': Sending state 0.10800 V with 2 decimals of accuracy
[14:06:30][D][sensor:094]: 'Rookmelder tuinhuis': Sending state 0.10700 V with 2 decimals of accuracy
[14:06:31][D][sensor:094]: 'Rookmelder tuinhuis': Sending state 0.10800 V with 2 decimals of accuracy
[14:06:32][D][sensor:094]: 'Rookmelder tuinhuis': Sending state 0.10600 V with 2 decimals of accuracy
[14:06:33][D][sensor:094]: 'Rookmelder tuinhuis': Sending state 0.10700 V with 2 decimals of accuracy

At one moment, I accidentally stepped on the device. :roll_eyes: No idea whether it was related, but I later noticed this output:

[14:49:48][D][sensor:094]: 'Rookmelder tuinhuis': Sending state 0.82800 V with 2 decimals of accuracy
[14:49:49][D][sensor:094]: 'Rookmelder tuinhuis': Sending state 1.04500 V with 2 decimals of accuracy
[14:49:50][D][sensor:094]: 'Rookmelder tuinhuis': Sending state 1.04500 V with 2 decimals of accuracy
[14:49:51][D][sensor:094]: 'Rookmelder tuinhuis': Sending state 1.04500 V with 2 decimals of accuracy
[14:49:52][D][sensor:094]: 'Rookmelder tuinhuis': Sending state 1.04500 V with 2 decimals of accuracy

I plugged in another KY-037 unit (I bought a pack of 5), and now this is the output:

[17:43:06][D][sensor:094]: 'Rookmelder tuinhuis': Sending state 0.14700 V with 2 decimals of accuracy
[17:43:11][D][sensor:094]: 'Rookmelder tuinhuis': Sending state 0.14700 V with 2 decimals of accuracy
[17:43:13][D][sensor:094]: 'Rookmelder tuinhuis': Sending state 0.14400 V with 2 decimals of accuracy
[17:43:13][D][sensor:094]: 'Rookmelder tuinhuis': Sending state 0.14700 V with 2 decimals of accuracy
[17:43:13][D][sensor:094]: 'Rookmelder tuinhuis': Sending state 0.14700 V with 2 decimals of accuracy
[17:43:13][D][sensor:094]: 'Rookmelder tuinhuis': Sending state 0.14600 V with 2 decimals of accuracy
[17:43:13][D][sensor:094]: 'Rookmelder tuinhuis': Sending state 0.14500 V with 2 decimals of accuracy
[17:43:13][D][sensor:094]: 'Rookmelder tuinhuis': Sending state 0.14700 V with 2 decimals of accuracy
[17:43:13][D][sensor:094]: 'Rookmelder tuinhuis': Sending state 0.14700 V with 2 decimals of accuracy
[17:43:13][D][sensor:094]: 'Rookmelder tuinhuis': Sending state 0.14700 V with 2 decimals of accuracy
[17:43:13][D][sensor:094]: 'Rookmelder tuinhuis': Sending state 0.15000 V with 2 decimals of accuracy

In all three cases, I had silent moments, and moments of continuing noise…

Hello! thanks for the code.
It works very well but i have a problem.
It sometimes/mostly misses short sounds, examble might a sneeze or cough. If i reduce the update interval to 1s, ESP doesn’t want to connect to wifi, since the code starts working before establishing connection, the device stays offline/unreachable.
Is it possible to edit the code so it only updates data if the numeric value of db changes? Could you help me with that?
Also i’m getting these warnings which i suppose i should ignore?

1