Tuesday, February 18, 2014

A simple Sound Pressure Level Meter (SPL) dB audio meter using AVR ATmega

Updated to version 02.



What is proposed here is a SPL db meter using and AVR Atmega micro.


A sound level meter or sound meter is an instrument which measures sound pressure level. Sound pressure level (SPL) or sound level is a logarithmic measure of the effective sound pressure of a sound relative to a reference value. It is measured in decibels (dB) above a standard reference level. The commonly used reference sound pressure in air is = 20 µPa (rms) which is usually considered the threshold of human hearing. Keep in mind that 1 pascal will equal an SPL of 94 dB. Because the frequency response of human hearing changes with amplitude, a weighting have been established for measuring sound pressure. Usually the A-weighting curve is used. A weighting curve is a graph of gain across the frequency range (10Hz to 20kHz).

SPL level is defined as


given p_rms as the sound pressure measured, and p_ref as the reference sound pressure.

Once we have got the RMS value of the signal (actualRMS), we can transform it to SPLdb using this formula:


given refRMS as the reference RMS value for the input board at a know refSPLdb SPLdb level.

To compute SPL measurements, the meters loop is:
  1. collects N samples
  2. do FFT for the N samples collected, the signal is now transformed in the frequency domain
  3. apply A-weighting (in freq domain)
  4. get magnitude of the signal
  5. get RMS value of the signal
  6. apply a time-weight filter to RMS value
  7. compute the SPL using the RMS value
  8. output data
Every sample is collected at a fixed time, a timer interrupt impose this timing, this is because we need to know the sampler frequency, to built filters and output signal magnitude.
Runnig @16Mhz i'm able to collect samples at almost 22050Hz.

For FFT i've used Radix-4 FFT library you can find it here http://davidegironi.blogspot.it/2013/06/avr-atmega-audio-input-rma-using-fft.html.

The method to weighting the signal proposed here just use a weight table that contains the weight of the signal in the frequency domain, this table shoud be FFT size/2, because we can retain frequencies below Nyquist rate.


A matlab script to check this filter method is used.
The picture above is the frequency reponse graph of the A-Weighting curve used.
The picture below compares the values of SPL for the unfiltered signal (blue), A-weighting filtered signal using the matlab "filter" function (green), A-weighting filtered signal using the weight table method (red).
As you can see, matlab native "filter" function and weight table method almost response in the same way.


Once we have got the A-weighted signal we can compute the RMS value for the signal.
To obtain RMS value of the AC current of the audio signal processed, from which you can get the SPL db value, we use the Parseval's theorem for FFT so for fft size of N (look at the Radix-4 FFT library link above for further information)


