Hello,
I am developing a pollution monitoring kit using an Arduino Uno. Before adding an Adafruit Max4466 to measure loudness, my kit had a KSeries K3O CO2 sensor, SPS30 PM Sensor, SHT31 temperature and humidity sensor, and Sparkfun SAM-M8Q GPS. The kit was outputting the previous sensor values as expected. I connected the Adafruit 4466 to the Analog 0 pin of a different Arduino Uno to test it, and I was able to achieve fairly accurate decibel readings after following this tutorial: https://www.youtube.com/watch?v=y5eSI1Pen7s
Below is the code I used to test the Max4466:
/****************************************
Example Sound Level Sketch for the
Adafruit Microphone Amplifier
****************************************/
const int sampleWindow = 50; // Sample window width in mS (50 mS = 20Hz)
unsigned int sample;
void setup()
{
Serial.begin(9600);
}
void loop()
{
unsigned long startMillis= millis(); // Start of sample window
unsigned int peakToPeak = 0; // peak-to-peak level
unsigned int signalMax = 0;
unsigned int signalMin = 1024;
// collect data for 50 mS
while (millis() - startMillis < sampleWindow)
{
sample = analogRead(0);
if (sample < 1024) // toss out spurious readings
{
if (sample > signalMax)
{
signalMax = sample; // save just the max levels
}
else if (sample < signalMin)
{
signalMin = sample; // save just the min levels
}
}
}
peakToPeak = signalMax - signalMin; // max - min = peak-peak amplitude
int db = map(peakToPeak, 20,900,49.5,90); // calibrate for decibels
Serial.println(db);
delay(200);
}
However, when I tried integrate the sensor into the code for the rest of my sensing kit, the Max4466 is outputting high values that end of converging to readings of 95db, even in a quiet room. I have the Max4466 connected to 5V on the Arduino Uno.
Below is the code I am using for the entire kit:
#include "kSeries.h" //include kSeries Library
#include <Wire.h>
#include "Adafruit_SHT31.h"
#include <sps30.h>
#include <Melopero_SAM_M8Q.h>
// constructor for Sparkfun SAM-M8Q GPS
Melopero_SAM_M8Q GPS;
// constructor for kSeries CO2 sensor //
kSeries K_30(12,13); //Initialize a kSeries Sensor with pin 12 as Rx and 13 as Tx
// constructor for SHT31 temperature sensor //
// temp & humidity sensor (uses I2C communication)
// yellow = SCL; white = SDA
Adafruit_SHT31 sht31 = Adafruit_SHT31();
// heater for SHT31 sensor //
bool enableHeater = false;
// initializing SPS30 PM sensor //
uint8_t loopCnt = 0;
int16_t ret;
uint8_t auto_clean_days = 4;
uint32_t auto_clean;
// Sampling Rate Timing Constants
const unsigned long SEND_INTERVAL_MS = 1000;
// const unsigned long SEND_INTERVAL_MS = 10000;
// const unsigned long SEND_INTERVAL_MS = 20000;
const size_t READ_BUF_SIZE = 64;
// constants for Max4466 Microphone
const int sampleWindow = 50; // Sample window width in mS (50 mS = 20Hz)
double inputV = 5.0; // input voltage (5V)
unsigned int peakToPeak = 0; // peak-to-peak level
unsigned int signalMax = 0;
unsigned int signalMin = 1024;
// Forward declarations //
void calcCO2();
void calcTempHum();
void calcPM();
void gpsRead();
void calcNoise();
// Global Variables //
float co2 = 0;
float temp = 0;
float tempAdjust = 2;
float hum = 0;
float pm2_5 = 0;
unsigned int sample;
// Microphone
unsigned long startMillis;
float db = 0;
// gps
float latitude = 0;
float longitude = 0;
//timing
unsigned long lastSend = 0;
unsigned long lastTime = 0;
char gps_read; // gps read
void setup() {
// Serial TX (1) is connected to Photon RX
// Serial RX (0) is connected to Photon TX
// Ardiuno GND is connected to Photon GND
Serial.begin(9600);
Serial.println("Beginning setup for test");
Wire.begin();
// SAM-M8Q initialization
GPS.initI2C();
Status stat = GPS.setCommunicationToUbxOnly();
// set the PVT to be sent 10 times a second:
// setMeasurementFrequency(measurementPeriod, measurementspersolution)
// with these settings we will have a measurement every 50 milliseconds
// and a navigation solution every 2 measurements which means every 100
// milliseconds.
stat = GPS.setMeasurementFrequency(50, 2);
// set the pvt message send rate:
// in this way the message will be sent every navigation solution
stat = GPS.setMessageSendRate(NAV_CLASS, NAV_PVT, 1);
delay(2000);
//Serial.println("Got past 2000 delay");
// initialize PM sensor
sensirion_i2c_init();
pinMode(8, OUTPUT);
if (! sht31.begin(0x44)) { // Set to 0x45 for alternate i2c addr
Serial.println("Couldn't find SHT31");
while (1) delay(1);
}
// Serial.println("Got past SHT31 search");
Serial.print("Heater Enabled State: ");
if (sht31.isHeaterEnabled())
Serial.println("ENABLED");
else
Serial.println("DISABLED");
// sps code
while (sps30_probe() != 0) {
Serial.print("SPS sensor probing failed\n");
delay(500);
}
#ifndef PLOTTER_FORMAT
Serial.print("SPS sensor probing successful\n");
#endif /* PLOTTER_FORMAT */
ret = sps30_set_fan_auto_cleaning_interval_days(auto_clean_days);
if (ret) {
Serial.print("error setting the auto-clean interval: ");
Serial.println(ret);
}
ret = sps30_start_measurement();
if (ret < 0) {
Serial.print("error starting measurement\n");
}
#ifndef PLOTTER_FORMAT
Serial.print("measurements started\n");
#endif /* PLOTTER_FORMAT */
// Serial.println("Got past SPS30 setup");
delay(10000); // warmup period
}
void loop() {
Serial.println(db);
if (millis() - lastSend >= SEND_INTERVAL_MS) {
lastSend = millis();
calcCO2();
calcTempHum();
calcPM();
calcNoise();
gpsRead();
// send data to Particle Electron via serial
Serial.print("<");
Serial.print(co2, 3);
Serial.print(", ");
Serial.print(temp, 2);
Serial.print(", ");
Serial.print(hum, 2);
Serial.print(", ");
Serial.print(pm2_5, 3);
Serial.print(", ");
Serial.print(latitude, 5);
Serial.print(", ");
Serial.print(longitude, 5);
// Serial.println(">");
Serial.print(",");
Serial.print(db, 2);
Serial.println(">");
}
}
void calcCO2(){
co2 = K_30.getCO2('p'); //returns co2 value in ppm ('p') or percent ('%')
if(co2 < 0){
co2 = 0;
}
}
void calcTempHum(){
// get temp & humidity
temp = sht31.readTemperature();
// temp = temp - tempAdjust;
hum = sht31.readHumidity();
}
void calcPM(){
struct sps30_measurement m;
char serial[SPS30_MAX_SERIAL_LEN];
uint16_t data_ready;
int16_t ret;
do {
ret = sps30_read_data_ready(&data_ready);
if (ret < 0) {
//Serial.print("error reading data-ready flag: ");
//Serial.println(ret);
} else if (!data_ready) {
}
//Serial.print("data not ready, no new measurement available\n");
else
break;
delay(100); /* retry in 100ms */
} while (1);
ret = sps30_read_measurement(&m);
if (ret < 0) {
//Serial.print("error reading measurement\n");
} else {
pm2_5 = m.mc_2p5;
}
}
void calcNoise(){
startMillis= millis(); // Start of db sample window
// collect data for 50 mS
while (millis() - startMillis < sampleWindow)
{
sample = analogRead(0);
if (sample > signalMax)
{
signalMax = sample; // save just the max levels
}
else if (sample < signalMin)
{
signalMin = sample; // save just the min levels
}
}
peakToPeak = signalMax - signalMin; // max - min = peak-peak amplitude
db = map(peakToPeak, 20.0,900.0,49.5,90.0); // calibrate for decibels
}
void gpsRead() {
Status stat = GPS.updatePVT();
if (stat == Status::NoError){
if (GPS.pvtData.fixType != NO_FIX){
longitude = GPS.pvtData.longitude / (double)10000000; // degrees
latitude = GPS.pvtData.latitude / (double)10000000; // degrees
}
}
}