Audio input

I'm looking to use a small electret mike for an input, just for general purposes. I'm wondering exactly how to go about doing this; would it be better to use a high sample rate and external amplifier, or use a lower sample rate and external integrator? Eventually I want to use the TVout library to display a scope, and possibly the FFT as well. I have currently available an LM324 quad op amp, and two 555s, and a plethora of standard components such as transistors, diodes, caps, etc., and would prefer not to have to get anything else if it can be avoided.

EDIT: I also have a large breadboard, and an arduino uno r3.

I'm wondering exactly how to go about doing this; would it be better to use a high sample rate and external amplifier, or use a lower sample rate and external integrator?

It depends on your requirements... I'm not sure you need an integrator or amplifier at all. You may need an external analog-to-digital converter if you need a higher sample-rate and/or more bit depth.

The built-in ADC is 10 bits (0-1023), and I read somewhere (not confirmed) that the maximum sample rate is ~10kHz. With a 10kHz sample rate, your signal can only go up to 5kHz (Nyquist theory). As you may know, CDs have a sample rate of 44.1KHz to cover the "full audio range" beyond 20kHz, with 16-bits of resolution.

Real digital oscillosopes have a sample rate of about 10 times their rated frequency/bandwidth.

As far as processing the data (FFT, etc.) I don't have a good feel for the Arduino's speed. Hopefully, someone will jump-in with some input... Something tells me that would be another bottleneck.

A 'scope doesn't have to do that much processing, and your eyes/brain can only process rather slowly, so I don't think a 'scope would be a problem once you get past the input/sampling limitations. And, you don't need much resolution for a 'scope, as long as you can change the range/scale. The Tektronix 'scope on my bench only has 8-bits of vertical resolution, which is about half the resolution of a DVD, and plenty for a 5-inch screen.

P.S.
If you want to make a 7-band spectrum analyzer, there is [u]nifty analog chip[/u] that makes it easy with 7 filtered-outputs for you to run into 7 Arduino analog inputs, and you only have to "process" the amplitude for each channel at a fairly-slow "visual" rate.

would it be better to use a high sample rate and external amplifier, or use a lower sample rate and external integrator?

The question isn't correct, as sampling rate has nothing to do with amplifier, and BTW, what is "external integrator"?
You will need amplifier for electret mic, LM324 should be O'K, I've seen a lot on-line resources with amplifier build on this chip.
Sampling rate depends on your objective max freq. input signal. You can sample with arduino up to 150 kHz,

Never mind, I got it worked out using this circuit with some slight modifications (100nF cap instead of 2.2uF, 2N4401 instead of BC550C): Electret Microphone & Preamplifier .

I have another problem now though; my signal is very small (I suppose I could replace the transistor with a darlington pair though, right?) and more importantly it's offset by rather too much. How would I add a potentiometer to that circuit to allow me to adjust the offset?

(100nF cap instead of 2.2u

Bad idea, if you have electrolitic caps, put higher value 10, 100 uF

I could replace the transistor with a darlington pair though, right?

Yes, you could stuck 2 - 3 of them

How would I add a potentiometer to that circuit to allow me to adjust the offset?

Instead of 2M2. If you gonna to change to darlington, you will have likely increase its value as well.

I wasn't sure about how to do an electrolytic there; I don't think it'd be polarized correctly either way.

I would change the 2M2 for a pot, but I only have two 100K pots to use... I'd rather not have to go get one.
Besides, wouldn't that adjust the amplification, not the offset? Or am I mixing up transistor amps and op amps?

I don't think it'd be polarized correctly either way.

Voltage at the base should be lower, ~3V at the mic and 0.7 on base.

wouldn't that adjust the amplification, not the offset?

Actually it would affect both, amplification and offset. To get more gain, you better split 2M2 in two resistors, or const. resistor and pot, than connect one more elect cap between middle point and ground, to cancel NFB

So even though the electret is AC it'll still work? Alright.
And I actually currently have two 1M resistors there instead of 2M2; I didn't have a 2M2 resistor. I'll try the cap; you recommend any particular capacitance?

So even though the electret is AC it'll still work?

electret is not AC, rather modulated DC.

I'll try the cap; you recommend any particular capacitance?

C = 1/ ( 2 x PI x R x f ), where PI = 3,14; R = 1M; f = 20 Hz
C = 0.007957747 uF, 10 nF should be o'k.

I think it's mostly working now, but the problem is it doesn't display correctly. Here's the code:

#include <font6x8.h>

#include <TVout.h>
#include <video_gen.h>

TVout tv;

void setup()
{
  tv.begin(NTSC, 120, 96);
  tv.select_font(font6x8);
}

void loop()
{
  tv.fill(BLACK);
  for(int x = 0; x < tv.hres(); x ++) {
    tv.set_pixel(x, int(analogRead(5) * (tv.vres() / 2) / 1023), WHITE);
  }
  tv.delay_frame(1);
}

The problem is that it only displays scattered dots, with usually over half the columns empty. Do you see anything that could be causing this?

I don't have experience with TVout , just guessing resolution set to 120x96 . If so, there is potentially overflow in this line

analogRead(5) * (tv.vres() / 2)

maximum analog read could return 1023, multiplying 96/2=48 getting 49104, which is above the upper limit signed integer .

Could I fix that by storing the values in an unsigned int? Or is there a simpler way?

Yes, I'd say it should fix it. Probably, you can cast int returned by analogRead to unsigned int before multiplying.

tv.set_pixel(x, int(((unsigned int)analogRead(5)) * (tv.vres() / 2) / 1023), WHITE);

.
Having bad experience with overflow in multiplication before, I'd play safe, and cast to long, than replace both division by shifting to get back a speed:

tv.set_pixel(x, int((((long)analogRead(5)) * (tv.vres() >>1 )) >>10), WHITE);

NOT tested.

Excellent, that worked perfectly! Now to try to get an FFT working... That won't be so easy.