Hello everyone, I am using esp32 wroom 32D and max9814 the wiring is as follows
ESP32 3.3v --> Breadboard positive rail
Esp32 GND --> Breadboard negative rail
ESP32 D35 --> MAX9814 OUT
MAX9814 VDD --> Breadboard positive rail
MAX9814 GND -> Breadboard negative rail
The issue is that i have wrong reading using the following code:
#include <WiFi.h>
#include <ESPAsyncWebServer.h>
#include <ArduinoJson.h>
#include <arduinoFFT.h>
// Wi-Fi credentials
const char* ssid = "Monitor Sound";
const char* password = "12345678";
AsyncWebServer server(80);
AsyncWebSocket ws("/ws");
// Sampling and FFT configuration
const int sampleRate = 512; // Number of samples
const double samplingFrequency = 20000; // Sampling frequency (20 kHz)
unsigned long samplingInterval; // Microseconds per sample
double vReal[sampleRate];
double vImag[sampleRate];
ArduinoFFT FFT = ArduinoFFT(vReal, vImag, sampleRate, samplingFrequency);
// Microphone calibration (example values)
const double micSensitivity = -42; // Sensitivity in V/Pa
const double referencePressure = 20e-6; // Reference pressure in Pascals
// HTML page for WebSocket visualization
String htmlPage = R"rawliteral(
<!DOCTYPE html>
<html>
<head>
<title>Sound Amplitude Graph</title>
<script>
let socket;
let amplitude = 0, spl = 0, rt60 = 0, frequency = 0;
function initWebSocket() {
socket = new WebSocket(ws://${location.hostname}/ws);
socket.onmessage = function (event) {
const data = JSON.parse(event.data);
amplitude = data.amplitude;
spl = data.spl;
rt60 = data.rt60;
frequency = data.frequency;
document.getElementById("amplitude").innerText = amplitude.toFixed(2);
document.getElementById("spl").innerText = spl.toFixed(2);
document.getElementById("rt60").innerText = rt60.toFixed(2);
document.getElementById("frequency").innerText = frequency.toFixed(2);
updateGraph(amplitude);
};
}
let graphData = [];
function updateGraph(newValue) {
const canvas = document.getElementById("graph");
const ctx = canvas.getContext("2d");
const maxAmplitude = 50000; // Adjust this based on expected input
const normalizedValue = Math.min(canvas.height, canvas.height * (newValue / maxAmplitude));
graphData.push(normalizedValue);
if (graphData.length > canvas.width) {
graphData.shift();
}
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.beginPath();
ctx.moveTo(0, canvas.height - graphData[0]);
graphData.forEach((val, index) => {
ctx.lineTo(index, canvas.height - val);
});
ctx.stroke();
}
window.onload = function () {
initWebSocket();
};
</script>
</head>
<body>
<h1>Sound Amplitude Graph</h1>
<p>Amplitude: <span id="amplitude">0</span></p>
<p>SPL: <span id="spl">0</span> dB</p>
<p>RT60: <span id="rt60">0</span> seconds</p>
<p>Frequency: <span id="frequency">0</span> Hz</p>
<canvas id="graph" width="500" height="300" style="border: 1px solid black;"></canvas>
</body>
</html>
)rawliteral";
void processFFT() {
unsigned long currentTime = micros(); // Start timing for sampling
samplingInterval = 1e6 / samplingFrequency; // Calculate interval (microseconds per sample)
// Read analog samples precisely
for (int i = 0; i < sampleRate; i++) {
vReal[i] = analogRead(35); // Read analog input
vImag[i] = 0;
while (micros() - currentTime < samplingInterval) {
// Wait for the correct sampling interval
}
currentTime += samplingInterval;
}
// Apply FFT
FFT.windowing(FFT_WIN_TYP_HAMMING, FFT_FORWARD);
FFT.compute(FFT_FORWARD);
FFT.complexToMagnitude();
// Find the dominant frequency bin
double maxAmplitude = 0;
int maxIndex = 0;
for (int i = 2; i < sampleRate / 2; i++) { // Ignore DC and low frequencies
if (vReal[i] > maxAmplitude) {
maxAmplitude = vReal[i];
maxIndex = i;
}
}
// Refine frequency estimation
double leftBin = vReal[maxIndex - 1];
double centerBin = vReal[maxIndex];
double rightBin = vReal[maxIndex + 1];
double interpolation = (rightBin - leftBin) / (2 * (2 * centerBin - leftBin - rightBin));
double refinedIndex = maxIndex + interpolation;
double dominantFrequency = (refinedIndex * samplingFrequency) / sampleRate;
// Convert ADC value to voltage
double amplitudeVoltage = maxAmplitude * (3.3 / 4095.0); // Convert ADC value to voltage (12-bit ADC)
// Convert the microphone's sensitivity from dBV/Pa to linear scale (V/Pa)
double sensitivityLinear = pow(10, -42 / 20.0); // Sensitivity in V/Pa for -42 dBV/Pa
// Compute sound pressure (Pa) from voltage using microphone sensitivity
double soundPressure = amplitudeVoltage / sensitivityLinear;
// Reference sound pressure is 20 μPa (0.00002 Pa)
double referencePressure = 20e-6;
// SPL Calculation
double spl = 20 * log10(soundPressure / referencePressure); // Calculate SPL in dB
// Debugging data for Serial Monitor
Serial.print("Frequency: ");
Serial.print(dominantFrequency, 2);
Serial.print(" Hz, SPL: ");
Serial.print(spl, 2);
Serial.print(" dB, Amplitude: ");
Serial.println(maxAmplitude);
// Send data via WebSocket
StaticJsonDocument<200> jsonDoc;
jsonDoc["amplitude"] = maxAmplitude;
jsonDoc["spl"] = spl;
jsonDoc["frequency"] = dominantFrequency;
String jsonString;
serializeJson(jsonDoc, jsonString);
ws.textAll(jsonString);
}
void onWebSocketEvent(AsyncWebSocket *server, AsyncWebSocketClient *client,
AwsEventType type, void *arg, uint8_t *data, size_t len) {
if (type == WS_EVT_CONNECT) {
Serial.printf("Client connected: %u\n", client->id());
} else if (type == WS_EVT_DISCONNECT) {
Serial.printf("Client disconnected: %u\n", client->id());
}
}
void setup() {
Serial.begin(115200);
// Start Wi-Fi Access Point
WiFi.softAP(ssid, password);
IPAddress IP = WiFi.softAPIP();
Serial.print("Access Point started. IP address: ");
Serial.println(IP);
ws.onEvent(onWebSocketEvent);
server.addHandler(&ws);
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request) {
request->send_P(200, "text/html", htmlPage.c_str());
});
server.on("/favicon.ico", HTTP_GET, [](AsyncWebServerRequest *request) {
request->send(404);
});
server.begin();
Serial.println("Server started.");
}
void loop() {
processFFT(); // Run FFT processing
delay(1000); // Adjust update interval as needed
}
The frequency is nearly accuarate (440HZ outputs 437.sth) but the SPL and RT60 are majorly wrong because the SPL for instance outputs 130+ in a queit room with 35 dB.
Can anyone help with this issue ?
