Microphone with software adjustable sensitivity

So I've just set up the basic AnalogReadSerial sketch taken reading to find the noise floor of the room without any music playing and im getting readings off the envelope pin with values between 54 and 56.

When I turn the music on to a pleasant level, with the sensor about ~3 meters/yards away the readings are unchanged.

My full code, if you wanted that.

Master.ino (10.0 KB)

Have you tried either of the other outputs? Maybe it helps to monitor the audio output instead of envelope. You'd have to sample the signal a couple of times to get a reliable reading. I can't see your sketch as I'm on my phone (it's better to post the code using code tags), but another possible issue is too infrequent sampling resulting in missed peaks.

I've got similar sort of results measuring from the Audio Pin, the noise floor and when music is playing I'm getting values between 480 and 570

When I put the speaker right up to the sensor I'm getting values between 200 and 800

The code.

#include "FastLED.h"

#define NUM_LEDS 240
#define LED_PIN 2
#define COLOR_ORDER GRB
#define LED_TYPE WS2811
#define LED_BRIGHTNESS = 25;

CRGB leds[NUM_LEDS];

const int  ForwardButton = 5;
const int  BackwardsButton = 6;
const int  ModeButton = 7;

int count = 0;   // counter for the number of button presses
int forwardbuttonState = 0;         // current state of the button
int forwardlastButtonState = 0;     // previous state of the button
int backbuttonState = 0;         // current state of the button
int backlastButtonState = 0;     // previous state of the button
int modebuttonState = 0;         // current state of the button
int modelastButtonState = 0;     // previous state of the button

int numAudioReadings = 200;
int audioReadings[200];
int numEnvelopeReadings = 200;
int envelopeReadings[200];
int audioIndex = 0;
int envelopeIndex = 0;

int audioSensorMax = 0;
int audioSensorMin = 0;
int envelopeSensorMax = 0;
int envelopeSensorMin = 0;
int mode = 0;



