Introduction: Sound Meter - Arduino

In this Instructable I'll show how to make a Sound Meter using an Arduino and some more components.

This is a school project I did recently which took me a year to complete, it is based on the construction of a Sound Meter which registers sound levels in decibels. The objective was highlighting noise pollution, a type of pollution that is less known, but which constantly affects us in our daily lives.

Step 1: Supplies

Electronics:

  • 1 - Arduino MEGA 2560
  • 1 - SparkFun Sound Detector
  • 1 - MicroSD Card Module
  • 1 - Standard protoboard
  • 1 - Neopixel LED Strip
  • 1 - LCD (20X4)
  • 1 - RTC DS3231(Real Tme Clock)
  • 1 - Seven degment display
  • 2 - 9V Batteries
  • 1 - Buck Converter
  • 12 - 220 Ω Resistor
  • 1 - 470 Ω Resistor
  • Cables
  • 2 - Switches
  • 1 - 1000 μF Capacitor

3D Printing:

  • Anet A8
  • Bq Black PLA

Assembly/tools:

  • Hot glue + Hot glue gun
  • Super Glue
  • Screws --> 3mm x various lengths
  • Double sided tape
  • Soldering Iron + Heat-shrink tubes
  • Screwdriver
  • Electrical tape

Step 2: Circuit Diagram

In this picture you can see the diagram of the circuit, done in Fritzing. I tried creating an schematic circuit diagram but I messed it up a little so I ended up making this more "visual" one, although I wanna give it another try.

I'll try to explain it.

First of all, the Arduino MEGA is the brain of the Sound Meter, it has the code which controls every component. The red PCB is the SparkFun Sound Detector which reads the amplitud of the waves, later on converted to dB. This measures are stored in the MicroSD Card along with the day and at what time were they taken (RTC Module), also they are displayed in the seven segment display.

We have also a Neopixel LED strip, consisting of 37 individually controlled LEDs, which light up in different colours depending on the decibel readings, explained in the LCD (see picture above).

  • Red: above 120 dB which is the pain threshold.
  • Yellow: between 65 and 120 dB.
  • Green: above 30 dB, which is the minimum the Sound Meter can detect.

This was design to resemble a traffic light and originally was planned to be just 3 LEDs (I even thought of a single RGB LED but it wasn't aesthetically pleasant). This Neopixel LED Strip is powered by a 9V battery but, since it only needs 5V, I used a Buck Converter to lower the voltage with a 1000 μF capacitor and a 470 Ω resistor not to burn the LEDs.

The rest of the components, including the Arduino were powered by another 9V battery.

There are also two switches: one for the main electronics (Arduino, etc.) and the other only for the LED Strip, in case I don't want them to light up.

NOTE: In the diagram to make it easier to see the conections there's a tiny protoboard but in the build I didn't use one.

Step 3: Code!

#include <Adafruit_NeoPixel.h><br>
#include <SD.h>
#include <SPI.h>
#include <DS3231.h>                // Modulo de reloj
#include <Wire.h>                  // LCD
#include <LiquidCrystal_I2C.h>     // LCD
#include <SevSeg.h>                // Display de segmentos

#define LED_PIN   24
#define LED_COUNT 37
Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);
SevSeg sevseg;
LiquidCrystal_I2C lcd(0x27, 20, 4);
DS3231  rtc(SDA, SCL);         // Reloj (rtc = real time clock)
File myFile;
int pinCS = 53;                // SD

const int soundPin = 0;        // Pin envelope del sensor de sonido (Analógico)

//Variables del sonido
int sound;                     // Amplitud
float decibelsCalculated;
float dB;                      // Decibelios tras la operación (float --> decimal)

//Millis
unsigned long time;
unsigned long t = 0;
int dt = 1000;                 // Diferencia de tiempo

unsigned long interval = 30; // the time we need to wait
unsigned long previousMillis = 0;

uint16_t currentPixel = 0;// what pixel are we operating on

