Conversion of Adafruit Max4466 Analog Output to Decibels Produces Constant Value

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
      }
    
}
}

Hello

Unlike your first code, the second code never reset signalMax and signalMin

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.