esp32loudness/src/main.cpp

248 lines
6.5 KiB
C++

#include <Arduino.h>
#include <WiFi.h>
#include <WiFiMulti.h>
#include <HTTPClient.h>
#include <AutoAnalogAudio.h>
#include <ArduinoOTA.h>
#include <SPIFFS.h>
#include "Config.h"
#include "fft_config.h"
//#include "httpserver.h"
extern "C" {
#include "fft.h"
}
#define ENDLESS_LOOP() while(true) { delay(100); }
#define OUTPUT_INTERVAL 10000 // milliseconds
#define SAMPLES_PER_BLOCK 512
static WiFiMulti wiFiMulti;
static bool wiFiConnectedToStation;
static AutoAnalog recorder;
// too large for the stack
static value_type timedomain[SAMPLES_PER_BLOCK];
static value_type fft_re[BLOCK_LEN], fft_im[BLOCK_LEN], fft_abs[BLOCK_LEN];
void wifi_setup(void)
{
// Connect the WiFi network (or start an AP if that doesn't work)
for (auto &net : Config::instance().getWLANList())
{
Serial.print(F("Adding network "));
Serial.println(net.ssid.c_str());
wiFiMulti.addAP(net.ssid.c_str(), net.password.c_str());
}
Serial.println(F("Trying to connect for 5 Minutes..."));
WiFi.setHostname("loudness");
WiFi.mode(WIFI_STA);
//WiFi.setSleepMode(WIFI_MODEM_SLEEP);
wiFiConnectedToStation = true; // assume the best
bool led_on = true;
for(size_t tries = 0; tries < 3000; tries++)
{
if(wiFiMulti.run() == WL_CONNECTED) {
Serial.println(F(""));
Serial.println(F("WiFi connected"));
Serial.println(F("IP address: "));
Serial.println(WiFi.localIP());
break;
}
led_on = !led_on;
digitalWrite(LED_BUILTIN, led_on);
delay(100);
Serial.print(F("."));
}
if(WiFi.status() != WL_CONNECTED) {
Serial.println(F("Connection failed, setting up access point..."));
wiFiConnectedToStation = false;
IPAddress apIP(192, 168, 42, 1);
WiFi.mode(WIFI_AP);
WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0));
WiFi.softAP("loudness", "dB(A)");
WiFi.enableAP(true);
digitalWrite(LED_BUILTIN, false); // LED ON (active low)
} else {
digitalWrite(LED_BUILTIN, true); // LED OFF (active low)
}
}
void setup()
{
Serial.begin(115300);
pinMode(LED_BUILTIN, OUTPUT);
Serial.println(F("Hello World!"));
Serial.println(F("Initializing LittleFS…"));
if(!SPIFFS.begin()) {
Serial.println(F("LittleFS setup failed!"));
ENDLESS_LOOP();
}
Config::instance().load();
Serial.println(F("Initializing WiFi…"));
wifi_setup();
//Serial.println(F("Initializing HTTP Server…"));
//httpserver_setup();
//Serial.println(F("Testing display…"));
//epaper_test();
Serial.println(F("Initialization routine complete."));
init_fft();
// start sampling
recorder.enableAdcChannel(6);
recorder.begin(true, false);
recorder.autoAdjust = 0; //Disable auto adjust of timers
recorder.adcBitsPerSample = 12;
recorder.setSampleRate(48000, false);
recorder.getADC(SAMPLES_PER_BLOCK);
}
void loop() {
static uint32_t last_output_time = 0;
static uint32_t nsamples = 0;
static value_type total_energy_0_to_300_hz = 0.0f;
static value_type total_energy_300_to_3500_hz = 0.0f;
static value_type total_energy_3500_to_8000_hz = 0.0f;
static value_type total_energy_8000_to_20000_hz = 0.0f;
wiFiMulti.run(); // maintain the WiFi connection
recorder.getADC(SAMPLES_PER_BLOCK);
// convert to Volt (float)
for(size_t i = 0; i < SAMPLES_PER_BLOCK; i++) {
timedomain[i] = (value_type)recorder.adcBuffer16[i] / 4096.0f * 3.30f;
}
// calculate average value
value_type avg = 0;
for(size_t i = 0; i < SAMPLES_PER_BLOCK; i++) {
avg += timedomain[i];
}
avg /= SAMPLES_PER_BLOCK;
// and remove it from the data
for(size_t i = 0; i < SAMPLES_PER_BLOCK; i++) {
timedomain[i] -= avg;
}
apply_hanning(timedomain);
fft_transform(timedomain, fft_re, fft_im);
complex_to_absolute(fft_re, fft_im, fft_abs);
value_type energy_0_to_300_hz = get_energy_density_in_band(fft_abs, 0, 300);
value_type energy_300_to_3500_hz = get_energy_density_in_band(fft_abs, 300, 3500);
value_type energy_3500_to_8000_hz = get_energy_density_in_band(fft_abs, 3500, 8000);
value_type energy_8000_to_20000_hz = get_energy_density_in_band(fft_abs, 8000, 20000);
total_energy_0_to_300_hz += energy_0_to_300_hz;
total_energy_300_to_3500_hz += energy_300_to_3500_hz;
total_energy_3500_to_8000_hz += energy_3500_to_8000_hz;
total_energy_8000_to_20000_hz += energy_8000_to_20000_hz;
nsamples++;
uint32_t now = millis();
if(now - last_output_time > OUTPUT_INTERVAL) {
total_energy_0_to_300_hz /= nsamples;
total_energy_300_to_3500_hz /= nsamples;
total_energy_3500_to_8000_hz /= nsamples;
total_energy_8000_to_20000_hz /= nsamples;
// calculate dBV
value_type dBV_per_Hz_0_to_300_hz = 20*log10(total_energy_0_to_300_hz);
value_type dBV_per_Hz_300_to_3500_hz = 20*log10(total_energy_300_to_3500_hz);
value_type dBV_per_Hz_3500_to_8000_hz = 20*log10(total_energy_3500_to_8000_hz);
value_type dBV_per_Hz_8000_to_20000_hz = 20*log10(total_energy_8000_to_20000_hz);
Serial.print(" 0 - 300 Hz [dBV/Hz]: ");
Serial.println(dBV_per_Hz_0_to_300_hz);
Serial.print(" 300 - 3500 Hz [dBV/Hz]: ");
Serial.println(dBV_per_Hz_300_to_3500_hz);
Serial.print(" 3500 - 8000 Hz [dBV/Hz]: ");
Serial.println(dBV_per_Hz_3500_to_8000_hz);
Serial.print(" 8000 - 20000 Hz [dBV/Hz]: ");
Serial.println(dBV_per_Hz_8000_to_20000_hz);
Serial.println();
// encode the data into JSON
String json_string = "{"
"\"0_to_300_hz\":" + String(dBV_per_Hz_0_to_300_hz, 2) + ","
"\"300_to_3500_hz\":" + String(dBV_per_Hz_300_to_3500_hz, 2) + ","
"\"3500_to_8000_hz\":" + String(dBV_per_Hz_3500_to_8000_hz, 2) + ","
"\"8000_to_20000_hz\":" + String(dBV_per_Hz_8000_to_20000_hz, 2) + "}";
// send the data to graphite
HTTPClient client;
client.begin("http://stats.tkolb.de/sensor/loudness.php");
client.addHeader("Content-Type", "application/json");
int httpResponseCode = client.POST(json_string);
if(httpResponseCode>0) {
Serial.print("HTTP request result: ");
Serial.println(httpResponseCode); //Print return code
//String response = http.getString(); //Get the response to the request
//Serial.println(response); //Print request answer
} else {
Serial.print("Error on sending POST: ");
Serial.println(httpResponseCode);
}
// reset accumulation
total_energy_0_to_300_hz = 0.0f;
total_energy_300_to_3500_hz = 0.0f;
total_energy_3500_to_8000_hz = 0.0f;
total_energy_8000_to_20000_hz = 0.0f;
nsamples = 0;
last_output_time = now;
}
//Serial.println(analogRead(A6));
/*unsigned long now = millis();
if((now - displayLastUpdateTime) >= DISPLAY_UPDATE_INTERVAL) {
Serial.println(F("Sending HTTP request…"));
displayLastUpdateTime = now;
}*/
}