Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

ADC (audio sampling) and PWM (audio playback)

Status
Not open for further replies.

MrNobody

New Member
I am doing a project to sample voice using PIC ADC at 8khz and then play it out using PIC's PWM as close to real time as possible.. I do not need to store the voice data so I do not need external memory.

The ADC part i think is pretty straight forward, but the playing of audio using PWM part is the one that I am not so sure about..

To start with the basics, lets say I sample a fixed 3KHz frequency signal output from function generator using ADC, i will get a bunch of 8bit data, how do I play these datas out using PWM to generate 3KHz tone using speaker..? I have experience of generating sine wave to drive stepper motor in microstepping mode. Is the principle the same..?

What kind of circuit do I need to play the audio out..? I know I need a low pass filter but apart from that, what else do I need..?
Any pointers or schematics..?

Thanks..
 
I don't think you can do what you want with a PWM at least not over the frequency range of a voice output. Using a PWM into a low pass filter works only for low frequencies. The idea is that the low pass filter will average several cycles of the PWM output. This implies that the PWM frequency needs to be at least an order of magnitude greater than the highest frequency component in the output. I am virtually certain that you will be less than thrilled with the results.

In your example you will use the 8-bit values to change the duty cycle at the same rate that you used to take the samples. One of the problems you will have is what happens when you change the pulse width at a frequency that is asyncronous to the PWM frequency. One of two things will happen, distortion due to partial cycles or delay due to finishing the current cycle before activating the next cycle. And as sure as there are little green apples some golden ear will point this out when he hears it.
 
Last edited:
Hi,
You need LPF even at the input, as well as the level shifter. Besides, many PICs are capable of performing ADC with 10-bit (some 12-bit). Just put the sampled data into the 10-bit hardware PWM, so no data loss. Check **broken link removed** out for the output.
 
bananasiong:
Thanks for the link.

Papabravo:
Since, the sampling frequency at 8KHz is not enough, then what sampling frequency do I need..? The quality i am hoping to achieve is only telephone quality. I suppose that is around 4KHz to 5KHz. That means that my PWM frequency needs to be around 4KHz to 5KHz right..? So, if I desire that output frequency, what frequency should i sample at..?

BTW, I am using 18F4620 running at 40MHz (10MHz crystal with 4X PLL)
 
Last edited:
blueroomelectronics said:
Yeah.. I know Nyquist theorem (Fs = 2 x Fmax).. but since Papabravo said that I can't use PWM output for voice quality, so I asked him how should I go about doing it..

My initial thought was pass the voice signal through at low pass filter with cut off freq of 4KHz, then sample at 8KHz using either 8 or 10 bit.. but it is the PWM part that I am not so sure about.. should I play out the audio using PWM at 4KHz or 8KHz..?

For better sound, I should use 10 bit PWM right..? and that means that I have to sample at 10 bit also right..?
 
Yes, 10-bit output needs 10-bit sample to work without waste. I suppose there are interpolation tricks you might be able to use if you sampled with 8-bits in order to try and restore the extra 2-bits for 10-bit playback in order to save memory at the cost of procesing power.
 
MrNobody said:
Yeah.. I know Nyquist theorem (Fs = 2 x Fmax).. but since Papabravo said that I can't use PWM output for voice quality, so I asked him how should I go about doing it..

My initial thought was pass the voice signal through at low pass filter with cut off freq of 4KHz, then sample at 8KHz using either 8 or 10 bit.. but it is the PWM part that I am not so sure about.. should I play out the audio using PWM at 4KHz or 8KHz..?

For better sound, I should use 10 bit PWM right..? and that means that I have to sample at 10 bit also right..?

No, 8 bit quality would be fine, more than enough for speech, and plenty for reasonable quality music - the Amiga was only 8 bit, and that had VERY acceptable sound. Both A2D and PWM are easily used as 8 bit rather than the full 10, and will save time as well.

Low pass filter (steeply) both input and output at 4KHz, and sample about 10KHz or as high you can get - just bung the 8 bit data directly in the PWM register, with the PWM running as fast as it can.
 
Thanks..

Hmm.. i have some difficulty in extracting the data from datasheet to calculate the A/D Acquisition Time Select Bits..

