Hardware solution to non linearity issues in ADC of PIC 18F4620

Thread Starter

pyridot

Joined Jun 11, 2010
7
Hey ppl!!

I am exploring PIC controllers and trying to figure out how to get rid of the non linearity issues in the ADC of PIC 18F4620.

My set up goes this way....

I am using a supply of 12V nd bringing it down to 4v using a voltage divider circuit. This goes to the non inverting pin of LM324 such that I get the same applied voltage at its output. This is then passed on to the channel 0 (AN0/pin 2) of the PIC. I am displaying this voltage reading onto the LCD. I need to read it correctly upto 3 decimal places.

Though I achieved it considerably through software. I would really like to know if there is a hardware solution to this?

Pls do let me know.

Thanks!
 

t06afre

Joined May 11, 2009
5,934
First of all. I would not recommend using a simple divider for power supply task. In your case I would have used LM317 type voltage regulator. Second your 18F4620 have 10 bit resolution. So resolution will be Vref/(1024). I am quite sure Vref is 4 volt in your case. So your resolution will be about 4 mV. And that is perhaps not good enough in your case. Due to noise ect. I think your resolution will be closer to about 10 mV.
The next time you post, please include a schematic. It will help you to get a more accurate answer quicker
 

beenthere

Joined Apr 20, 2004
15,819
The LM324 opamp is not a precision device. It could be the source of the nonlinear response. A schematic would be useful.
 

Thread Starter

pyridot

Joined Jun 11, 2010
7
Hey guys!!

I shall send you the schematic asap.

The thing is that I need to simulate the noisy industrial environment.

the ADc is 10 bit and Vresolution = 4.887 mV

Software is my strength....Hardware doesnt come that easily to me...i'm learning....thanks for the input guys...will send the schematic soon...pls do help me out.

Thanks again!
 

t06afre

Joined May 11, 2009
5,934
I think I misread your first posting somewhat. So my first advice will not apply very good I think. But anyway this shows the importance of posting a schematic before starting a discussion:)
 

Thread Starter

pyridot

Joined Jun 11, 2010
7
Hey ppl!

Here is the Diagram....didnt have access to proper tools for drawing the circuit so this is just a drawing in paint....Hope this will do for now

The PIC is 18F4620....other details as above

Thanks!
 

Attachments

beenthere

Joined Apr 20, 2004
15,819
You can vary the input from around 6 volts. You have a gain of up to about 2. What is the input limit for the ADC? What voltage/s are on the LM324?

It looks like either the ADC or the LM324 is presented with more voltage than they can handle.
 

Thread Starter

pyridot

Joined Jun 11, 2010
7
Hey!

Should the input voltage limit for the adc be the same as that of the PIC since it is an internal adc?

After the pot divider the voltage is brought down to around 4V. I am getting ≈4.12 V at inv and non inv pins of LM 324 and the output pin is showing ≈4.3V. After the 0.1μF capacitor I am getting ≈4.12V.

Is the third 10KΩ resistor of the pot divider parallel to the 10kΩ resistor next to the 10μF capacitor? should I replace the (1kΩ+10kΩ pot) feedback with a 10K fixed resistor and remove the 100Ω? Should I also add a electrolytic capacitor at the output?

Another solution I thought of was to change the prescaling of ADC...but that would just mean more work for PIC right? something which I dont want to do.

Please do lemme know asap.
 

t06afre

Joined May 11, 2009
5,934
Your circuit will have a minimum gain of 1.1. In order for the ADC to work correct you must also set it up correct. Have you read the data sheet regarding this point. Also which voltage do you use for supply voltage for the LM324 and the PIC. All this is important.
You should also post your code.
 

Thread Starter

pyridot

Joined Jun 11, 2010
7
PIC is 18F4620 at 20Mhz
the PIC Vdd = 5V and 324 is 12V

The program:

#include <built_in.h>

#define BACKLIGHT PORTD.F0
#define ON 1
#define OFF 0