An SPL meter also needs the signal to be time-weighted. Time-weightings have been internationally standardised, 'S' (1 s) originally called Slow, 'F' (125 ms originally called Fast and 'I' (35 ms) originally called Impulse.
A time-weight is a RC filter, exponential averaging is equivalent to a simple RC filter


Y is the RMS signal global, and Ynew is the RMS signal computed every step.
alpha effects the filter speed, it has to be a number between 1 and 0.
We can define alpha so that it depends on the sample frequency Fs and the windows size W. A good estimation could be


In my code, i've use another estimation for alpha, it seams to me better to consider the number of cycles needed to collect the N samples, i've call this number fsc, said this, my alpha was estimated as


Now that the signal is windowed, we can compute SPL using the above definition:



The input microphone preamp board proposed here is a derivation of the John Conover WM-61A preamp. The reference is the schematic-6 found here: Using the Panasonic WM61A as a Measurement Microphone (John Conover).
This board is stated 306uV RMS at ~32db.
Using an ebay SPL meter, and a scope, i've found that my board implementation should be 315uV at ~32db (which is next to 306uV as stated in the referecence audio board schematics).


Two http://processing.org/ scripts are provided as a viewer for the data.
The screenshot below shows one of them, it also show you the spectrum of the input signal.


I'm not a DSP expert, so method proposed here can be improved, for example it is possible to implement the A-weighting filter in time domain, becuse it can be used as a IIR filter, this will prevent the use of the FFT computation for the signal, saving microcontroller resources.

Also, if you want to help me, send me feedback if you:
  • you've got any better input board circuit
  • you've found bugs in my software implementation
This project is build on an ATmega8 running at 16Mhz, compiled with avrgcc, using Eclipse IDE


ChangeLog
  • 02b: main.c strict compile error fixed, function audioget_getrmsval now called the right way (thanks to Emmanuel Pierre for reporting this bug) 
  • 02: weighting function bug fix, weighting now applied on both the real and imaginary part of the fft (thanks to Xiaofeng for reporting this bug).
  • 01: first version.

Code

Notes
  • read risk disclaimer
  • excuse my bad english

142 comments:

  1. Hi Davide, great idea. Im working in a SPL Meter too, and I found Primo Mic M173 capsule, wich is working great. Im refining preamp now. I will try your design for it. Is your code good to be run on an arduino uno r3 board?

    ReplyDelete
    Replies
    1. Hello, as far as i know Arduino UNO is built on ATmega328, so yes, it can be run on that board.
      But yo built it using the Arduino framework code may need some refactoring.
      Let me know how does it works.

      Delete
    2. Hi,davide I'm asking you?? , Audioget_visualizer software for me Please send Email me: msun.nbtelectronic@gmail.com Thank you

      Delete
    3. You can find the visualizer software in the code you can download here.

      Delete
    4. Hello,
      Do you have the same code for arduino framework?
      I mean the audioget library refactored for arduino?
      Thanks

      Delete
    5. No I'm sorry. However it should not be difficult to translate in to arduino. Because arduino too use avrgcc compiler, and it is based on a ATmega family.

      Delete
  2. Excuse, I 've downloaded the code file, But They are (PDE) format How they are setup ? Computer does not recognize their format
    Please get help !! Thank you





    ReplyDelete
    Replies
    1. Hi, mr Davide Gironi, Thanks for your help, Im download software & setup,
      Im a have a question of you ?
      circuit diagram & How The connect Micro to usb & Driver Used for computer
      Type usb adapter & IC used for adapter About this explain
      Thank you



      Delete
    2. microcontroller to pc communication is done through UART, you have to connect an RS232 USB TTL adapter to TX and RX uart pin of your microcontroller. If this is your first project, i suggest you to build an "hello world" uart example.

      Delete
  3. Hi, for programm micro atmega8 in project of HEX code in file avr_splemeter.HEX
    use ?

    ReplyDelete
    Replies
    1. you can compile the code by your own, using avrgcc as compiler, or upload the avr_splmeter\Release\avr_splmeter.hex file to your ATmega8 microscontroller, running at 16Mhz.

      Delete
  4. Hi Davide, I cannot download the zip from source forge. Would you please send me copy to my mail address? beijingcrow@gmail.com Thank you

    ReplyDelete
  5. Hi Davide, I use the ATmega1281 with 3.3V power supply. Can I use this circuit with Vcc = 3.3V power supply ?

    Thank you for answer.

    ReplyDelete
    Replies
    1. Hello,
      it depends on the opamp you use, you have to look for one with a minimum votlage below 3v. Like the TLC272C*.
      Of course you have to calibrate you microphone pre, setting up the corretct voltage ref and db ref (AUDIOGET_VOLTREF, AUDIOGET_DBREF).

      Delete
    2. Hi, i have another question. Why do you use in the "adc_emafilter" (64 - aplha) instead of (1 - alpha) and how you calculated the coefficient alpha = 30? I found a formula for EMA filter: alpha = exp (-1 / (sampling_frequency * TAU_S)) ...

      Delete
    3. I've use 64 to avoid the use of float math.
      Writing
      _ (1-alpha)*Y + alpha*Ynew _ , alpha between 1 and 0
      is pretty the same of int math
      _ ((63-63alpha)*Y + 63alpha*Ynew)>>6 _, alpha between 63 and 0
      To analize the freq response of that filter one can use the Laplace transformation, and then convert it to the Z domain because we are in discrete time. It means that the magnitude respose H[z] = alpha / (alpha*z^-1), with 0 <= alpha <= 1. Decreasing the value of alpha will lower the cutoff frequency. I've chose to an alpha of almost 0.46 it means 30.

      Delete
  6. I can't found Audio signal Generator .PDE
    so can you please send me .PDE on
    mahendrasondagar08@gmail.com

    ReplyDelete
    Replies
    1. Hello, the audio signal generator it's not a processing sketch. It's a binary windows file, you can find it here: https://code.google.com/p/audiotools/

      Delete
  7. hi dear Davide,
    I have a question, what is the program for opening the schematic file that you put above, neither altium nor proteus could open that.
    thank you very very much

    ReplyDelete
  8. Hey can you mail the connection diagram with the microcontroller. And if you have any documentation regarding the code please mail me. Thank you...!

    ReplyDelete
    Replies
    1. Hello, simply connect the analog output of the microphone preamplifier to one of the ADC of the microcontroller. If you are using the code i posted connect it to the PC3 input pin of the ATmega8. Also add a 16Mhz crystal, and set fuses in order to make the ATmega run @ 16Mhz. Unluckly the only documentation i've build for this project is the one you can find here or in the attached download.

      Delete
    2. can you tell me the specific data for fuse bits atmega8@16mhz

      Delete
    3. Hello, take a look here: http://www.engbedded.com/fusecalc/
      Usually Low Fuse to FF works. But keep in mind that if you made mistake on setting fuse, you will "brick" your micro, then you would need something like the "Atmega fusebit doctor".

      Delete
  9. Hi, Davide Gironi, can u tell me what should I change if I want to get this program with ATmega16?

    ReplyDelete
    Replies
    1. if it isnt hard to do maybe you can send it? maciek1992mac@wp.pl

      Delete
    2. Hello,
      You have to change the TIMER interrupt registers.

      Delete
    3. Thank you, I will try to do it.

      Delete
  10. hey in your program you keep the voltage reference to Aref; internal vref off. so what voltage do you apply to the aref pin.

    ReplyDelete
    Replies
    1. Hello, in this code ADC reference is set to external, and the AREF pin is connected to 5V, but you can even set ADC_REF in order to accept other reference voltage. Keep in mind that with internal 1.1V, or 2.56V mode, or with lower external voltage, you reduce the amount of signal you can compute.

      Delete
  11. Replies
    1. Hello, where's your question? I can not find it, sorry.

      Delete
    2. Hi there, I'm sorry but i think my question wasn't published... anyway, I can't load the code directly into my Arduino Uno R3 controller, could you send me the code in .txt, please?

      Delete
    3. This code is for ATmega8, compiled with avr-gcc, you could not load it into an Arduino Uno R3 with the Arduino IDE / framework. You could download the code from the above link, read the files you read from the audioget folder as an arduino library, and use that library. Or you can adjust this code in order to be compiled with avrgcc and to be run on a ATmega328p.

      Delete
  12. Dear Sir
    i can connect atmega 8 microcontroller with JP1 pin(from above diagram)with your code.then i can get a value on lcd.

    ReplyDelete
    Replies
    1. Hello, it that's a question, yes, you can connect JP1 from the analog board to an ADC of your micro, then you can output values to a LCD.

      Delete
  13. Hi Davide!
    In advance I wanna thank you for all your effort in this project is simply amazing. In the other hand I have a question for you, if I wanna run it on atmega328p what do I have to do to the code and to the hardware connections? .
    Thanks in advance.

    Mike

    ReplyDelete
    Replies
    1. Davide, Can I use an Atmega8A? Thanks

      Delete
    2. The ATmega8/A should have no problem at all, but you have to try. About the ATmega328, you have to change the timer registers that you can find in the audioget_init function, the one that rules the TIMER1_OVF_vect interrupt, according to the ATmega328 registers.

      Delete
    3. hey Davide!

      I´ve been experimenting with your project, and could not find the FUSE BIT CONFIGURATION so I can not get it to work, would you be so kind to explain to me the configurations that you did to the atmega8.

      Thanks in advance

      Delete
    4. This project is tested on ATmega8 @16Mhz. To run a ATmega8 at 16Mhz you will need to connect a 16Mhz crystal between XTAL1 and XTAL2 pin, and two small cap like 22pF ceramic, between XTAL1 and ground, and XTAL2 and ground. One you have connect those, you have to set the low fuse to accept external clock source, something like 0xFF should work. For further information about fuse, and all fuse combination, you could look at the ATmega8 datasheet or take a look here http://www.engbedded.com/fusecalc/. Remember that settings your fuse the wrong way can "brick" your micro.

      Delete
  14. Hi, can the output of this device be send via bluetooth? Thankyou

    ReplyDelete
    Replies
    1. Yes, one can use a simple and cheap UART Bluetooth module as example.

      Delete
  15. Hello and first many thanks for providing the circuit and code.

    Using avr-gcc with the Release/makefile gives some errors:

    hgode@aoa150:~/Documents/adsbox/audio/avr_splmeter/Release$ make all
    Building file: ../src/uart/uart.c
    Invoking: AVR Compiler
    avr-gcc -Wall -Os -fpack-struct -fshort-enums -ffunction-sections -fdata-sections -std=gnu99 -funsigned-char -funsigned-bitfields -mmcu=atmega8 -DF_CPU=16000000UL -MMD -MP -MF"src/uart/uart.d" -MT"src/uart/uart.d" -c -o "src/uart/uart.o" "../src/uart/uart.c"
    ../src/uart/uart.c:86:36: error: attempt to use poisoned "SIG_UART_RECV"
    #define UART0_RECEIVE_INTERRUPT SIG_UART_RECV
    ^
    ../src/uart/uart.c:87:36: error: attempt to use poisoned "SIG_UART_DATA"
    #define UART0_TRANSMIT_INTERRUPT SIG_UART_DATA
    ^
    In file included from ../src/uart/uart.c:40:0:
    ../src/uart/uart.c: In function ‘SIG_UART_RECV’:
    ../src/uart/uart.c:86:36: warning: ‘SIG_UART_RECV’ appears to be a misspelled signal handler [enabled by default]
    #define UART0_RECEIVE_INTERRUPT SIG_UART_RECV
    ^
    ../src/uart/uart.c:252:8: note: in expansion of macro ‘UART0_RECEIVE_INTERRUPT’
    SIGNAL(UART0_RECEIVE_INTERRUPT)
    ^
    ../src/uart/uart.c: In function ‘SIG_UART_DATA’:
    ../src/uart/uart.c:87:36: warning: ‘SIG_UART_DATA’ appears to be a misspelled signal handler [enabled by default]
    #define UART0_TRANSMIT_INTERRUPT SIG_UART_DATA
    ^
    ../src/uart/uart.c:295:8: note: in expansion of macro ‘UART0_TRANSMIT_INTERRUPT’
    SIGNAL(UART0_TRANSMIT_INTERRUPT)
    ^
    src/uart/subdir.mk:18: recipe for target 'src/uart/uart.o' failed
    make: *** [src/uart/uart.o] Error 1

    How do I fix these? (GNU Make 4.0, avr-gcc (GCC) 4.8.1)

    ~josef

    ReplyDelete
    Replies
    1. Hello. You can try to update the uart library, using the newer Peter Fleury one, the one shipped with this project could be not compatible with your avg-gcc. Let me know if it works ;)

      Delete
  16. After download and unpack the uartlib and make clean and make I got another issue:
    Building file: ../src/audioget/fftradix4.c
    Invoking: AVR Compiler
    avr-gcc -Wall -Os -fpack-struct -fshort-enums -ffunction-sections -fdata-sections -std=gnu99 -funsigned-char -funsigned-bitfields -mmcu=atmega8 -DF_CPU=16000000UL -MMD -MP -MF"src/audioget/fftradix4.d" -MT"src/audioget/fftradix4.d" -c -o "src/audioget/fftradix4.o" "../src/audioget/fftradix4.c"
    ../src/audioget/fftradix4.c:17:1: error: unknown type name ‘prog_int16_t’
    const prog_int16_t Sinewave[NWAVE] PROGMEM = {
    ^
    src/audioget/subdir.mk:21: recipe for target 'src/audioget/fftradix4.o' failed

    This has been resolved by inserting a line into src/audioget/fftradix4.c before #include
    (NEW is now:)
    #define __PROG_TYPES_COMPAT__
    #include

    This has been taken from /usr/lib/avr/include/avr/pgmspace.h where it says for prog_int16_t:

    =========================
    ...
    \typedef prog_int16_t
    \note DEPRECATED

    This typedef is now deprecated because the usage of the __progmem__
    attribute on a type is not supported in GCC. However, the use of the
    __progmem__ attribute on a variable declaration is supported, and this is
    now the recommended usage.

    The typedef is only visible if the macro __PROG_TYPES_COMPAT__
    has been defined before including (either by a
    #define directive, or by a -D compiler option.)

    Type of an "int16_t" object located in flash ROM.
    */
    typedef int16_t PROGMEM prog_int16_t;
    ...
    =======================

    with the above added line the code then compiles.

    Thanks for the uart hint.

    ~Josef

    ReplyDelete
  17. Created Arduino compatible version at https://github.com/hjgode/avr_splmeter_arduino

    ReplyDelete
  18. Hello

    I build the TLC272 circuit, but the output is to low. What is the expected amplification?
    As I used a signal injector with a high output, audioget_visualizer.pde showd a nice graph etc. But with a microphone and the TLC272 amplifier, the signal seems to be by far too low.
    As noted for the Arduino port, I switched Vref to internal for the Atmega. Is this correct? Can you post the complete circuit with the Atmega8 and a note about which Anaolg in and Vref is used?

    Thanks

    Josef

    ReplyDelete
    Replies
    1. Hello, the gain of this preamp should be 1+R3/R9. I've proposed the complete schematics, thought you just have to connect the preamp output to any ADC input of your ATmega. You have to set the ADC_REF (adc.h file) according to your ADC reference voltage. If your Arduino has the AREF pin connected to ground by a capacitor, then your ADC_REF should be set to 1 (i.e. AVCC with external capacitor at AREF pin).

      Delete
    2. Thank you for the reply. I found my mistake: during transfer of the circuit mannually for a striped pcb, I replaced R3 100K by a 220Ohm resistor. Now the amplification is better. Using the internal AREF will be 1.1V and the SPL is down at 32 most the time, where it was about 52-55db ground noise level here with the now broken SPL meter. I will have to do some more tests the get more or less reliable SPLs.
      thanks again
      ~Josef

      Delete
  19. This comment has been removed by the author.

    ReplyDelete
    Replies
    1. Hello, I'm sorry but I do not understand your question. Anyway, as long as you run FFT on the input signal, you transform the signal in his frequency domain, you now can read the signal frequencies. Take a look here at the The Scientist and Engineer's Guide to
      Digital Signal Processing here http://www.dspguide.com, it's a well written book.

      Delete
  20. how to display data on 16x2 by the LCD?

    ReplyDelete
    Replies
    1. You cna't do that much on a 16x2 LCD, you can just write out the string for the frequency observed. Take a look at the P.Fleury LCD library here: http://homepage.hispeed.ch/peterfleury/avr-software.html Thas's really a well made and simple to use piece of software.

      Delete
  21. http://s019.radikal.ru/i638/1702/51/e1ea9a5d4eb7.jpg
    how to calculate the frequency of the signal?
    atmega 32 + lcd

    ReplyDelete
    Replies
    1. Hello, i suppose you are asking me how to make a project like the one in that picture. As i tell you January 31, 2017 at 9:22 PM you may use FFT. Rude speaking: trasform your signal in the domain frequency using FFT, then you get your signal "splitted" by frequency and you may measure each frequency power. Take a look here, that's well explained http://www.dspguide.com/ch9/1.htm. Once you've got your frequency analysis you can draw it out on an LCD, there are a few library out there for LCD, it depends on what driver you are using. Sometime you have to draw pixel by pixed, making a pixel matrix of the signal you would like to draw.

      Delete
    2. One further not about frequency analysis. I completly forget that you can also take a look at my processing sketch to see how the specrum meter is coded, and the port it to your micro, and plot it on an LCD. Hope this helps.

      Delete
  22. Hi Davide,why the SPL value is showed in integer format instead of float? Thanks

    ReplyDelete
    Replies
    1. Hello, thank you for that question. That's because I wasn't interesed in decimal point. This is not a precision instrument, to me 1dB of accuracy was enought on this meter, but one can even use float.

      Delete
    2. This comment has been removed by the author.

      Delete
  23. Replies
    1. Hello, what do you mean with which? If you are speaking of the frequency spectrum analyzer, take a look at the audioget_visualizer processing sketch and the parts of code involved by the audioget_getmagnitude(&spectrum[0]) on the main sample code.

      Delete
    2. I need to get the frequency Hz and display on lcd

      Delete
    3. As i tell you you here, check the audioget_getmagnitude function and select a proper LCD library to work with. Hope this helps.

      Delete
  24. Hello again, I have seen another project similar to this, but yours is more complete. The autor uses Fast Hartley Transform (FHT). I am reading that process time is similar for FFT and for FHT due modern computers speed. But what about microcontrollers? Here: http://www.redalyc.org/articulo.oa?id=344234322004 they say that:
    "Orthogonal transformations have been very useful in thecharacterization and signal processing. In particular Hartley Transform allows for time-frequency representations and vice versa. This paper presents an algorithm for calculating the Discrete Hartley Transform in embedded systems with the objective of minimizing the computational load and storage capacity required. It exploits the similarity with the Discrete Fourier Transform to use a fast algorithm reduces the number of trigonometric functions calculated using the rotation factors (Twiddle factors). In general, the implementation can increase the size of the processing window and increase computational speed compared to direct calculation".
    What do you think about using FHT instead of FFT in order to improve your project? Thanks for your answer and
    Un saludo desde Popayán, Colombia

    ReplyDelete
    Replies
    1. Hello, thank you for that question. Yes FHT is even faster than Radix-4, this could be a good improvement, at the time I write this project I was testing and using the Radix-4, that's because of my choice, but FHT should do the job. I will try to use FHT for an improved version of this meter, testing the FHT for real. Here you can find a comparison against the most used FFT http://www.cypress.com/file/55401/download, then here ther's a good FHT implementation for AVR http://www.waitingforfriday.com/?p=53#Fast_Hartley_Transformation

      Delete
  25. Hello Devide,

    Insted of TLC2272 I'm suing NPN transistor 2N3904 as a pre-amplifier, which i got the idea from your November 2014 post

    http://davidegironi.blogspot.in/2014/11/a-npn-transistor-electret-condenser.html

    I'm using ATmega1281 with 3.3V @16Mhz
    I'm using same sampling rate, tune my ADC with 3.3V
    my amplifier output voltage is 1.44V at 32dB Noise
    now the thing is that which points that i need to change to get the proper output

    ReplyDelete
    Replies
    1. Hello, you can use any preamp, the TLC2272 should have an higher SNR, but a NPN will do the job. You have to setup your hardware in the audioget.h header file.

      Delete
  26. Replies
    1. Hello, yes but you have to change the code a little bit, also you have to compile it using the avrgcc compiler, not the Arduino framework.

      Delete
  27. Replies
    1. You can take a look to a Eclipse AVR toolchain. Or, if you would like to use the Arduino IDE and Framework, you have to change the code by your own.

      Delete
  28. This comment has been removed by the author.

    ReplyDelete
  29. By what setting can the frequency of peaks be?
    http://forum.vegalab.ru/attachment.php?attachmentid=239967&d=1434809111

    ReplyDelete
    Replies
    1. Hello, if you mean what's your frequency peak RMS, you can just take the max RMS from your frequency domain signal.

      Delete
  30. Replies
    1. Hello, if i understand what do you mean, something like this should work (note: code below is not test)
      uint16_t samplingfrequency = 22050; uint16_t samples=64; double spectrummax = 0; uint8_t spectrummaxindex = 0; for(i=0; i spectrummax) { spectrummax = spectrum[i]; spectrummaxindex = i; } } double peakfreq = (samplingfrequency/(samples/2+1)) * spectrummaxindex;

      Delete
    2. yes need a frequency of peaks.
      can you add this feature?
      https://hostingkartinok.com/show-image.php?id=b288355e22e18ab48a827e71673e34be

      Delete
    3. Hello, you can add this feature to the code provided in link. I have no time at now to implement that. If you do that please share the code, it could be helpfull for other people. Thank you!

      Delete
  31. This comment has been removed by the author.

    ReplyDelete
  32. Can you reduce the sampling frequency from 22050 to 240?
    #define AUDIOGET_ADCSAMPLERATE 22050 to 240?
    #define AUDIOGET_SAMPLES 64 to 256?

    ReplyDelete
    Replies
    1. Hello, you can reduce the sample rate, but a 240Hz sample rate is too low, you will need a better ADC mic pre to process such a low frequency.

      Delete
  33. ок.
    Move the project from atmega8 to atmega32 error
    No definitions available for this AVR
    How to fix for atmega32?

    ReplyDelete
    Replies
    1. Hello, you just need to add definitions on the ADC library for the ATmega selected

      Delete
  34. help me please .
    to fix for atmega32

    ReplyDelete
    Replies
    1. Hello, the only think in this project that prevents it to be compiled for ATmega32 is the adc library. So, take the ADC library out of this project and check it how you have to modify in order to make it works, it can not do your homework or you will not learn anything. Some tips: the ATmega32 datasheet is your friend here, it would be really simple.

      Delete
  35. This comment has been removed by the author.

    ReplyDelete
    Replies
    1. Hello, so if it's all ok you can use this functions. Please, for the next time do not post long codes here, instead use pastebin or something like that.

      Delete
  36. Hi Davide, if I want to measure frequences until 20 khz, I must use a sample frequency about 40 khz and a weight table for 20 khz. How did you make your weight table for the sampling frequency of 22050 hz and what some one must to do to get a weight table for testing sounds until 20 khz?

    ReplyDelete
    Replies
    1. Hello, you should find the build_Aweighting_table.m matlab script in the helper folder of the downlodable package.

      Delete
  37. Thanks Davide, I had not seen it. You are great!!!!

    ReplyDelete
    Replies
    1. Thank you, this kind of comments are always welcome :)

      Delete
  38. Hello . Help me please .
    Тo fix for atmega32

    ReplyDelete
    Replies
    1. Hello, look at my comment April 15, 2017 at 2:38 PM

      Delete
    2. Delete the adc file?
      Help rebuild the project, I suffer for a long time.

      Delete
    3. Hello. Try to build a simple ADC library at first, it will be easy. Also check the Arduino IDE, is fairly simple than plain avrgcc code. Check the avrfreaks forum, you will find how to read ADC for ATmega32 there.

      Delete
  39. Hi Davide:

    just surfing and found your excellent project here. This project is sure really popular even years after. :)

    However, I have a question regarding your A-weighting frequency response graph: from most of googled data, it shows the A-weighting stopped after 20 kHz, instead of your 2~3 kHz showed above. Is there a typo in your graph, or have I misunderstand these pages? Like:
    https://commons.wikimedia.org/wiki/File:Acoustic_weighting_curves_(1).svg#/media/File:Acoustic_weighting_curves_(1).svg
    or
    https://en.wikipedia.org/wiki/ITU-R_468_noise_weighting

    LF2YR

    Carl

    ReplyDelete
    Replies
    1. Thank you for your feedback. There was a typo error in the matlab script that I've use to generate this figure.
      semilogx(AW*1000,20*log10(abs(AH))) instead of semilogx(AW*10000,20*log10(abs(AH))). Now it is corrected.

      Delete
  40. can we use op amp lm358 instead of your proposed circuit? i have connected lm358 based pre amp microphone, but am literally getting 0 values :(

    ReplyDelete
    Replies
    1. Hello, it should work with a LM358. But if you use that pre a design like this one would work better: https://lowvoltage.wordpress.com/2011/05/21/lm358-mic-amp/

      Delete
    2. Ty for the reply davide. I went to the market in city and sourced TLC272 :D now building that one. and will let you know.

      Thank you again!

      Delete
    3. Hello Davide, I have replicated your op amp circuit. and only replaced 330nf with 220nf. I am getting 0 rms and 0 spl on processing. is there anything i should look at?

      Delete
    4. Hello, at first look at the raw ADC values you get. You can also "fake" raw values in order to check if there is something wrong in the code, or in the hardware.

      Delete
    5. Thank you for reply Davide. I checked raw values with max min sketch and it was amplitude between 22 to 778 so values are working fine. but as i checked the value of audiorms and audiospl those are zeros. no changes at all. and in processing when i debug and set breakpoint. the value is zero too. do i need a statement to set which adc to use? btw i am using arduino translated code as published here. It would be nice to have your advice. Also what decibel range we can do using panasonic electret microphone?

      Thank you

      Delete
    6. Have you checked it using avrgcc compiler, have you checked the FFT output and try to use it on matlab, just to check what do you get from that? I'm using a Panasonic WM61A and i get 315uV at ~32db.

      Delete
    7. Thank you davide. finally the output came using avrgcc.

      But i am not getting rail to rail output. it just swing between 0 to 778 not upto 1023.

      i tried changing 10k resistor upto 100k to reduce senstivity but it doesn't go upto 5v.

      need your help. Thank you.

      Delete
    8. Hello, try to put a pullup of 100k and a pulldown of 100k right before the input micro PIN. Check this with a oscilloscope and a test signal if you get one.

      Delete
    9. Hi Davide, hope you doing good today!. I didn't get what you mean by input micro pin? is it on microphone or you mean where i send the audio signal on micro controller.


      Thank you!

      Delete
    10. will i be able to get range of 30 to 100 dba out of the setup :D?

      Delete
    11. The output pin of the schematics above has to be connected to the microcontroller input ADC pin, ther you have to put one pulldown and one pullup. Let's suppose you get 315uV at ~32db like my board, take a look at the SPL_db function, if you are using a 5V ADC ref, the max theorical RMS will be 2.5, so max SPL_db will be almost 109.

      Delete
    12. Thank you for the response Davide. I tried the pull up and pull down right on audio out which goes into micro controller. But it didn't go stll upto 1024. the lowest and max is still 0 to 781.

      my question is how it will goto 75db to 90 db range if we get only upto 781 values on adc.

      Thank you!

      Delete
    13. When no audio pass through the mic, you should get almost 2.5V, so 512 on ADC. Check it with an oscilloscope if you get almost 2.5V, and look at the signal output of the mic preamp.

      Delete
    14. How did you read 315uV on microphone, i dont have a dmm that goes below 100 mv :(

      Delete
    15. If you do not have that, you could get a x10 (or x100) gain using an opamp, then divide.

      Delete
    16. Yes i am getting 510 to 512 with no noise. that looks good but what i mean is from 0 to 1023 resolution we cannot get a range of more than 50 db, how can we achieve 90 dB range?

      Thank you

      Delete
    17. You can try faking the ADC raw output, just put a fake value and try with that, also try the formula using matlab or octave or any other math tool you are familiar with, it may help.

      Delete
  41. Hi Davide thanks for all the explanation. Everything worked well on with analog mic.
    Would it be possible to work with 12 bits ADC?
    How do I get more bin precision?
    Would I be able to work with a better microcontroler as Teensy3.6 and have better resolution and/or better results?

    After plotting the frequency spectrum. How do I get the SPL level a known microphone sensitivity let's say 32db. S/N?

    Thanks you one more time for the excellent project and how you keep helping everyone! Thumbs up

    ReplyDelete
    Replies
    1. Hello and thank you for your comment. Yes it should work with 12 bit. For more precision you have to build up a new Sinewave with let's say 512 NWAVE, and also of course taking more samples helps. Yes, you can just port it to other micro, but there will be a few change to do, most of the math part will work, ADC part must be changed. For your mic, If I've understand what you need you can measure your microphone level output using a multimeter and a calibrated spl meter. Hope this helps.

      Delete
  42. Hi Davide,

    Great project!, what is te maximum dB that your circuit could read, before saturation?. Thanks a lot for your post

    ReplyDelete
    Replies
    1. Hello and thank you, look at the Crush September 15, 2017 at 7:37 AM comments and reply. Hope this helps.

      Delete
  43. Greetings David,

    If I were to implement an analog A-weighting filter before sending the signal to the ATmega,will I still have to compute the fourier transform?

    ReplyDelete
    Replies
    1. Hello. It depends on what's your needs. You still have to compute the fft if you need to compute spl as example.

      Delete
    2. This comment has been removed by the author.

      Delete
    3. Why would you need to compute the fft if the signal is A-weighted prior to be sent to the adc.An actual analog filter would "A weight" the signal being sampled by the adc.The rms value can then be calculated in the time domain rather than computing the fft

      Delete
    4. Hello. That is because I'm using a digital weighting fileter. So the weighting function is in the freq domain. You can use an analog filter before ADC of course.

      Delete
  44. This comment has been removed by the author.

    ReplyDelete
  45. Hello David.

    Ok im recreate your config, step by step. Everything is same, but mic.
    Im calculate, what with opamp G - 66 and mic sens -35db, i would have 800uV at 32db.
    Also im change Vref to 1 (VRef = AVCC thru cap == 5V)

    Now UART receive two bytes 20 00. If im change ADC chanel or Vref to 0 (unconnected thru cap == 0V) , UART still receive 20 00. So i have 2 questions:

    Why 2 bytes, real Db values always between 0 and 120-140. So why 2 bytes, how i must interpret them?

    Why 20 00, why not zero or what? What zero point that system has?

    ReplyDelete
    Replies
    1. Hello, check the uart ouput by converting the values to ascii, use a simple terminal application.

      Delete
  46. Hello Davide,

    I am mounting a decibel meter with arduno using this Mic Electret Ci Max4466 Adjustable Gain Amplifier Module, I am having problems with the calculus part, I wonder if you could send your code to see what I did wrong, I can send mine .. .what I have doubts about alpha.



    my code:

    int arduino_analogico = A0;
    int valor_A0 = 0;

    #define VREF 5.0

    float getDb(){
    valor_A0 = analogRead(arduino_analogico);
    float dB = 20.0*log10(valor_A0);
    Serial.print("A0: ");
    Serial.println(dB);
    delay(1000);
    return dB;
    }

    void setup() {
    Serial.begin(112500);
    pinMode(arduino_analogico, INPUT);

    }
    void loop() {


    getDb();






    /*float voltageValue,dbValue;
    voltageValue = analogRead(arduino_analogico) / 1024.0 * VREF;
    dbValue = voltageValue * 50.0; //convert voltage to decibel value
    Serial.print(dbValue,1);
    Serial.println(" dBA");
    delay(1000);*/
    }

    ReplyDelete
    Replies
    1. Dear person Unknown, this code is not for Arduino, you have to change this code to make it works with the Arduino framework.

      Delete
  47. Hi I want to build a sound pressure level meter using the atmega164p. I am unsure where to start. I know I need a sound sensor connected to an amplifier how would I decide on the right components for this? Please get back to me. Thanks.

    ReplyDelete
    Replies
    1. Hello, you can follow the guide here. Unluckly I've not time at present to follow you.

      Delete
  48. Thanks for the reply David, did you use a rectifier in your circuit or in the software.

    ReplyDelete
    Replies
    1. The only rectifier I've used is in the bridge in the supply stage.

      Delete