/* Los caracteres personalizados de mi logo (máximo 8)
  Este LCD tiene 20 caracteres por 4 líneas y cada caracter se compone de pixeles de 5x8
  1 --> enciende el pixel     0 --> lo apaga
*/
byte logo_1[8] = {
  B00000,
  B00000,
  B00001,
  B00010,
  B00100,
  B00100,
  B01000,
  B01000
};
byte logo_2[8] = {
  B00000,
  B11111,
  B00000,
  B00000,
  B00000,
  B11111,
  B10101,
  B01110
};
byte logo_3[8] = {
  B00000,
  B00000,
  B10000,
  B01000,
  B00100,
  B00100,
  B00010,
  B00000
};
byte logo_4[8] = {
  B01000,
  B01000,
  B00100,
  B00100,
  B00010,
  B00001,
  B00000,
  B00000
};
byte logo_5[8] = {
  B00100,
  B00100,
  B00111,
  B00000,
  B00000,
  B00000,
  B11111,
  B00000
};
byte logo_6[8] = {
  B11110,
  B00010,
  B00100,
  B00100,
  B01000,
  B10000,
  B00000,
  B00000
};

void setup()
{

  currentPixel = 0;
  strip.begin();           // INITIALIZE NeoPixel strip object (REQUIRED)
  strip.show();            // Turn OFF all pixels ASAP
  strip.setBrightness(50); // Set BRIGHTNESS to about 1/5 (max = 255)

  Serial.begin(9600);
  lcd.backlight();
  lcd.begin();
  lcd.clear();
  pinMode(pinCS, OUTPUT);       // SD
  rtc.begin();
  Wire.begin();

  // Crear los caracteres del logo
  lcd.createChar (0, logo_1);
  lcd.createChar (1, logo_2);
  lcd.createChar (2, logo_3);
  lcd.createChar (3, logo_4);
  lcd.createChar (4, logo_5);
  lcd.createChar (5, logo_6);

  // Display de segmentos
  byte numDigits = 4;
  byte digitPins[] = {10, 11, 12, 13};
  byte segmentPins[] = {2, 3, 4, 5, 6, 7, 8, 9};
  bool resistorsOnSegments = true;
  byte hardwareConfig = COMMON_CATHODE;
  sevseg.begin(hardwareConfig, numDigits, digitPins, segmentPins, resistorsOnSegments);
  // sevseg.setBrightness(90);

  //LOGO
  lcd.setCursor(9, 1);
  lcd.print(char(0));
  lcd.print(char(1));
  lcd.print(char(2));
  lcd.setCursor(9, 2);
  lcd.print(char(3));
  lcd.print(char(4));
  lcd.print(char(5));
  delay(3000);
  lcd.clear();

  // Iniciamos la MicroSD
  if (SD.begin())
  {
    // Si funciona
    Serial.println("SD card is ready to use");
    lcd.print("Tarjeta:");
    lcd.setCursor(0, 1);
    lcd.print("Lista para usar.");
    delay(5000);
    // Create/Open file
    myFile = SD.open("Sonido.txt", FILE_WRITE);
  } else {
    // Si no funciona
    Serial.println("SD card initialization failed");
    lcd.print("Tarjeta:");
    lcd.setCursor(0, 1);
    lcd.print("Fallo al iniciar.");
    delay(5000);
  }

  // Abrimos el archivo
  if (myFile) {
    // Si se creó/abrió correctamente
    Serial.println("File created/opened");
    lcd.clear();
    lcd.print("Archivo:");
    lcd.setCursor(0, 1);
    lcd.print("Creado/abierto.");
    myFile.println(" ");
    myFile.print(rtc.getDateStr());
    myFile.print(" - ");
    myFile.println(rtc.getDOWStr());
    myFile.close(); // close the file
    delay(5000);
  } else {
    // Si no se abrió correctamente
    Serial.println("Error opening file");
    lcd.clear();
    lcd.print("Error abriendo el");
    lcd.setCursor(0, 1);
    lcd.print("archivo.");

    delay(5000);
    }lcd.clear();                                   // Limpiamos el LCD
    lcd.print("SONOMETRO");
    lcd.setCursor(0, 1);
    lcd.print("Rojo: >120 dB Nocivo");
    lcd.setCursor(0, 2);
    lcd.print("Amarillo: >65 dB");
    lcd.setCursor(0, 3);
    lcd.print("Verde: >30 dB");
}void loop()
{
  time = millis();
  if (time - t > dt) {
    t = time;
    sound = analogRead(soundPin);                 // Lee los datos y valores del pin Envelope del sensor de sonidodecibelsCalculated = 20 * log10(sound / 1);   // Calcula los dB
    dB = decibelsCalculated + 30.15;

    Serial.println(dB);                            // Imprimimos en el puerto serial los dB

    // Open file
    myFile = SD.open("sonido.txt", FILE_WRITE);if (myFile) {
      //Si se abrió correctamente el archivo
      myFile.print(rtc.getTimeStr());           // Escribimos la hora
      myFile.print(",");
      myFile.println(dB);                       // Escribimos los dB calculados en el txt
      myFile.close();                           //Cerramos el archivo
    }
  }
  sevseg.setNumber(dB, 2);                        // Escribimos los dB en el display de segmentos
  sevseg.refreshDisplay();

  // Leds
  if (dB > 120 && (unsigned long)(millis() - previousMillis) >= interval) {                                   // Led ROJO --> A partir de 120 dB
    previousMillis = millis();
    colorWipe(strip.Color(255, 0, 0));
  }
  if (dB > 65 && dB < 120 && (unsigned long)(millis() - previousMillis) >= interval) {                        // Led AMARILLO --> Entre 65 y 120 dB
    previousMillis = millis();
    colorWipe(strip.Color(255, 128, 0));
  }
  if (dB > 30 && dB < 65 && (unsigned long)(millis() - previousMillis) >= interval) {                        // Led VERDE --> Entre 30 y 65 dB
    previousMillis = millis();
    colorWipe(strip.Color(0, 255, 0)); // Red
  }
}

