last updated: 2023-07-04
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.
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.
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;
}
I used openhab to monitor the data that is sent via MQTT.
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