Problem: ADC with microphone input (PIC18F4550)

Thread Starter

DrStu

Joined Dec 11, 2008
6
uC - PIC18F4550 (Compiler: MPLAB MC18)

I'm trying to build a simple circuit using the built in ADC of the PIC to convert the analog values from an electret microphone.

Objective:
- Light up an LED if the sound amplitude is above a certain level

Brief Block Diagram:
Mic -----> Amplifier -----> PIC

Problem:
So far i've not been able to make the PIC work with the mic. Unsure whether the problem is in the amplifier stage or the coding of the ADC. Btw, i've tested the ADC using DC voltage and it works fine. (LED lights when ADC connected to +5V DC and vice versa). It just wouldn't work with the mic.

Circuit Used:
http://www.josepino.com/circuits/?mini_amplifier_lm386.jpc
(Using the general purpose amplifier from this site)

Rich (BB code):
#include <p18cxxx.h>
#include <adc.h>

//Global Variables
int ADC_Output=0;

#pragma config FOSC = HS
#pragma config WDT = OFF /* Turn the watchdog timer off */
#pragma config LVP = OFF /* Turns Low Voltage Programming off */
#pragma config MCLRE = ON /* To enable MCLR - To enable PIC reset */

void main()
{

    TRISA = 0xFF;

    TRISC = 0x00; /*Configure Port C as All Output*/
    LATC = 0x00;

    // configure A/D convertor
    OpenADC( ADC_FOSC_16     &
         ADC_RIGHT_JUST &
         ADC_12_TAD,
         ADC_CH0     &
         ADC_INT_OFF ,
         ADC_VREFPLUS_VDD);

    while (1)
    {
        ConvertADC(); // Start conversion
        while( BusyADC() ); // Wait for completion
        ADC_Output = ReadADC(); // Read result
        if (ADC_Output>512){
            LATC=0b11111111;
        }
        else {
            LATC=0b00000000;
        }
    }
}
Any help would be much appreciated. I'm not very familiar with audio signals (as in mic and the amplifier stage). Thx! ....Very Very Much!
 

mik3

Joined Feb 4, 2008
4,843
You need to use a peak detector after the amplifier as to store the highest value of the DC varying signal of the voice (microphone). Another way, is to make your program to turn on the led once it senses the voltage over the limit for one instance and leave it on until you press a reset button.
Now, your circuit turns on the led just for a tiny time interval (time the voltage goes above the limit) and you can't see it. Thus, make the changes mentioned earlier.
 

Thread Starter

DrStu

Joined Dec 11, 2008
6
gee thx! i think i get da point.... i think i didnt get it that the output was in AC all da while :)P ...no oscciloscope at home to observe it)

anyway, is it possible to rectify the problem inside the pic coding instead of building a peak detector/rectifier? like...getting the difference between the instantaneous value and the center reference value....and use the average of like 20 of these values...or sth like that?
 

Thread Starter

DrStu

Joined Dec 11, 2008
6
sth i would like to know about the ADC configuration bits of the ADC...

wad "A/D Acquisition Time" and "A/D Conversion Clock"is best for audio sampling? (dat best suits my project)
 

beenthere

Joined Apr 20, 2004
15,819
That decision is yours to make. If you wish to go for voice only, the highest frequency needs to be only 6 KHz or so. Nyquist strongly suggests sampling at twice the rate of the signal, so something like 12 KHz, or every 83 us.

Full audio pushes the upper limit to around 20 KHz, or every 50 us. The industry uses 22.5 KHz.

Your A to D is going to output 10 bits/conversion, which is not really going to give good fidelity on playback. 16 bits is pretty much the minimum for that.
 

mik3

Joined Feb 4, 2008
4,843
gee thx! i think i get da point.... i think i didnt get it that the output was in AC all da while :)P ...no oscciloscope at home to observe it)

anyway, is it possible to rectify the problem inside the pic coding instead of building a peak detector/rectifier? like...getting the difference between the instantaneous value and the center reference value....and use the average of like 20 of these values...or sth like that?
You can do it by programming but you have to ensure the voltage on the adc input does not go negative (clamp it). To do it, you have to compare the read value from the adc with the next value and if it is greater then you continou to read the values. However, if it is less than the current value you keep the current value as the peak value. Then you start the same process again.
 