void setup() {
  Serial.begin(9600);
  FastLED.addLeds <WS2811, LED_PIN, COLOR_ORDER> (leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
  pinMode(ForwardButton, INPUT);
  pinMode(BackwardsButton, INPUT);
  pinMode(ModeButton, INPUT);


  audioSensorMax = analogRead(A1);
  audioSensorMin = audioSensorMax;
  envelopeSensorMax = analogRead(A0);
  envelopeSensorMin = envelopeSensorMax;


  mode = 1;
}

void loop() {

  modebuttonState = digitalRead(ModeButton);
  if (modebuttonState != modelastButtonState) {
    if (modebuttonState == HIGH) {


      if (mode < 3) {
        mode++;

      }
      else
        mode = 1;

      delay(50);
    }
    // save the current state as the last state, for next time through the loop
    modelastButtonState = modebuttonState;
  }



  switch (mode) {
    case 1:

      Off();
      break;

    case 2:

      Multi();
      break;

    case 3:

      Beat();
      break;

  }
}

/*
 * ********************************************************************************
                                      START OFF MODE
 * ********************************************************************************
*/


void Off() {
  Serial.println("OFF");
  CRGB::Black;
  FastLED.setBrightness(0);
  FastLED.show();
}


/*
 * ********************************************************************************
                                      MULTI MODE
 * ********************************************************************************
*/


void Multi() {
  delay(200);
  Serial.println("Multi");

  const CRGB ColourValue;

  int audiovalue = analogRead(A1);
  int envelopevalue = analogRead(A0);
  Serial.println(audiovalue);

  audioReadings[audioIndex] = audiovalue;
  audioIndex++;
  if (audioIndex >= numAudioReadings) audioIndex = 0;

  if (audiovalue > audioSensorMax) audioSensorMax = audiovalue;
  if (audiovalue < audioSensorMin) audioSensorMin = audiovalue;

  envelopeReadings[envelopeIndex] = envelopevalue;
  envelopeIndex++;
  if (envelopeIndex >= numEnvelopeReadings) envelopeIndex = 0;

  if (envelopevalue > envelopeSensorMax) envelopeSensorMax = envelopevalue;
  if (envelopevalue < envelopeSensorMin) envelopeSensorMin = envelopevalue;

  float total = 0;
  for (int i = 0; i < numAudioReadings; i++) total += audioReadings[i];
  float average = total / numAudioReadings;

  if (envelopevalue > (envelopeSensorMin + 10))
  {
    envelopevalue = map(envelopevalue, envelopeSensorMin, envelopeSensorMax, 75, 255);
  }


  if (audioIndex >= 199) {
    if (audiovalue >= 520) {
      audioSensorMax = audiovalue;
    }
  }

    float threashold = (audioSensorMax - average) / 7;

    if (audiovalue >= 500); {
      if (audiovalue > average + threashold * 1 && audiovalue <= average + threashold * 2) {
        Serial.println("Yellow");
        ColourValue = CRGB::Yellow;

      } else if (audiovalue > average + threashold * 2 && audiovalue <= average + threashold * 3) {
        Serial.println("Green");
        ColourValue = CRGB::Orange;

      } else if (audiovalue > average + threashold * 3 && audiovalue <= average + threashold * 4) {
        Serial.println("Blue");
        ColourValue = CRGB::Red;

      } else if (audiovalue > average + threashold * 4 && audiovalue <= average + threashold * 5) {
        Serial.println("Violet");
        ColourValue = CRGB::Purple;

      } else if (audiovalue > average + threashold * 5 && audiovalue <= average + threashold * 6) {
        Serial.println("Red");
        ColourValue = CRGB::Violet;

      } else if (audiovalue > average + threashold * 6 && audiovalue <= average + threashold * 7) {
        Serial.println("Orange");
        ColourValue = CRGB::Blue;

      } else if (audiovalue > average + threashold * 7) {
        Serial.println("White");
        ColourValue = CRGB::Cyan;

      }

    for (int i = 0; i < NUM_LEDS; i++)
      leds[i] = ColourValue;
    FastLED.setBrightness(envelopevalue);
    FastLED.show();
  }
  ColourValue = CRGB::Green;
}


/*
 * ********************************************************************************
                                      BEAT MODE
 * ********************************************************************************
*/


void Beat() {
  delay(200);
  Serial.println("Beat");
  int envelopevalue = analogRead(A0);
  Serial.println(A0);

  envelopeReadings[envelopeIndex] = envelopevalue;
  envelopeIndex++;
  if (envelopeIndex >= numEnvelopeReadings) envelopeIndex = 0;

  if (envelopevalue > envelopeSensorMax) envelopeSensorMax = envelopevalue;
  if (envelopevalue < envelopeSensorMin) envelopeSensorMin = envelopevalue;

  if (envelopevalue > (envelopeSensorMin))
  {
    envelopevalue = map(envelopevalue, envelopeSensorMin, envelopeSensorMax, 0, 255);
  } else envelopevalue = 0;


  forwardbuttonState = digitalRead(ForwardButton);
  if (forwardbuttonState != forwardlastButtonState) {
    if (forwardbuttonState == HIGH) {
      if ( count >= 141) {
        count = -1;
      }
      count++;
      //Serial.println(count);
    }

    delay(50);
  }
  // save the current state as the last state, for next time through the loop
  forwardlastButtonState = forwardbuttonState;


  backbuttonState = digitalRead(BackwardsButton);
  if (backbuttonState != backlastButtonState) {
    if (backbuttonState == HIGH) {


      if (count < 1) {
        count = 142;
      }

      count--;
      //Serial.println(count);
    }

    delay(50);
  }
  // save the current state as the last state, for next time through the loop
  backlastButtonState = backbuttonState;





  const CRGB EnumColors[] = {
    CRGB::Aqua,
    CRGB::Aquamarine,
    CRGB::Azure,
    CRGB::Beige,
    CRGB::Bisque,
    CRGB::BlanchedAlmond,
    CRGB::Blue,
    CRGB::BlueViolet,
    CRGB::Brown,
    CRGB::BurlyWood,
    CRGB::CadetBlue,
    CRGB::Chartreuse,
    CRGB::Chocolate,
    CRGB::Coral,
    CRGB::CornflowerBlue,
    CRGB::Cornsilk,
    CRGB::Crimson,
    CRGB::Cyan,
    CRGB::DarkBlue,
    CRGB::DarkCyan,
    CRGB::DarkGoldenrod,
    CRGB::DarkGray,
    CRGB::DarkGreen,
    CRGB::DarkKhaki,
    CRGB::DarkMagenta,
    CRGB::DarkOliveGreen,
    CRGB::DarkOrange,
    CRGB::DarkOrchid,
    CRGB::DarkRed,
    CRGB::DarkSalmon,
    CRGB::DarkSeaGreen,
    CRGB::DarkSlateBlue,
    CRGB::DarkSlateGray,
    CRGB::DarkTurquoise,
    CRGB::DarkViolet,
    CRGB::DeepPink,
    CRGB::DeepSkyBlue,
    CRGB::DimGray,
    CRGB::DodgerBlue,
    CRGB::FireBrick,
    CRGB::FloralWhite,
    CRGB::ForestGreen,
    CRGB::Fuchsia,
    CRGB::Gainsboro,
    CRGB::GhostWhite,
    CRGB::Gold,
    CRGB::Goldenrod,
    CRGB::Gray,
    CRGB::Green,
    CRGB::GreenYellow,
    CRGB::Honeydew,
    CRGB::HotPink,
    CRGB::IndianRed,
    CRGB::Indigo,
    CRGB::Ivory,
    CRGB::Khaki,
    CRGB::Lavender,
    CRGB::LavenderBlush,
    CRGB::LawnGreen,
    CRGB::LemonChiffon,
    CRGB::LightBlue,
    CRGB::LightCoral,
    CRGB::LightCyan,
    CRGB::LightGoldenrodYellow,
    CRGB::LightGreen,
    CRGB::LightGrey,
    CRGB::LightPink,
    CRGB::LightSalmon,
    CRGB::LightSeaGreen,
    CRGB::LightSkyBlue,
    CRGB::LightSlateGray,
    CRGB::LightSteelBlue,
    CRGB::LightYellow,
    CRGB::Lime,
    CRGB::LimeGreen,
    CRGB::Linen,
    CRGB::Magenta,
    CRGB::Maroon,
    CRGB::MediumAquamarine,
    CRGB::MediumBlue,
    CRGB::MediumOrchid,
    CRGB::MediumPurple,
    CRGB::MediumSeaGreen,
    CRGB::MediumSlateBlue,
    CRGB::MediumSpringGreen,
    CRGB::MediumTurquoise,
    CRGB::MediumVioletRed,
    CRGB::MidnightBlue,
    CRGB::MintCream,
    CRGB::MistyRose,
    CRGB::Moccasin,
    CRGB::NavajoWhite,
    CRGB::Navy,
    CRGB::OldLace,
    CRGB::Olive,
    CRGB::OliveDrab,
    CRGB::Orange,
    CRGB::OrangeRed,
    CRGB::Orchid,
    CRGB::PaleGoldenrod,
    CRGB::PaleGreen,
    CRGB::PaleTurquoise,
    CRGB::PaleVioletRed,
    CRGB::PapayaWhip,
    CRGB::PeachPuff,
    CRGB::Peru,
    CRGB::Pink,
    CRGB::Plaid,
    CRGB::Plum,
    CRGB::PowderBlue,
    CRGB::Purple,
    CRGB::Red,
    CRGB::RosyBrown,
    CRGB::RoyalBlue,
    CRGB::SaddleBrown,
    CRGB::Salmon,
    CRGB::SandyBrown,
    CRGB::SeaGreen,
    CRGB::Seashell,
    CRGB::Sienna,
    CRGB::Silver,
    CRGB::SkyBlue,
    CRGB::SlateBlue,
    CRGB::SlateGray,
    CRGB::Snow,
    CRGB::SpringGreen,
    CRGB::SteelBlue,
    CRGB::Tan,
    CRGB::Teal,
    CRGB::Thistle,
    CRGB::Tomato,
    CRGB::Turquoise,
    CRGB::Violet,
    CRGB::Wheat,
    CRGB::WhiteSmoke,
    CRGB::Yellow,
    CRGB::YellowGreen,
    CRGB::Black,
    CRGB::White,
    CRGB::AliceBlue,
    CRGB::Amethyst,
    CRGB::AntiqueWhite,
  };

  const size_t NumbColors = sizeof(EnumColors) / sizeof(EnumColors[0]);

  for (int i = 0; i < NUM_LEDS; i++) {
    leds[i] = EnumColors[count];

  }

  //  Serial.println(EnumColors);
  FastLED.setBrightness(envelopevalue);
  FastLED.show();


}

I'd start by getting rid of those delays in beat() and multi() and rethink your sampling strategy. The delays limit your sampling frequency to 5Hz, which means you can very easily miss peaks. This is exacerbated by the fact that in both multi() and beat() you seem to average out 200 readings for certain parts of your code, and in multi() you have hardcoded the peak value instead of determining it dynamically (i.e. relative to the noise floor/average). I haven't analyzed your code in detail but at first glance I'd say you're more likely struggling with a software issue than problems with the hardware gain of your sensor module.

I'd start by getting rid of those delays in beat() and multi()

Fair point the on in beat() is not necessary. However, the one in multi() is there otherwise the colour changes are so rapid to the point that it's almost seizure-inducing. I want the LED's to remain on for 200ms before changing again.

both multi() and beat() you seem to average out 200 readings for certain parts of your code,

I've done this so that as the music changes through the song the colour thresholds remain appropriate ie, as a song decreases in volume/frequency the change in brightness and colour represents that.

in multi() you have hardcoded the peak value instead of determining it dynamically (i.e. relative to the noise floor/average).

The intent for that was to reduce the number of false activations from the LEDs when no music is playing. I'll have another look at this.

So use a non-blocking 'delay' using millis(). Don't make the color changes timing-dependent on your audio sampling!

Yeah, I see your point. Just make sure your peak detection doesn't somehow get lost in the averaging of readings. I don't think that's the case presently, but as said, I only took a cursory glance at your code.

Yes, I get the point, but this is exactly where your problem lies. You're making yourself dependent on an absolute peak reading whereas your application calls for a peak determination that is relative to the average or noise floor. So you'll have to modify your approach in this respect.

I can't write the test code because I'm not currently in a place to use the IDE, but I feel that the only LED change should be delayed and the sampling itself should continue to be fast.

Seems very unlikely indeed - you want low-noise circuitry for a microphone.
1k to 10k range is typically used.

A 1M resistor in the signal path is a recipe for unwanted Johnson noise.

Sure, but this is mostly about peak detection, so a bit of noise isn't necessarily a problem. Besides, we've established by now the problem is likely at least partly in the software and not so much the hardware.

I'm starting to think that somehow I must have damaged the spark fun sensor, as I've swapped it out for a DF Robot analog sound sensor and its performance is much better in comparison.

So I'm going to order a replacement SparkFun sensor, as it has the outputs I need [audio and envelope]

This is the completed project.
Any feedback would be appreciated.

Components

  • AD5242BRZ1M
  • SparkFun Sound Detector
  • 16v 1000uF Capacitor

/*
  Pot Pin 2 = Wiper A Terminal
  Pot Pin 3 = Wiper
  Pot Pin 4 = B Terminal
  Pot Pin 5 = Voltage in 5v
  Pot Pin 6 = Shutdown Not used wire to Pin 5
  Pot Pin 7 = SCL - Wire to A5
  Pot Pin 8 = SDA - Wire to A4
  Pot Pin 9 = A0 - Wire to GND
  Pot Pin 11 = DGND - Wire to GND



*/


int SoundVal;
unsigned long previousMillis = 0;


#include <Wire.h>


void setup()
{
  Wire.begin(); // join i2c bus (address optional for master)
  Serial.begin(9600);

}


byte val = 128;

void loop()
{

  unsigned long currentMillis = millis();
  int   SoundVal = analogRead(A0);

  if (currentMillis - previousMillis >= 5000) {

    Wire.beginTransmission(44);
    Wire.write(byte(0x00));
    Wire.write(val);
    Wire.endTransmission();
  }

  Serial.println(SoundVal);


}

I'd need a schematic.

Just added a DC-DC converter and battery.
I haven't really worked with Schematics before so hopefully, that makes sense.