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.

My PICs AD Converter is not very acure...

Status
Not open for further replies.

Jay.slovak

Active Member
I have one small problem with my PIC18LF4320's AD Converter. I have calculated all necessary conversion times, But its not working OK. The source of the voltage is a Power supply (That's my school Project) and the AD input is Buffered with OPamp (Datasheet says that source impedance SHOULD NOT be grater that 2.5K). When I AD convert for example 50 values in 1mS intervals of the same Pin, and make an average value of them, it gives me the value that should be there.
Here's the Code:
Code:
AD1
   MOVLW	b'00000100'	;Channel 1
	MOVWF	ADCON0
	GOTO	INITAD

INITAD
	MOVLW	b'00010110'	;Tad=3.2Ms, Tacq=12.86Ms Fosc=20MHz
	MOVWF	ADCON2	;Timeing requirements
	BSF	ADCON0,0	;Turn on AD
	NOP
	BSF	ADCON0,GO	;Begin AD Conv.
	BTFSC	ADCON0,GO	;Done?
	GOTO	$-2	;No, Wait...
	MOVF	ADRESH,w	;Yes, Value is in W
	RETURN

Is there any way I can improve acurancy or is there a Mathematical Routine to make any average of 16 Ad values?
Help appreceated...
 
You must wait the Tacq AFTER turning on the ADC before you set GO. The hardware does not do this for you, you need to use one of the timers or wait in a loop.
You're turning on the ADC and then setting GO without any ack time.
 
But I'm using PIC18F's AD converter which has "Automatic Aquistion Time" feature. I set Tad and Tacq in ADCON2, and I can set ADON and /GO bit without any time loop. Hardware does this instead me..
 
Now I put 20 mikroS between the ADON and the /GO and the result is this:

... 031 030 032 032 029 030 033 031 030 028 ...
It should be 030, If you put it into Excel it works out excelent!
 
i find taking a bunch of samples and averaging them works good. Also what input rsistor,cap combo are you using?. I usually try 1uf and a 1k resistor.
 
What do you have supplying power to the PIC? Unless you set it up differently, Vdd is the reference voltage so any noise on it will affect the ADC readings.

Make sure you have proper caps on both sides of the reg, and a ceramic bypass cap right at the PIC's power pin.
 
This is a part of my scheme. I do not have any high speed logic in the circuit. The PIC is running at 20Mhz, AD's voltage reference is VDD and VSS. I found out, that if I bypass the OPamp, the result is the same... Do you have any routine that can take 16 samples and average them?
 

Attachments

  • piczdroj.gif
    piczdroj.gif
    4.5 KB · Views: 1,172
Jay.slovak said:
This is a part of my scheme. I do not have any high speed logic in the circuit. The PIC is running at 20Mhz, AD's voltage reference is VDD and VSS. I found out, that if I bypass the OPamp, the result is the same... Do you have any routine that can take 16 samples and average them?

Just add them all together (they will fit in a two byte 16 bit variable), then divide by 16 (you can do this by simply shifting left four times).
 
OK, I will try the Averaging Routine...
Do you have an example written in Asembly? The only way, I know how to make a Sum of 8 bit values into two 8 bit registers is to add two 8 bit values and then test if it overflowed, if so increment upper 8 bit register and so.... am I right?
 
Jay.slovak said:
OK, I will try the Averaging Routine...
Do you have an example written in Asembly? The only way, I know how to make a Sum of 8 bit values into two 8 bit registers is to add two 8 bit values and then test if it overflowed, if so increment upper 8 bit register and so.... am I right?

The results from the A2D are 10 bit, you may as well use the 10 bit precision - eight 10 bit numbers added together will fit easily in 16 bits.

Here's a 16 bit ADD routine I use, it adds Acc2 to Acc1, leaving the result in Acc1 - there's also a flag which is set (Flags, Overflow), if it overflows the 16 bit value.

Code:
_Add16     BCF    Flags, OverFlow ; clear overflow flag
	MOVF   Acc2L, w          ; Add the LSBs. If carry,
	ADDWF  Acc1L
	BTFSC  STATUS, C       ; increment MSB of sum.
	INCF   Acc1H
	MOVF   Acc2H, w          ; Add the MSBs
	ADDWF  Acc1H 
	BTFSC  STATUS, C       ; check for sum overflow
	BSF    Flags, OverFlow  ; set overflow flag
	RETURN
 
Succes!

Thanks Nigel,
So i will just add 16 8-bit samples together and shift left 4 times do divide it.
Just one question: Datasheet says that maximum non-linearity error is 1/2LSB, how come it so freakin' weird, Even if I use 8 out of 10 bits of the AD?
 
Re: Succes!

Jay.slovak said:
Thanks Nigel,
So i will just add 16 8-bit samples together and shift left 4 times do divide it.
Just one question: Datasheet says that maximum non-linearity error is 1/2LSB, how come it so freakin' weird, Even if I use 8 out of 10 bits of the AD?

It's quite likely the input is varying, also using Vdd as the positive reference isn't a very good reference source - I use a 2.5V precision reference in my tutorials.

Don't forget, even only using 8 bits, you're trying to achieve better than 0.5%.

Using Vdd as reference, and a simple pot from Vdd to Vss feeding the input, the 10 bit analogue values are quite stable.
 
Re: Succes!

Jay.slovak said:
Thanks Nigel,
So i will just add 16 8-bit samples together and shift left 4 times do divide it.
Just one question: Datasheet says that maximum non-linearity error is 1/2LSB, how come it so freakin' weird, Even if I use 8 out of 10 bits of the AD?

Actually to be anal about proper rounding, you'd add 8 before shifting.

I am unsure what your problem is. What is the span from highest to lowest code in its reading of a fixed voltage?

What is the power source for the sensor? If it's a resistive element, you always want to tie it to the same Vdd the PIC uses. That way, any error in the reg's output won't matter at all. And most of the noise is also filtered out.

What you describe is noise, not offset, scale, or linearity error. Don't know what the source would be here. You sure you didn't accidentally select an external Vref?

Did you add a ceramic bypass cap (0.1uF is good) at the PIC's power itself?
 
So the Project I'm building is a Power Supply controlled by PIC, with range from 1.5V to 25.5 V and max current is 5A. The voltage divider will divide the voltage by 5.1 so: 25.5 / 5.1 = 5V = 255d, therefore 1 bit = 0.1V.The AD conversion of this Value must be as acurate as possible, even a change in 1 bit LSB will change measured voltage by 0.1 and that is not acceptable. I'm sure that I'm using VDD and VSS as a reference, but I might try using external reference as well. I'm using LF version of the PIC, I hope that is not the problem.

The project is currently in Beta stage, the 5V supply is about 30cm away from the PIC and there might be a lot of noise from my PC & Speakers... Every IC has it's own 0.1uF Capacitor. The Final project is gonna be on a single board, with lots of shelding and the 5V supply will be right next to the PIC. Do you think that's my problem ?

This is how it looks like:
 

Attachments

  • dsc00953.jpg
    dsc00953.jpg
    120 KB · Views: 1,083
Well certainly having massive lengths of wire everywhere isn't going to help anything - I would have thought you're likely to be picking up huge amounts of interference.
 
Looking at your schematic i would suggest a 1k input resistor and a 10uf
cap to buffer the input signal. by the way at 16 bits you can take apx 60 samples and divide by 60 for very very smooth results!!


60 * 1023 =61380
 
I think that the Opamp I'm using to buffer is better than rezistor + cappacitor.
Taking 60 samples will average it *realy* nice... But I think 16 is enaugh.
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top