First difficulty i have is understanding Figure 19-3: Analog Input Model from PIC18F4620 datasheet which is shown below..
Are those things in the dotted box part of the PIC architecture of do I have to build it in my circuit..? I mean, the "Rs" and "V(ain)".. By the way, what is V(ain) anyway..? is it the input signal..?

One of the reason why i am confused is that in the datasheet at page 228, it says "The maximum recommended impedance for analog sources is 2.5k Ohm". I dun really understand if I have to add a 2.5k ohm resistor or the 2.5k Ohm impedance is already part of the PIC..?

I am now reading Equation 19-3 which says that the T(acq) is 2.4us.. how am I going to use that information for ACQT2 - ACQT0..? What are the values in ACQT2 - ACQT0 anyway..? Are they in microsecond..? Forexample, we have "2 T(AD)", "4 T(AD)", "6 T(AD)", etc...

Man.. the more i look at the datasheet for the acquisition time, the more I am lost..
 

Attachments

  • Figure 19-3.jpg
    Figure 19-3.jpg
    44.4 KB · Views: 1,333
Nigel Goodwin said:
No, 8 bit quality would be fine, more than enough for speech, and plenty for reasonable quality music - the Amiga was only 8 bit, and that had VERY acceptable sound. Both A2D and PWM are easily used as 8 bit rather than the full 10, and will save time as well.

Low pass filter (steeply) both input and output at 4KHz, and sample about 10KHz or as high you can get - just bung the 8 bit data directly in the PWM register, with the PWM running as fast as it can.
Thanks.. I understand more.. however, i still am not sure of 1 thing.. Lets say I sampled at 10kHz, when I play out the sound using PWM, do I have to use PWM at 10kHz as well..? Does the PWM frequency have to match the sampling frequency..?

My understanding is that it has no benefit if I run PWM at higher frequency than ADC but if I run PWM at lower frequency than ADC then the quality will drop.. Is my understanding correct..?
 
Nigel Goodwin said:
The higher you run the PWM the more effective the filtering, so it makes sense to run it as fast as you can - but certainly NOT lower than the sampling rate.
Oh.. ok.. thanks...

Umm.. Nigel, can u help me with the A/D acquisition time..? Now I am having a tough time understanding the datasheet and using the information. The part about setting ACQT2, ACQT1, and ACQT0 in PIC18F4620's ADCON2 register..

By the way, I checked ur tutorial for PIC16F877 but i dun think it has the setting for acquisition time..
 
Last edited:
MrNobody said:
Oh.. ok.. thanks...

Umm.. Nigel, can u help me with the A/D acquisition time..? Now I am having a tough time understanding the datasheet and using the information. The part about setting ACQT2, ACQT1, and ACQT0 in PIC18F4620's ADCON2 register..

By the way, I checked ur tutorial for PIC16F877 but i dun think it has the setting for acquisition time..

The acquisition time is complicated, if you're trying for the absolute maximum sampling rate! - but at 10,000 samples per second (100uS per sample) you don't need to get so involved.
 
Nigel Goodwin said:
The acquisition time is complicated, if you're trying for the absolute maximum sampling rate! - but at 10,000 samples per second (100uS per sample) you don't need to get so involved.
Oh.. Umm.. i think i understand what acquisition time is.. Its the minimum time the input signal need to be stable for the accurate sampling to occur (i think)... I just don't know how to use it in PIC..

Umm.. will it still work if I just set the the value to 0..? I mean, the sampled signal will still be accurate right..?
 
By far the most effective thing to do is get a codec chip.

"full quality" voice audio is around 15 bit, 80-3400 hz. Many codecs are voiceband codecs like this and sample at an industry-standard 8khz for voice, but many are also high quality stero (44.1khz/48khz/96khz). Some also have headphone and speaker drivers built-in. You'll generally want to use a dsPIC to interface with them.

Overkill? Well, a simple high quality codec chip may be had for $2. And they are pretty high quality!

There's a LOT of issues that the codec fixes for you. For one, your microphone will capture noise outside the 4khz limit that the 8khz sampling rate can take and that becomes weird aliasing noise you won't be able to get rid of. So you have to build an input filter to prevent this. Your filter will also probably need to be a mic amplifier.
The output PWM you'll need to filter into an analog AC signal and a codec chip does that too. Both the input and output stages are almost always programmable so you can tweak the gain to be what you need.
 
