Voice Loudness Monitor (Arduino)

by Harrrry in Circuits > Arduino

2483 Views, 28 Favorites, 0 Comments

Voice Loudness Monitor (Arduino)

IMG_20201124_120038584.jpg
IMG_20201124_120042000.jpg

In this pandemic it is important to take reasonable measures to reduce spreading viruses. A paper from 2019 found that louder voices spread more viruses (https://www.nature.com/articles/s41598-019-38808-z) [Asadi et al. 2019].

This simple project aims to remind people to not shout unnecessarily. This can be used in classrooms, meeting rooms or any other setting where people are talking.

Supplies

Arduino Nano x 1

Green 5V LED x 1

Red 5V LED x 1

560 Ohm resistors x 2

Jumper wires (male to male) x 4

Breadboard x 1

Electret microphone with MAX 4466 amplifier (https://www.adafruit.com/product/1063) x 1

USB to USB Mini B cable x 1

USB Power Bank or 5V Power supply x 1

Assembling the Circuit

IMG_20201124_105739354.jpg

The circuit is fairly simple and can be laid out in a number of ways. On my breadboard I have connected:

  • Green LED +ve to Arduino D3
  • Green LED -ve to Arduino GND
  • Red LED +ve to Arduino D2
  • Red LED -ve to Arduino GND
  • Mic VCC to Arduino 3.3V (this is the least noisy power supply pin)
  • Mic GND to Arduino GND
  • Mic OUT to Arduino A0

For supplying power to the Arduino, I simply connected the Mini USB port on the Arduino board to a USB power bank with the appropriate cable.

Writing the Code

A simple way of measuring loudness is to take the maximum and minimum voltage readings from the microphone. A dB sound pressure level can be calculated using the microphone sensitivity and amplifier gain. However, this application does not require this level of detail.

You can have a go at writing your own code or copy the example below:

// Define constants - these can be tuned to the user's preferences
#define sampleWindow 10 // Sample window width in milliseconds (10 ms = 100 Hz)
#define LEDtime 1000 //time to keep LED on for when noise goes above threshold
#define threshold 40 //mV
#define QTY_SAMPLES 16 // the number of samples to be averaged

//Define pins used on the breadboard
#define MIC_IN A0
#define LED_LOUD PD2
#define LED_QUIET PD3
#define V_MIC 3.3

//Create global variables
int sample;
long startLED;
float values[QTY_SAMPLES];
float sum;
int index;


// This function takes a rolling average of QTY_SAMPLES
// The oldest value is removed from the sum and the newest takes its place in the array. Then the mean of this array is returned.
float rollingAverage(float num) {
  sum -= values[index];
  values[index] = num;
  sum += values[index];
  index++;
  index = index % QTY_SAMPLES;
  return sum / QTY_SAMPLES;
}


//Begin serial output, initialise pins and set global variables
void setup()
{
  Serial.begin(9600);
  pinMode(LED_QUIET, OUTPUT);
  pinMode(LED_LOUD, OUTPUT);
  pinMode(MIC_IN, INPUT);
  float sum = 0;
  int index = 0;
}


//Sample the signal amplitude and calculate a rolling average. If the average loudness is too high, then alert user via LEDs
void loop()
{

  // Reset variables
  int signalMax = 0;
  int signalMin = 1024;
  unsigned long startMillis = millis(); // Set the start of the sample window

  // Record the signal maximum and minimum over the sample window
  while (millis() - startMillis < sampleWindow)
  {
    sample = analogRead(MIC_IN);
    if (sample > signalMax)
    {
      signalMax = sample;  // save the new maximum
    }
    else if (sample < signalMin)
    {
      signalMin = sample;  // save the new minimum
    }
  }

  // Convert the signal maximum and minimum into millivolts from the amplifier
  float amplitude = signalMax - signalMin;  // This calculates the peak-to-peak amplitude
  float millivolts = rollingAverage(amplitude) * V_MIC / 1.024; // This calls the rolling average function and converts the average amplitude to millivolts
  Serial.println(millivolts);

  //Alert the user via the LEDs if the noise is too loud
  if (millivolts > threshold) {
    digitalWrite(LED_LOUD, HIGH); digitalWrite(LED_QUIET, LOW);
    startLED = millis();
  } else if (millis() - startLED > LEDtime) {
    digitalWrite(LED_LOUD, LOW); digitalWrite(LED_QUIET, HIGH);
  }
}

//Further work could be converting the millivolts signal into a Sound Pressure Level (dB SPL), or adding more LEDs to display a noise level scale<br>

Tuning

IMG_20201124_105716169.jpg
IMG_20201124_105707748.jpg

The key value to be set is the 'threshold'. This is the number of millivolts which are required to trigger LED_LOUD. This is most easily done by using the serial monitor in the Arduino IDE. Here you can correlate how loudly you speak with what the Arduino calculates.

When the threshold is correctly set, the green LED should be lit during normal conversation, and the red LED should light up whenever anyone speaks more loudly than is necessary.

The other constants can also be tweaked to change the sampling window or the number of samples that are averaged. Play around with these constants to see what effect they have.

Thank You

uob_rae_logos_small.png

Thank you for reading this instructable, and thanks also to the University of Bristol and the Royal Academy of Engineering for supporting Project Clean Access.