Microcontroller projects

Noise and Temperature Meter

last updated: 2023-07-04

Quick links

Introduction

My Victron Multiplus-II 48/8000/100 Inverter are quite noisy and they produce heat. This can be fixed, but to see the effect of the fixes I wanted to monitor the noise (sound).

So here is a quick and dirty project to do so.

Quick, because I can use my ESP Toolbox library. I took the MQTT example with supported temperature sensor as base. This example does the biggest part. It provides MQTT, WiFi, fix IP address, OTA and debugging via UDP.

Dirty because I use a breadboard.

noise meter

Hardware

I use a LOLIN/WEMOS D1 mini Pro (V2.0). This board has a Lithium battery interface, so we could use this battery if wanted. I had a microphone breakout board called sound detector from sparkfun in my tinkering box. This board is cool, because it has an envelope output, that helps without further components to acquire the noise level. For the temperature I use an BME280 breakout board (I²C).

When I tested the sound detector envelope output, I realised that it can not be used if we power it with the USB power supply. Neither does it work with the Lithium battery connected to the board. There is way too much noise, so we need an external battery. I took 4x1.5 V AA cells, with a diode in series to reduce the voltage to under 5.5 V.

The output level was not very high. This could be changed by removing R3 on the breakout board and adding a 1 MΩ potentiometer. I found that the level did not really get above 3 V (max of ESP8266 on analog input) with 1 MΩ, so I replaced the pot with a normal 1 MΩ resistor. I also de-soldered a solder-paste blob on the board to save the current of the onboard LED. Look for this in the Sparkfun Sound Detector Hookup Guide.

BOM

Circuit

circuit noise meter

Software

The code is on github https://github.com/weigu1/noise_temp_meter.

As stated before I used my ESPToolbox. More infos about this code on this page: https://www.weigu.lu/microcontroller/esptoolbox/index.html.

Here only the part of the code regarding the noise sampling. It is done in the main loop. The analogue value is read READ_SAMPLES times and the maximum of all these samples is saved to an array. With 1000 samples we need about 100 ms.

