Must be doing something wrong-Amplification

So this was supposed to be a simple follow some examples I found, build it, and use it...well not so much. I'm trying to use a LM386 to boost the signal of a elect condensor microphone so that my analog pin can read it and based upon the number returned turn a LED on or off...basically a sound detector or really simple VU meter. I found this example online, DIY Tengu on a breadboard – tinkerlog.
I'm using his circuit in the top right for the set-up, minus the speaker as I'm just needing to read the value to the pin.

This very example has come up before on the forum but the other fellows problem didn't help me any. I'm new to using pots so I played with them first and was able to hook them up alone and read the values via the serial just fine, twist one way bigger numbers, twist the other get smaller, life is good :slight_smile:

int potPin = 2;    // select the input pin for the potentiometer
int ledPin = 13;   // select the pin for the LED
int val = 0;       // variable to store the value coming from the sensor

void setup() {
  pinMode(ledPin, OUTPUT);  // declare the ledPin as an OUTPUT

void loop() {
  val = analogRead(potPin);    // read the value from the sensor
  Serial.print("Val = ");

So I know the pots do work, I'm just not getting the rest right somewhere. A first question would be for the 10K pot at the top, using it as a variable resistor, must the positive go to one of the outer contacts and the continuation of the positive to the wiper (middle) contact...I've tried both ways, does it matter? And then I connect everything up just as the schematic shows, and I double checked the LM386 datasheet against it and it seems it should work

When I hook everything up and just run my simple print val program I get very random numbers, mostly around 500 or so, some up to the 800s, then down to the 200s...but mostly 500s. Turning the pots does nothing for the readings and clapping over the mic or other noises does not raise the numbers...they just seem to go about on their own randomly. I've been plugging and unplugging wires and components to my frustration with seemingly no seems like a fairly simple thing to do and its got my number!
Is there an obvious thing I'm missing? Any ideas?

I can't see how the LM386 can work with the electret mic. Its gain is limited to 200 and the mic's output is only around 500micro-V.

In my applications I use a LM358 op-amp with a gain of 1000 in order to bring the voltage up to about 500mV, then feed to to the Arduino with Aref set to INTERNAL (1.1v).

Yes not enough gain.

The data sheet shows a 10uF capacitor in the feedback of the op amp and you have 0.1uF so I think you are only getting a gain of about 20 anyway. A gain of 200 is not enough but you might have to change the configuration if you use a normal op amp because you have no negative feedback with this design (it's all in the LM386).

So trying to learn by fire here I read what I could and it seems I want a non-inverting op-amp? Going off of the LM358 and shooting for a 1000 gain and using their formula from their datasheet, page 11 I'd need a 1M resistor for R2 and 1K for R1? Gain=1+R2/R1.

And I adjusted my schematic a little bit to show it how I thought it should be laid out...granted I'm just shooting in the dark here.

I couldn't find any examples where they used any caps or anything on the input or output lines, and the datasheet doesn't show any either. QuantSuff is this similar to how you've used them successfully before?

Thanks guys.

You've got the right idea here, but a few key points to get good performance...

The adjustable 10k is used to bias the electret, simply select a value to allow 1mA through - here a 4.7k would be ideal.

Remove the 100k pot as well, with only 500uV at this stage, it's just adding unneeded noise. Any volume adjustment can be done in software or on the output side, when you add your speaker amp.

You should not use the electret's bias for the op-amp, so (1) route the mic's output through a 1uF to the 1K before the (-) input of the amp. The Electret has an internal impedence of around 1.5k, so you're right in the ball park here. You may want to bypass the 1Meg with a 10nF so you don't get HF feedback.

And (2) set up a virtual-ground bias for the op-amp by putting two 10k in series from +V to Gnd, then connect the center point to (+).

The output is now at around 2.5v so you have to isolate it before connecting to the Arduino. Put a .1uF in series here and terminate it to Ground with a 1M resistor.

With Aref at 1.1v, and some programming, you'll be able to get a 25db dynamic range.

Put a .1uF in series here and terminate it to Ground with a 1M resistor.

Problem with that is that you will get negative voltages on the analogue input pin of the Arduino unless you also have a clamping diode to earth.

Normally I'd suggest a clamping diode here too, but since we're dealing with only half a volt of undershoot, it's not really needed.

Ok so I searched and read a bit here and some info sunk in, some not so much...but we're headed in the right direction it seems. It seems as if pretty much all examples I come across use an input from a line and not a speaker, or if they do use a speaker it doesn't show how to connect it. So as a result I'm just guessing on you hook the (+) of the speaker to pin 3 (+) of the LM358. But anyways here's what I have so far...take a look I'm hoping it's getting close! :smiley:

You should not use the electret's bias for the op-amp, so (1) route the mic's output through a 1uF to the 1K before the (-) input of the amp.

I'm sorry I don't understand what you're talking about here. And I was unable to figure it out by looking at any of the schematics I was able to find elsewhere. Could you explain more?

Good job! Your circuit should work now.

You can also switch the 1k from Ground and use THAT for the input. That gives you a slightly better impedence match at the cost of an inverted signal.

Here's a picture of my Electret Candle project:

I'd like to take a look at your picture however it's not coming through on my end. Could be a problem with my computer but when I check the link to it it doesn't seem that it's hosted on the web somewhere else so that you can link to it in your message text. I put my images on photobucket and then link from you have your own site?

The picture's here:

Looks a lot more impressive on the original with full size LEDs!

but since we're dealing with only half a volt of undershoot,

Not sure where you get half a volt from. If a signal at one end of a capacitor can go from 0 to 5V the the voltage at the other end of a capacitor can go from -5 to +5 volts (that's how voltage doublers work), so by my recogning you could get a maximum of -5V undershoot.

When you say:-

I don't understand what you're talking about here.

That issue is addressed in you last circuit. The bias (that means DC level) for the input comes from R2 and R3. Where as the bias current for the microphone comes from R1.
In your first circuit the 10K pot was the source of bias current for the microphone and the op amp (through 100K to the op amp).

that's how voltage doublers work

You must be thinking of another circuit.

You must be thinking of another circuit.


Ok thanks for your help guys but I'm obviously missing something on my end here as it's not working despite reading some more and triple checking everything. So here's a picture of my set-up and the simple code I'm trying to just get it going with. And I'm sorry that my breadboard isn't as neat as some guys's are but I've labeled a number of things that can be used as a reference with the schematic.

int soundPin = 16;    // select the input pin 
int ledPin = 13;   // select the pin for the LED
int val = 0;       // variable to store the value coming from the sensor
int amp = 0;

void setup() {
  pinMode(ledPin, OUTPUT);  // declare the ledPin as an OUTPUT
  pinMode(soundPin, INPUT);

void loop() {
  val = analogRead(soundPin);    // read the value from the sensor
  amp = (val >= 512) ? val - 512 : 512 - val; 
  if (amp > 100) {   
    digitalWrite(ledPin, HIGH);   
  else {   
    digitalWrite(ledPin, LOW);   
  Serial.print("Val = ");
  Serial.print("Amp = ");

You can ignore the resistors and yellow wires in the bottom left, they're for later on and not used currently. So I have 5v coming from the Arduino supply, into the rail and then through R1 to the positive of the Mic. The Negative of the Mic is connected to the GND rail. The orange wire is plugged into the same row as the Mic positive and connects to C1. The other end of C1 is in the row below with R2 & R3, one end of R2 is plugged into the positive and R3 into the negative rail. Now that I look at it again the black wire inbetween R2 & R3 really isn't needed but it connects to the orange wire which goes all the way over to the left to pin 3 on the LM358. Pin 8 of the LM358 is connected to the +5v rail and pin 4 is connected to the GND rail. The yellow wire coming out of pin 1 gets split two ways. One way it heads via the black wire which goes through R5 and then to pin 2 via the longer yellow wire, and also to the GND rail through R4. Now back to the output from pin 1, the other route it takes is through the orange wire and into C3. On the other end of C3 a row lower it connects to the GND rail via R6 and also goes through the black wire to the row with the diode plugged into the GND rail. And lastly from that row the blue wire just visible goes into analog pin #2 (or pin 16 overall if I can count) of the Arduino. Hope that made sense!

I'm getting readings in the 650s for val with no changes really based on music or clapping above it. I've got it set to INTERNAL analog reference so that shouldn't be the problem. If I move the input wire going into and out of other pins the readings will change or even go to zero. But it doesn't seem as if my mic is being allowed to work and since the code I'm using seems pretty simple I thought I must have buggered up the connections somewhere.

Any thoughts?

You have an isolating capacitor (C3) , so the input should not be at 600. In fact, you should only be seeing the top (positive) half of the input signal.

Test your connection with the following code. Alternately, connect a 10K pot between + and gnd and feed the wipe directly into the mic pin. The LED should blink based on the input voltage.

Not that it would matter in the long run, but the Atmel docs suggest discarding the first reading from the analog pin, particularly after changing the Reference.

void loop() {
  val = analogRead(soundPin);    // read the value from the sensor
  if (val>100) {
    digitalWrite(ledPin, HIGH);  

  digitalWrite(ledPin, LOW);  

  Serial.print("Val = ");


I appreciate trying with me here. I've come back to my problem after a sanity break and have tried to find any other faults that could be the problem. I tried to see if my wiring GND was the problem and by trying different jumper ways I don't believe it is.

I tried you test code QS and hooked the wiper of a 10K pot into pin 0 and it read just fine, as one would expect with higher values and lower as you that works. I then for kicks tried putting the wiper into the (+) of the mic and that didn't do anything for my readings. Also tried a variable resistor set-up with the pot connecting (+) to one of the outer contacts of the pot and then connecting the wiper to the mic. I found that it doesn't like the Arduino pins to be declared as pin 14, 15, ect. like some examples show, however calling them pin 0, 1, ect. does work. I get random reading every 3 seconds or so of near 10-14 for val during quiet and with nothing for loud claps. Not sure the rules at work behind this one though but when I touch capacitor C3 with my finger across both leads the val reading will go increasingly higher with the more better contact with the leads. It will go all the way up to 1023 with good finger contact and less with lighter contact. So it is interacting, just not in any way desireable or expected!

The fact that you are taking a single reading means you are not getting an accurate representation of the output. Don't forget that sound waves are constantly going from 0 to max and back to 0. Which means that unless you catch it at exactly the right moment, odds are you are getting a reading other than the peak value.

I've had success with the following routine, which numerically finds the peak and remove the baseline noise. It has a bandwidth of about 5-8kHz, give it a try:

#define samplesize 10
int input[samplesize];

int getInput() {
  int iMin=600;
  int iMax=0;
  int ii=analogRead(micPin);
  for (int i=0;i<=4;i++) {
  inSum+= iMin-input[inIdx]; // Find baseline noise.
  if (inIdx>=samplesize)
  return max(iMax-(inSum/samplesize),0);
  //return iMax>>1;