void colorWipe(uint32_t color) {
  strip.setPixelColor(currentPixel, color);
  strip.show();
  currentPixel++;
  if (currentPixel == LED_COUNT) {
    currentPixel = 0;
  }
}

This is the code I created, it's really long. For the the Neopixel LED Strip I used the Adafruit Neopixel library, I tried using the Fast LED but it's easier this one. Also, I coded it so that the SparkFun Sensor read the amplitud each second, this resulted in too many readings so I changed it once to 5 seconds, but I ended changing it to one second again.

I've also attached the ino file.

Step 4: CAD Design - Fusion 360

I've had my Anet A8 for about 4 years now (I LOVE IT) and I've always used TinkerCAD, which is an online free CAD program that lets you design wathever you want! It is very intuitive and I learned by tinkering (The Internet is fuuuulll of info, I learned to code and do projects with Arduino thanks to it and the amazing Arduino forum. But also everything I now from 3D Printers. That's why I decided to make this post and share my experience).

For this project I switched to Fusion 360 because TinkerCAD has some design limitations, originally I got Fusion before thinking about the project because you could get it for hobbyists (really cool if you only use it once in a while to design your tiny creations), altough I didn't use it until I decided to create the Sound Meter.

Thanks to the basic knowledge I had from my previous TinkerCAD adventures I quickly learned the basics and created the first version of the case (see first picture), I liked it and I used it to see how the Sound Meter worked and some experiments (trial and error). But I thought I could design a better looking one, so I created version 2 (and the final one), the black and curvy case.

In this last design I improved a few things to make it more functional and beautiful:

  • Reduced the size
  • Neopixel LED strip
  • Better organization
  • Knurl patten to easy take the top off.
  • Black filament (more elegant ;) )

Both are divided in pieces to fit in the Anet A8 bed. In version 2 there are 26 pieces, and you can take off the top and see the machine guts, I also designed it for not having to unscrew the Arduino when connecting it to the computer.


