# Using a microphone with an Arduino

EDIT: I have been investigating in this problem for quite some time. It turns out to be a way more difficult project than I thought and not something for beginners. This requires expensive hardware (microphone & amplifier) and some sophisticated audio analyizig on the microcontroller. Even a complete microphone with amplyfier circuit does not provide the desired results (according to the comments on this product)

I am entirely new to the Arduino (but I'm familiar with programming). In order to built a VU meter, I want to put a microphone to the analog 0 pin of the Arduino and display the value via the serial connection.

I googled and found this circuit:

... and I tried to build it with this result:

(I'm now using the circuit suggested by Oli Glaser in his answer)

The values on the serial monitor don't change depending on the music volume.

What is the easiest way to measure the volume on the analog input of the Arduino?

Also, I have a TDA2822M, but I don't know if it is helpful for this project. The caption on the microphone reads XF-18D.

Edit: My arduino code:

void setup() {
Serial.begin(9600);
}

void loop() {
delay(300);
}


The serial output: 1023 1022 1022 1022 1022 1023 1022 and so on

How can I check if the microphone works at all? Is it directional?

Edit: I am now using a S9014 transistor. The ADC and the serial connection work (I tested them with a potentiometer).

The serial output is now around 57.

Also, I don't have a multimeter or oscilloscope. I have a multimeter now.

• Have you verified with a scope that you can see an audio waveform at the output of your circuit? – HikeOnPast Jul 29 '12 at 22:31
• Whoa, why is the 3V3 and 5V pin shorted out in the schematic? That could be an issue. – Connor Wolf Aug 12 '12 at 0:47
• Nope, I just didn't draw the schematic properly. – Toast Aug 12 '12 at 17:40

The "easiest" way is simply to apply the signal and sample with the ADC. Store the results in a buffer then display as desired (in your case send to PC via RS232)
If you want the RMS level of the signal then you will need to calculate this at some point, either before sending to PC or afterwards.

Your amplifying circuit as shown is not ideal, but should work reasonably for a basic VU meter. EDIT - I just noticed C2, remove this as it will block the DC bias from the transistor, and the signal will swing below ground.

EDIT - here's a better circuit for the amplifying transistor:

This shouldn't care too much about the transistor used, the output bias should be around 2.5V.
The exact values for the input divider (R3 and R4) are not too important, it's the ratio of 1:4 that's more so. So you can use e.g. 400k and 100k, or 40k and 10k, etc (try not to go above or below these respective values). C2 should be >10uF. C1 should be >1uF (replaces C1 in your schematic)
R1 and R2 do need to be these values though.
All you need is the electret with it's bias resistor (R1 in your schematic)

One point of concern is the Arduino 3.3V and 5V lines seem to be tied together - I'm assuming this is a schematic error, but if this is the case in the actual circuit it will not work, and may damage something.
To pinpoint the problem(s) it would help to see your code, and what you are seeing on the PC side. Also what transistor are you using?

If you have an oscilloscope, then you can check to see if your mic/transistor are working correctly. If not, then a multimeter can be used to perform some more basic tests (e.g. confirm +5V present, confirm base of transistor is at ~0.6V, test collector to make sure it's not pinned to +5V or ground with no signal present)

Also you need to make sure the RS232 is working correctly, so writing some simple code to send some test values would be a good idea.

If you can provide the requested info, and let us know what tools you have available more specific help can be given.

EDIT - if you are sampling so slowly, then you will need a peak detect circuit like this:

You would put this circuit in between the transistor and the Arduino pin (minus C2)

The diode can be just about any diode. The cap and resistor values are just a guideline, they can be changed a bit. Their values dictate how long the voltage will take to change with the signal level. You can calculate this using the RC constant (i.e. R * C - in the above example, the RC constant is 1e-6 * 10e3 = 10ms. The voltage will take around 2.3 time constant to fall by 90% of it's original value, so in the above example if the voltage starts at 1V and you remove the signal, it will have dropped to 0.1V around 23ms later.

EDIT - okay, think I found a major problem. Your S9012 transistor is a PNP transistor (as is the S9015), you need an NPN transistor for this circuit. The S9014 is an NPN transistor, so you will have to use this one.

The capacitors marked "104" are almost certainly 0.1uF ceramic capacitors. The value (in pF) is the first 2 numbers followed by a number of zeros set by the last number. So for 104, the value is 10 + 4 zeros, or 100,000pF. 100,000pF is 100nF or 0.1uF.

EDIT - Not having a scope or multimeter makes life very difficult here (you should get hold of one or both as soon as you can)
However, there are some basic PC soundcard oscilloscopes that could be used to test your electret/transistor circuit. Visual Analyser is quite a good example:

If you replace C2 (not strictly necessary but a good idea), you should be able to feed the signal into the PC directly and observe in the software to see if the microphone and amplification are working correctly. If your PC has line in use that, but the microphone input is usually good for up to 2V IIRC. You could also test the electret directly - just remove the transistor bit and keep R1 and C1, take signal from the other side of C1.
Note that this method will not test the DC levels, only the AC (due to a DC blocking cap in the souncard input) but the AC (audio) signal is what you are interested in here.

If you try this, post the screenshots so we can get an idea of what's happening.

• 3.3V and 5V are not tied together. Its the first time I'm using this software - sorry. I will put my code in the question but there is nothing that could go wrong with it. Also, i made a project today that uses a photoresistor and displays the value on six leds like i want my vu meter to look like and I tested the serial connection with that. I have neither an oscilloscope nor a multimeter. The transistor has the caption "S9012 H 331" I also have "S9014 C 331" and S9015 ones. – Toast Jul 29 '12 at 23:26
• @Toast - see edit about C2, remove this and connect directly. – Oli Glaser Jul 30 '12 at 0:16
• I removed C2 and added the parts as Kristoffon described it in his answer. Still the same results. – Toast Jul 30 '12 at 0:27
• If you have a potentiometer or a variable voltage source, you can apply a 0-5V input to the input of the ADC to test your code, independent from your input circuit. You are trying to debug two things at once -- isolate the circuit and verify its behavior using an oscilloscope and/or isolate your code and provide a predictable but variable input to validate your code. – HikeOnPast Jul 30 '12 at 1:22
• @OliGlaser I am confused by the circuit. The "electret" is a microphone? Where does the other wire of the microphone go, GND or VCC? Do I connect 5 or 3.3V to that circuit? Could you please somehow remove the EDIT blocks and edit it so that it can be understood without reading the comment thread? I am also a beginner and I don't understand how the problem was solved and whether I can use the circuit you posted as-is. – Tomáš Zato - Reinstate Monica Mar 14 '16 at 9:54

Assuming your circuit works the audio signal is in the kHz range while the Arduino has an ADC suited for DC levels. The DC component on your signal is zero which is to say that it floats over a fixed voltage. It is that fixed voltage that your ADC is reading.

To fix that you would put a diode in series with your output connecting to the ADC and to a capacitor and resistor.

The cap will charge to the peak value being received while the resistor will discharge the cap when the signal dies down.

--|>|---*---- adc
*---- resistor -----*----ground
\----- capacitor ---/


Edit: The ADC input is actually floating as it has no bias whatsoever due to the series capacitor. If you're going to try my solution delete C2.

• Okay, I added this to the circuit and the signal on the serial monitor now is 458 (but still doesn't change when there is noise). – Toast Jul 29 '12 at 23:51
• I exchanged the transistor from "S9012 H 331" to "S9014 C 331" and the value is 56. – Toast Jul 29 '12 at 23:53
• The Arduino ADC is capable of sampling fast enough for audio. I don't use them, but I think 10ksps (so up to 5kHz bandwidth) is possible with the library functions, which is fine for lo-fi stuff (I'm pretty sure the actual ATMega can sample faster if used normally) – Oli Glaser Jul 30 '12 at 0:10
• @Toast - how fast are you sampling? If it's very slowly then the peak detector is a good idea. You can do this in software though. – Oli Glaser Jul 30 '12 at 0:13
• @Kristoffon - Not with an Arduino no, but I have used similar 8-bit micros (e.g. PIC16F, 18F, etc) for sampling and playing back audio many times. 10ksps is easily doable. To quote this AVR ADC document: When using single-ended mode, the ADC bandwidth is limited by the ADC clock speed. Since one conversion takes 13 ADC clock cycles, a maximum ADC clock of 1 MHz means approximately 77k samples per second. This limits the bandwidth in single-ended mode to 38.5 kHz, according to the Nyquist sampling theorem. – Oli Glaser Jul 30 '12 at 1:46

Your readings of 1022, 1023 are basically full scale on the Arduino's ADC. Assuming you installed a non-faulty series capacitor as shown in your diagram, this level cannot be coming from the microphone circuit you built, since that can only couple changing voltages (ie, AC).

As a result, I suspect you are reading leakage current within the ATMEGA itself - you would probably get the same result on any of the other (unconnected) analog pins.

Try making a very "lightweight" voltage divider with some high value resistors (between 10K and 100K) and use this to bias the analog input to half the reference voltage (you could also use a potentiometer, which gives you some extra testing capability). Then your reading with no input should be in the neighborhood of 512.

Once you have the ADC input suitably biased, you can start working trying to see if you get variation through it. You may be undersampling your bandwidth some, which means you will get aliasing of high frequency components, but if all you are trying to do is estimate overall volume that should not be too much of a problem.

• That sounds right, I guess it's overloaded. OP have you thought of connecting a small speaker to debug that analog line your reading. When I made a vu meter I took the lines from a headphone jack, basically straight into the AnalogRead and Mapped out the resulting. – Hellonearthis Jul 30 '12 at 10:15