In the function calculate_noise() the average over the array is calculated, and the function calculate_noise_dB() calculates the value in dBA. As there is no real linearity between the noise value and the noise value in dBA, I take 3 map functions to get the approximated dBA value. For this I used a lent dBA-meter, and measured the ADC value and dBA value with a white noise signal at different levels. This calibration is necessary, because every microphone has a different sensitivity.

    /*
      noise_temp_meter.ino
      www.weigu.lu*/

    ... 

    long rand_number = 0;
    const unsigned int READ_SAMPLES = 1000;
    const unsigned int AVG_ARRAY_SAMPLES = 30; 
    unsigned int value = 0;
    unsigned int max_value = 0;
    unsigned int array_counter = 0;
    unsigned int avg_array[AVG_ARRAY_SAMPLES]; 

    ESPToolbox Tb;                                // Create an ESPToolbox Object

    /****** SETUP *************************************************************/

    void setup() {
      Tb.set_udp_log(true, UDP_LOG_PC_IP, UDP_LOG_PORT);
      Tb.set_led_log(true); // enable LED logging (pos logic)
      #ifdef STATIC
        Tb.set_static_ip(true,NET_LOCAL_IP, NET_GATEWAY, NET_MASK, NET_DNS);
      #endif // ifdef STATIC
      Tb.init_wifi_sta(WIFI_SSID, WIFI_PASSWORD, NET_MDNSNAME, NET_HOSTNAME);
      Tb.init_ntp_time();
      MQTT_Client.setBufferSize(MQTT_MAXIMUM_PACKET_SIZE);
      MQTT_Client.setServer(MQTT_SERVER,MQTT_PORT); //open connection MQTT server
      #ifdef OTA
        Tb.init_ota(OTA_NAME, OTA_PASS_HASH);
      #endif // ifdef OTA
      #ifdef BME280_I2C
        init_bme280();
      #endif // ifdef BME280_I2C
      randomSeed(analogRead(0));
      Tb.blink_led_x_times(3);
      Tb.log_ln("Setup done!");
    }

    /****** LOOP **************************************************************/

    void loop() {
      #ifdef OTA
        ArduinoOTA.handle();
      #endif // ifdef OTA
      if (Tb.non_blocking_delay(PUBLISH_TIME)) { // PUBLISH_TIME in config.h
        mqtt_get_temp_and_noise_and_publish();
        Tb.blink_led_x_times(3);
        delay(1000);
      }
      if (WiFi.status() != WL_CONNECTED) {   // if WiFi disconnected, reconnect
        Tb.init_wifi_sta(WIFI_SSID, WIFI_PASSWORD, NET_MDNSNAME, NET_HOSTNAME);
      }
      if (!MQTT_Client.connected()) {        // reconnect mqtt client, if needed
        mqtt_connect();
      }
      MQTT_Client.loop();                    // make the MQTT live
      // get noise  
      array_counter++;   
      if (array_counter == AVG_ARRAY_SAMPLES) {
        array_counter = 0;
      }  
      for (unsigned int i=0; i<READ_SAMPLES; i++) { // takes about 100ms with 1000 samples
        value = analogRead(A0);    
        if (value > max_value) {
          max_value = value;
        }    
      }
      avg_array[array_counter] = max_value;  
      max_value = 0; 
    }

    ...

    /********** NOISE functions *************************************************/
    unsigned int calculate_noise() {  
      unsigned long long avg_value = 0;
      for (unsigned int i=0; i<AVG_ARRAY_SAMPLES; i++) {    
        avg_value += avg_array[i];
        Tb.log(String(avg_array[i]) + "\t");
      }
      avg_value = avg_value/AVG_ARRAY_SAMPLES;
      Tb.log("\nADC: " + String(avg_value) + "\t");
      return avg_value;  
    }

    unsigned int calculate_noise_dB(unsigned int avg_value) {
      double value_db = 0;
      if (avg_value < 100) {
        value_db = map(avg_value,20,100,40,67); 
      }
      else if ((avg_value >= 100) && (avg_value <= 400)) {
        value_db = map(avg_value,100,400,67,82); 
      }
      else if (avg_value > 400) {
        value_db = map(avg_value,400,900,82,115); 
      }
      value_db = round(value_db*100)/100;  
      Tb.log_ln("  dB: " + String(value_db));
      return value_db;  
    }

OpenHAB

I used openhab to monitor the data that is sent via MQTT.

noise meter openhab

Here is the thing YAML file:.

    UID: mqtt:topic:udoo_mqtt_server:noise_temp_meter
    label: Noise Temperature Meter
    thingTypeUID: mqtt:topic
    configuration: {}
    bridgeUID: mqtt:broker:udoo_mqtt_server
    channels:
      - id: noise_meter_noise_adc
        channelTypeUID: mqtt:number
        label: Noise Meter Noise ADC
        description: null
        configuration:
          min: 0
          stateTopic: weigu/basement/storage/noise_temp
          transformationPattern: JSONPATH:$.noise_adc
          max: 1024
      - id: noise_meter_noise_db
        channelTypeUID: mqtt:number
        label: Noise Meter Noise dB
        description: null
        configuration:
          min: 0
          stateTopic: weigu/basement/storage/noise_temp
          transformationPattern: JSONPATH:$.noise_dB
          max: 150
      - id: noise_meter_temp
        channelTypeUID: mqtt:number
        label: Noise Meter Temperature
        description: null
        configuration:
          min: -20
          stateTopic: weigu/basement/storage/noise_temp
          transformationPattern: JSONPATH:$.temperature_C
          max: 100
      - id: noise_meter_hum
        channelTypeUID: mqtt:number
        label: Noise Meter Humidity
        description: null
        configuration:
          min: 0
          stateTopic: weigu/basement/storage/noise_temp
          transformationPattern: JSONPATH:$.humidity_%
          max: 100
      - id: noise_meter_press
        channelTypeUID: mqtt:number
        label: Noise Meter Pressure
        description: null
        configuration:
          min: 700
          stateTopic: weigu/basement/storage/noise_temp
          transformationPattern: JSONPATH:$.pressure_hPa
          max: 1200

Links

Downloads