Details

This design has some details that I want to highlight:

  1. The knurl design --> To add more grip and help lift the top part (3rd picture). I also hid the entrance of LED cables covering it with electrical tape.
  2. SD card --> it has a groove to make it easier to pick it up (4th picture).
  3. Guide --> To help keep the top part in place I designed a triangular guide (5th picture).
  4. Silicone adhesive bump stops under the bottom piece.

Step 5: 3D Printing

Both versions took a long time to print.

I'm gonna talk about the final version. I used the Cura slicer and my parameters were:

  • Most of the pieces don't need supports
  • I used a skirt in some of them because they were tall or small, to help them stick to the bed.
  • Temperature = 205º
  • Bed = 60º
  • Fan --> Yes
  • 0.2 mm
  • Speed = 35 mm/s aprox. (depends on the piece). Although the first layer is 30 m/s.
  • Infill 10 - 15% (It also depends on the piece).

One of the pictures shows some of the pieces.

Step 6: Assembly

In the pictures can be aprecciated the difference regarding to orgnization.

As always I'm gonna focus on the final version, the black one. Unfortunately, I don't have any pictures of the build, but I hope this pictures show how it's all set up.

Both batteries have two compartmens to hold them and make easier their replacement, I sticked them with double-sided tape. I also used JTS connectors (I think that's the universal name, cause there are various types, but I've also added a picture of the ones I used) they also make easier taking out the batteries.

I covered all the places were I soldered with heat-shrink tubes.

The LCD is also held with some double-sided tape. And some parts are held in place with screws of 3mm of diameter and various lengths except for the MicroSD Module, which had smaller holes so I held it in place with some that I had laying around and were the correct size.

The switches and the seven segment display were wrapped in electrical tape so there wasn't the need to use hot glue or super glue because they fitted snuged into their respective places.

Step 7: Calibration

The best way could be with another Sound Meter but I dind't have one so I used an app in my phone. And this fisics formula to obtain the decibels.

Step 8: Result

So this is the ending result of both cases. I have attached pictures of both but all the components of the first version are on the last one, which is the real final result but I don't want to forgett the other one because it was also a part of the creation process.

NOTE: This is a still work in progress post, I might change some things, like explain more the calibration or add a video showing it working.

Step 9: Conclusion

I measured some places with the Sound Meter I built to see how much noise pollution do we live with and I made some graphics in Excel showing how it fluctuates and the maximum and minimum dB peaks.

  1. This is in the change of clases in my school.
  2. An indoor party in New Year's Eve, I noticed that the lowest decibels where when in the change of a song.
  3. In a cinema watching 1917. I kind of know in which part of the movie that increasing decibels at the beginning is but I won't say anything, although I don't think it's a spoiler.

Note: every measure shown was made months before the pandemic caused by the COVID-19 disease.

Step 10: Problems Encountered

In the creation of this project I faced some problems which I want to talk about because they are part of every makers creation.

  1. Neopixel LED strip code: The biggest issue with the code was the LED strip and the animation delays, which affected the whole programs (including the refresh rate of the seven segment display). I used millis but still affected everything so I ended up leaving with a code I made that didn't affected the rest of the components but the animation didn't start in the first LED, it would start in a random one (I don't know why), but it still looks cool. I did searched a lot and the problem of the colourwipe animation seems unfixable.
  2. This isn't a major problem, the SparkFun sensor I bought didn't had headers so I bought ones and soldered them but they hinder in the placing of the sensor in the 3D printed case. But, since I'm not the best at soldering I left it like that and is slightly misplaced.
  3. When assembling the final case I found it was to difficult to place correctly the 3D printed curves of the sides so I designed another piece to place and glue them correctly.

Guess I'm a perfectionist (sometimes it's bad) but I think there's a lot of room for improvement.

I also thought about adding an ESP8266 Wi-fi Module to also access through a phone, PC, etc. to see the readings instead of turning the Sound Meter off and picking up the MicroSD card.