char *cptrText;
long lAdcRead;

void main()
{
long fAdcResult = 0;
short iCount;
char ch;

INTCON = 0x00;
ADCON1 = 0x07;
ADCON2 = 0x05;
TRISA = 0xFF;
TRISD = 0x00;

Lcd_Custom_Config(&PORTD,7,6,5,4,&PORTD,3,2,1);
Lcd_Custom_Cmd(LCD_CURSOR_OFF);
Lcd_Custom_Cmd(LCD_CLEAR);
BACKLIGHT = ON;
delay_ms(1000);

cptrText = " Dummy ";
Lcd_Custom_Out(1,2,cptrText);
cptrText = "Batt Vltg:";
Lcd_Custom_Out(2,1,cptrText);

delay_ms(1000);
while (1)
{
for(iCount= 0; iCount<= 250; iCount++)
{
lAdcRead = ADC_read(0);
delay_ms(2);
fAdcResult += (float)lAdcRead;
}
fAdcResult /= (float)250;

/* if(fAdcResult <= 1.00 && fAdcResult > 0.00)
{
fAdcResult = fAdcResult - (fAdcResult * 0.0065);
}
else if(fAdcResult <= 2.00 && fAdcResult > 1.00)
{
fAdcResult = fAdcResult - (fAdcResult * 0.00065);
}
else if(fAdcResult <= 3.00 && fAdcResult > 2.00)
{
fAdcResult = fAdcResult - (fAdcResult * 0.00035);
}
else if(fAdcResult <= 4.00 && fAdcResult > 3.00)
{
fAdcResult = fAdcResult - (fAdcResult* 0.0004);
}
else
{
fAdcResult = fAdcResult - (fAdcResult * 0.0025);
} */

//adc_rd=adc_rd-(adc_rd*(float)0.035);

lAdcRead = fAdcResult + 0.5;

lAdcRead *= 5000;
lAdcRead /= 1023;

ch = lAdcRead / 1000;
Lcd_Custom_Chr(2,11,48+ch);
Lcd_Custom_Chr_Cp('.');

ch = (lAdcRead / 100) % 10;
Lcd_Custom_Chr_Cp(48+ch);

ch = (lAdcRead / 10) % 10;
Lcd_Custom_Chr_Cp(48+ch);

ch = lAdcRead % 10;
Lcd_Custom_Chr_Cp(48+ch);
Lcd_Custom_Chr_Cp('V');
Delay_ms(500);
}

}
 

Thread Starter

pyridot

Joined Jun 11, 2010
7
Please Ignore the if...else part...thats just software adjustments to the mismatch between adc readings and the lcd display.....this is the part i want to avoid and find a hardware solution to reduce the nonlinearity.

since the supply fluctuates...I am reading the adc ch0 250 times and then taking average value....hence the float.....then I round off this float avg value and assign it to a Long type variable lAdcRead.

Then I convert this lAdcRead to bring in the range 0 to 5 volts

eg: after 250 reads of the adc, fAdcRead = 818.4 (≈4V)

lAdcRead = fAdcRead +0.5 = 818.4 +0.5 = 818.9
lAdcRead = 818 ......truncation from float assigned to integer

(818*5000)/1023 = 3998.044

then i extract digit by digit and send to lcd.

Hope I didnt confuse you further :)
 

beenthere

Joined Apr 20, 2004
15,819
Should the input voltage limit for the adc be the same as that of the PIC since it is an internal adc?
Doesn't the data sheet indicate that?

You have a setup which can present the ADC input with some voltage ranging from over 4 volts to well above the ADC input maximum. The (power?) "supply" is noisy, so you are taking 250 readings and doing an average.

That prompts some questions. Why have you gone immediately to some simulation of a "noisy industrial" environment? Why is the input limited to only voltages above 4? Is it the power source for the LM324 that is noisy? What part of the limited range of voltage input to the ADC that shows non-linearity? Wouldn't you want to investigate proper response at first without the noise?
 
Top