audio on a PIC

Status
Not open for further replies.

toozie

New Member
Hello all. I have been working on an audio project with a PIC 16F877A, but it dawned on my today that I didn't think far enough ahead. I have a small mic that I am putting through a little audio amp, and that appears to work fine. My question is, how do I take the audio output (from the amp) and put it into the ADC? I know how to work the ADC, but the amp output is a voltage that centers around 0Vdc, so 1/2 the time it is a negative voltage (which I don't think I can put through the PIC's ADC). Can I add a DC couple to it to make the voltage center around some positive voltage (say 2.5Vdc)? There is probably a simple solution, but I haven't been able to come up with anything yet.

Thanks!
 
I assume the output of you audio amplifier is AC coupled. There is a capacitor on the output.

Add a 10k resistor from +5 volts to the output of the amplifier.
Add a 10k resistor from ground to the output of the amplifier.
Now the signal will be centered around 5/2 volts or 2.5 volts.
 
Thanks Ron for the quick response! I am using the LMV722 from National which has a 4.7uF cap to block out a DC voltage offset (pdf drawing).

OK, I kind of wondered if I could introduce a DC offset into the line that way. If I were to play the audio file that is created by the PIC (using the mic, amp, and offset), it would sound wacky because of the 2.5V increase, so I need to subtract it off of each sample right (storing the value into a signed variable)?

Thanks again! My CompEng background just didn't get into enough analog for me to feel real comfortable.

~J
 
Hi,
Is 5 k going to be a little high? <2.5 k is recommended in the datasheet. Make the source impedance to be as less as possible since you're dealing with the audio.
Or you can shift it up before an op amp, the output impedance of the op amp is low enough to minimize the charging time.
 
Bananasiong,

I think the impedance will be 100 ohms or that ever the output of the preamp is.
The DC resistance is 5k. The AC impedance will be low.
So the question is will the ADC work correctly in this manner. I think it will.
 
Thank you both. I will give it a try today and report back.

Or you can shift it up before an op amp, the output impedance of the op amp is low enough to minimize the charging time.
If I do that, won't the coupling cap on the output of the amp kill the DC voltage (so when there is no noise, the input of the ADC will see 0V, which in my software I will then unknowingly reduce down 2.5V to compensate for the offset and throw off the signal?

I plan on adding a 5th Order Butterworth filter (probably the **broken link removed**) to clean things up at some point. I assume that I would want to go: mic -> filter -> amp -> introduce DC couple -> the PIC's ADC. Does that sound about right?

~Jason
 
Last edited:
Toozie,

You asked about adding 2.5 volts to the ADC input.

Top line is input voltage to the ADC.
Second line is the reading of the ADC. (4 bit)
The third line is when you add 1000. (in 8 bit add 1000,0000)

0 volts…2.5 volts…5 volts
0000…..0111,1000…1111
1000…..1111,0000…0111

The third line should be audio compatible.
 

I think you're vastly over complicating it?.

You're inventing signed variables for no good reason, the second line is all you need, and is far simpler both for A2D and D2A.
 
I appreciate everyone's help and I think I am starting to make some progress.

Once of the reasons that I asked about subtracting off the DC voltage is because I am trying to work around one of Microchip's app notes (**broken link removed**) and their simplified ADPCM encoder/decoder (I am working on the encoder first) which requires a signed 16bit 2's complement of the sample to be passed into their encoder.

I have introduced the 2.5V to the amp output, and am reading the ADC correctly (when there is no noise I read 0x200 in 10bit mode), but that is where my confidence ends.

what doesn't seem to be working for me is:
signed short temp
//using 10bit right justified ADC
temp = (((signed short)(ADRESH))<<8) + ((signed short)(ADRESL))
temp -= 0x200

but that seems to hose things up a bit. Anyone see where I am going wrong?

thanks again
~J
 
Hi,
I'm still not very 'C' , can I know what does this mean?
Code:
temp = (((signed short)(ADRESH))<<8) + ((signed short)(ADRESL))
 
toozie said:
what doesn't seem to be working for me is:
signed short temp
//using 10bit right justified ADC
temp = (((signed short)(ADRESH))<<8) + ((signed short)(ADRESL))
temp -= 0x200

I think what you need is,
temp = (signed short) ((ADRESH<<8) + ADRESL)
Assuming signed short is 16 bit.

Mike.
 
I think what you need is,
temp = (signed short) ((ADRESH<<8) + ADRESL)
Assuming signed short is 16 bit.
Thanks Pommie, I actually end up with:
Code:
temp = (((int)(ADRESH))<<8) + (int)(ADRESL)
Which is think is overkills on the typecasting, but at the time I was desperate. This seems to work and I will try to simplify it to what you had as well (as an aside: a short and int (which are both signed) are indeed 16bits in this system).

bananasiong:
What I was doing is called typecasting. Essentially, you get the complier to change the type of variable (in our case a 8 bit [both ADRESH and ADRESL are]) to something else. Since I ended up wanting a 16 bit signed number (a signed int), I needed to make sure that the compiler did not do 8 bit math with the two numbers I was manipulating (ADRESH and ADRESL) and place it into my 16 bit variable. So by changing "ADRESH" in the equation to "(int)(ADRESH)", the compiler treats it like a 16 bit variable, otherwise, it would chop off those bits I was shifting to the left 8 times.

I know that is probably hard to read, but I promise that it isn't a difficult concept and that someone else could probably write it more eloquently than I.

~J
 
Doesn't a PIC C compiler allow you to directly read the A2D as a single 16 bit variable?, from what's going on here it's more complicated and difficult than doing it in assembler?.
 
Nigel Goodwin said:
Doesn't a PIC C compiler allow you to directly read the A2D as a single 16 bit variable?, from what's going on here it's more complicated and difficult than doing it in assembler?.
Not that I have found. If you know a way of doing it, I would love to hear it, otherwise I have to take the two 8 bit registers (one of which is padded with 6 0s), and concatenate them.

~J
 
What's the sample rate of the ADC?

You need an anti-aliasing filter to cut the high frequencies at half the sample rate so you don't get a distorted signal.
 
What's the sample rate of the ADC?

You need an anti-aliasing filter to cut the high frequencies at half the sample rate so you don't get a distorted signal.

I am sampling at 8kHz and putting it through a 5th order Butterworth filter with a corner freq set so that at 4kHz I am 40dB down. I assume that that will be enough, but I am not much of an analog person.

~J
 
Last edited:
Status
Not open for further replies.
Cookies are required to use this site. You must accept them to continue using the site. Learn more…