As Nigel says, the higher the PWM frequency the better. With this in mind, I’d like to make a few suggestions.

If you use Tad as 32 Tosc then Tad will be 1.25uS (40MHz) which is well above the minimum of 0.7uS. Your acquisition time will be dependant on your input source impedance but 15uS (12*Tad) is probably a safe value. This will give a total conversion time of 30uS which is equivalent to 33kHz.

For the PWM, setting the prescaller to 1 and PR2 to 0xff will give you a frequency of 39kHz and 10 bit resolution. If you set the postscaller to 2 and use that to synchronise your A2D conversion then everything should run smoothly at a sample rate of 20kHz(ish). You can of course increase the postscaller to reduce your sample rate but keep your output rate the same.

To setup the ADC, you would set ADCON2=0b00101010 and that would automatically take care of the acquisition time. With left justification you can simply transfer ADRESH into CCPR1L and not worry about the 2 lower bits.

HTH.

Mike.
 
Thanks Oznog and Mike

Pommie said:
As Nigel says, the higher the PWM frequency the better. You can of course increase the postscaller to reduce your sample rate but keep your output rate the same.
Umm, when you say keeping keeping my output rate th e same, do u mean that whatever frequency i sampled at, I should played out through PWM using that same sampling frequency or u mean that eventhough I sample at lower frequency, I still play out through PWM at 20KHz..?

Pommie said:
To setup the ADC, you would set ADCON2=0b00101010 and that would automatically take care of the acquisition time. With left justification you can simply transfer ADRESH into CCPR1L and not worry about the 2 lower bits.
If i understand u correctly, i am to sample using 10bit ADC and play out using 10bit but only using the right most 8 bits right..?
 
Last edited:
MrNobody said:
Thanks Oznog and Mike
Umm, when you say keeping keeping my output rate th e same, do u mean that whatever frequency i sampled at, I should played out through PWM using that same sampling frequency or u mean that eventhough I sample at lower frequency, I still play out through PWM at 20KHz..?
Yes, I'm suggesting that you sample at 20K and let the PWM complete 2 pulses at 40kHz. If you change to a postscaler of 4 then you would be sampling at 10k and still playing back at 40k. A postscaler of 16 would reduce your sample rate to 2.5k. This would only be useful if you are sending the data serially or some other such thing.
If i understand u correctly, i am to sample using 10bit ADC and play out using 10bit but only using the left most 8 bits right..?
Correct, you can transfer the other bits as well but it's a little messy.

Mike.
 
Last edited:
MrNobody said:
If i understand u correctly, i am to sample using 10bit ADC and play out using 10bit but only using the right most 8 bits right..?

You can configure the A2D so the top 8 bits are in a single register, for this exact reason.
 
Below is part of the ADC code i found in microchip's TCP/IP stack.. I am trying to understand the reason why the code is written that way..

Code:
    // AN0 should already be set up as an analog input
    ADCON0bits.GO = 1;

    // Wait until A/D conversion is done
    while(ADCON0bits.GO);

    // AD converter errata work around (ex: PIC18F87J10 A2)
    #if !defined(__18F452)
    PRODL = ADCON2;
    ADCON2bits.ADCS0 = 1;
    ADCON2bits.ADCS1 = 1;
    ADCON2 = PRODL;
    #endif

    // Convert 10-bit value into ASCII string
    itoa(*((WORD*)(&ADRESL)), AN0String);
First question i have is regarding the "#if !defined(__18F452)" macro. Why does the code assign ADCON2 to PRODL, and after that make changes to ADCON followed by assigning PRODL back to ADCON2..?
Won't that overwrite the changes made in the middle..?

Second question is, these lines are part of a function that was called everytime the ADC need to sample the signal. Why does the ADC needs to be reinitialized everytime before the sample is taken..? I mean, why not just do it like below..?
Code:
    // Wait until A/D conversion is done
    while(ADCON0bits.GO);

    // Convert 10-bit value into ASCII string
    itoa(*((WORD*)(&ADRESL)), AN0String);

Is there any benefit in reinitializing the ADC before taking the samples..? Even in 18F4620's datasheet on page 227, it ask to reconfigure A/D module everytime before taking the sample (Step 7 which ask to go back to Step 1 or Step 2).
 
Status
Not open for further replies.

New Articles From Microcontroller Tips

Back
Top