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..
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?
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?
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?
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
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?
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.
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 ?
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!!
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.