I searched the web for a cheap method to let the ATmega respond to sound. My knowledge in analog circuits is very limited, but what I do remember, is that you can not attach a electret mircophone to a controller pin. The signal of the microphone is just too small and has to be amplified. There is much of information out there, especially on diy amplifiers. I stumbled upon this little circuit here. It consists only of a handful of components:
- 2 resistors 10k
- 1 resistor 100k
- transistor 2N3904
- 1 capacitor 0.1u
- electret microphone
Prototyping the amplifier
Putting things together on a breadboard.
Actually I had no 2N3904 around, so I replaced it with a BC337. The circuit is a emitter circuit with voltage degeneration (I dont know if that exists in english). I dropped the couple capacitor and took the signal right away at the collector.
Prototyping with the ATmega
The sound sensing is done with the ADC of the ATmega. A simple program reads the analog value of the amplifier over and over. If the value (loudness) exeeds a specific level, an LED is lit.
Here is the code. It is just hacked together and has lots of room for improvements.
/* ----------------------------------------------------------------------- * Title: sound sensor * Author: Alexander Weber * Date: 19.05.2007 * Hardware: ATmega8 * Software: WinAVR 20060421 * */ #include <inttypes.h> #include <avr/io.h> #include <util/delay.h> #define LED_BIT PD4 /* * get_adc * Return the 10bit value of the selected adc channel. */ uint16_t get_adc() { uint16_t value; // warm up the ADC, discard the first conversion ADCSRA |= (1 << ADSC); while (ADCSRA & (1 << ADSC)); value = ADCW; ADCSRA |= (1 << ADSC); // start single conversion while (ADCSRA & (1 << ADSC)); // wait until conversion is done return ADCW; } int main(void) { uint8_t i = 0; DDRD |= 0x1c; // PD2-PD3: col 6-7, PD4: debug LED // select channel ADMUX = 5; // ADC setup ADCSRA = (1 << ADEN) | // enable ADC (1 << ADPS1) | (1 << ADPS0); // set prescaler to 8 // say hello for (i = 0; i < 5; i++) { PORTD |= (1 << LED_BIT); _delay_ms(10); _delay_ms(10); _delay_ms(10); _delay_ms(10); _delay_ms(10); PORTD &= ~(1 << LED_BIT); _delay_ms(10); _delay_ms(10); _delay_ms(10); _delay_ms(10); _delay_ms(10); } _delay_ms(10); _delay_ms(10); while (1) { if (get_adc() > 180) { PORTD |= (1 << LED_BIT); _delay_ms(10); PORTD &= ~(1 << LED_BIT); } } return 0; }
Video
The video got lost :(
Conclusion
It was easy and worked pretty well. I enjoyed looking at the LED responding to the music. I haven’t recorded anything with this amplifier, it might sound awfull. Next steps could be playing the sound back or be able to analyze the sound (FFT). And (re-)learning more on analog circuit design.
Links
Hello all, Interesting post.
Hereis what I am looking for. Did analog circuit design 25 years ago. Looking for up to date methods:
I have an Alpine card CD receiver that has an Interrupt lead. I would like to take an iPod headphone out and generate a trigger from a circuit every time there is audio on the headphone jack. the trigger signal wil be connected to the interrupt lead on the head unit. I also need to hold the lead high for say 1-4 seconds once the headphone out goes higher than a preset value.
How do I do this?
Thanks in anticipation. Cheers. -Amitabh
LikeLike
Hello Alex,
Great tutorial, very well explained! I tried to recreate the setup, but it doesn’t work very well. It only responds when I blow into the speaker.
I used exact the components you described at the beginning, including the 2N3904.
One difference, but I don’t know if it matters: my electret is connected via two cables of about 20 cm. Could this influence the gain? Any other idea why my preamp performs so badly?
Thanks!
Pieter
LikeLike
Hi Pieter,
the gain of the original circuit is really really small. Try to log the values you get while it’s silent. Then log the values while you are blowing or playing loud music. Maybe that can help.
Otherwise you may want to choose another circuit with more gain.
Cheers,
Alex
LikeLike
Hey!
just a simple question the output should be analog or a trigger ?!
LikeLike
The output is analog but I needed only a trigger.
LikeLike
Hey, great tutorial! I’m thinking of recreating it, though not exactly the same.. Could you tell me if you really need capacitors C2 and C3 which are connected to ports 9 and 10 on the schematic above? Also, is Q1 needed? I’m thinking of using making the following circuit, connecting the “Output to next stage” to an ADC pin, and a servo to an output pin. http://www.reconnsworld.com/audio/simplepreamp.gif
Thanks for your time,
Vignesh R.
LikeLike
Hi,
I have no knowledge in microcontrollers but i can work with labview. I am searching for sound sensor that hear the noise from a pump. Do you have any idea to do this. I had a pump that can give noise when inside the storke is touched to mechanical parts. I need to adjust it by using sound sensor. Can you help with any idea,
LikeLike
yaa i have no idea about sound sensor.may i know how much money should i have to spend for this projet??
LikeLike
It’s only a couple of bucks. Only cents if you don’t count the microcontroller.
LikeLike
Hi,
thank you for this great setup. We built a RGB-LED Controller in a project and I added the Sound Sensor. We used only SMDs, so I choose the MMBT3904 instead of the 2N3904. Well, it does work. But I have the same problem as Josh(#38). My ADC output value is allways around 800 (10bit). And it only varies about +/- 10 when I play some sounds, so it is very tricky to find the right trigger level. What is your difference between silence and sound? I used an MCE101 instead of the MCE 100 but the only difference should be the cable… Has anyone an idea what could cause my high level?
LikeLike
Sorry for the double post.
It works just fine with a value of 800 now!
My problem was, that I sent every single value to my console with printf and therefore the programm was to slow. Now it is really sensitiv, even to the sound of me writing on my keyboard!
Again thank you for this real simple but great sound sensor!
LikeLike
hey, i was jus wondering if i can put the output from the amplifier into an arduino uno?
LikeLike
The diffrence between adc output is probably caused by AVREF specification. In atmega88 u can choose between AVcc/1.1V/AREF . I calculated aprox values with diffrent VRefs and thats what i got:
for AVcc ~ 176
for 1.1V ~ 800
the formula is very simple ADC = AIN/AVREF * 1024
PS. I used BC337 and output voltage was 0,86V.
PS2. Nice and simple amp :)
LikeLike
In the tutorial, you say you used 2 capacitors at 0.1uF but, i only see one in your design and schematics. Where is the second one located (if there is a second)?
LikeLike
You’re right, it’s only one.
LikeLike
Hi Alex,I measured the output of the BJT used VOM and found it to stand still in a position (with sound-needle run).
The sound sensor true or false? I don’t connect with AVR,i just test by voltage-VOM!
PL help me,thank for your watching my question!
LikeLike
Hi Luu,
you probably can’t see changes on a voltmeter because it’s too slow and the changes are too small.
Cheers,
Alex
LikeLike