Thread Starter

DrStu

Joined Dec 11, 2008
6
That decision is yours to make. If you wish to go for voice only, the highest frequency needs to be only 6 KHz or so. Nyquist strongly suggests sampling at twice the rate of the signal, so something like 12 KHz, or every 83 us.

Full audio pushes the upper limit to around 20 KHz, or every 50 us. The industry uses 22.5 KHz.
thx beenthere :) ...i do understand wad uve said about the sampling frequency thing.....but what i dun get is actually the "A/D Acquisition Time" and "A/D Conversion Clock" ......i've read through the datasheet for the PIC18F4550 and was very confused about how to configure these 2..... what i understand is u can calculate the conversion time (and thus the conversion frequency) through these 2 parameters.....and also that the "acquisition time" must be long enuf to charge up the capacitor of the sample and hold circuit of the a/d......

or simply...i juz dun get da whole picture of it :) ....say i would like to sample at 40kHz.....how do i calculate the ideal "A/D Acquisition Time" and "A/D Conversion Clock" if im running my PIC at 20MHz?

Your A to D is going to output 10 bits/conversion, which is not really going to give good fidelity on playback. 16 bits is pretty much the minimum for that.
i'm not actually trying to record and playback audio....juz trying to show the sound level by lighting up LEDs (i know theres a specific IC for this...but this is juz a part of my PIC project) ..thx!
 

Thread Starter

DrStu

Joined Dec 11, 2008
6
You can do it by programming but you have to ensure the voltage on the adc input does not go negative (clamp it).
yea...as i am using the LM386 audio amplifier...the output is already biased to 1/2 of the supply voltage (2.5V in my case) ...so my adc input does not go below 0V

To do it, you have to compare the read value from the adc with the next value and if it is greater then you continou to read the values. However, if it is less than the current value you keep the current value as the peak value. Then you start the same process again.
so the way i understand it....this is the "Software Peak Detector" right?

Currently i'm trying out "software averaging" ...and yet the output is not wad i expect (its reading a constant 5V) ....any ideas? ...
this is my ADC coding:
Rich (BB code):
OpenADC( ADC_FOSC_2 	& 
		 ADC_RIGHT_JUST &
		 ADC_8_TAD,
		 ADC_CH0 		& 
		 ADC_INT_OFF ,
		 ADC_VREFPLUS_VDD);

while (1)
{
	int i;
	Sum=0;

	LATC=0b00000000;

	for (i=0; i<10; i++){ 
		Delay10TCYx( 5 ); // Delay for 50TCY
		ConvertADC(); // Start conversion
		while( BusyADC() ); // Wait for completion
		ADC_Output = ReadADC(); // Read result

		if (ADC_Output>512+100){
			ADC_Output=ADC_Output-512-100;
			//LATCbits.LATC0 = 1;
		}
		else if (ADC_Output<512-100){
			ADC_Output=512-ADC_Output-100;
			//LATCbits.LATC1 = 1;
		}
		else{
			ADC_Output=0;
			//LATCbits.LATC1 = 1;
		}

		Sum=Sum+ADC_Output;

		Delay1KTCYx( 5 ); // Delay for 1ms
	}
	
	Sum=Sum/10;

		if (Sum<100){
			LATCbits.LATC0 = 1;
			Delay10KTCYx( 500 );
		}
		else if (Sum <250) {
			LATCbits.LATC1 = 1;
			Delay10KTCYx( 500 );
		}
		else{
			LATCbits.LATC2 =1;
			Delay10KTCYx( 500 );
		}
	}
ath wrong with my coding part? any help VERY MUCH appreaciated :)
 

mik3

Joined Feb 4, 2008
4,843
You don't need any averaging code. Just read the input and when the voltage goes above a certain limit the PIC will perform the appropriate function.
 

beenthere

Joined Apr 20, 2004
15,819
By just determining the volume peaks, you also don't need to worry about the sampling rate. That is only necessary for accurate reproduction.

Get the apparatus working and then you can experiment with sampling rate to see what is actually necessary.
 
Top