|
|
View previous topic :: View next topic |
Author |
Message |
Guest
|
A/D converter performance..... |
Posted: Tue Apr 21, 2009 9:46 pm |
|
|
Hi All,
I'm working on a project that uses a PIC16F876A to read and display (on a GLCD) the output voltage and current of a benchtop power supply. I've got the A/D in 10 bit mode, and I have successfully measured and displayed these values. I'm looking to make a (relatively) precise piece of measurement equipment, but so far I'm not impressed with the internal A/D converter. For example, I've got an adjustable "scale factor" for each reading type, and when measuring voltage, I adjust it to read correctly at 20V (for example), the readings will be off by 50mV at 10V. I haven't taken a lot of data yet, but this is certainly more than I expected I don't think it's anything else because I'm using 0.1% resistors in my voltage divider, and values, 66.5K, and 15K, that are sufficiently high that there should be minimal interaction with the A/D input itself.
Anyway, what have others found about the internal A/D converter? Is a single correction factor enough, or do I need to do more? Some sort of a polynomial correction, or a lookup table? How about an external A/D, would the performance be better in terms of these gain errors that i appear to be seeing?
Doug |
|
|
Matthew Aurand
Joined: 20 Dec 2007 Posts: 9
|
|
Posted: Tue Apr 21, 2009 10:25 pm |
|
|
There are several factors that contribute to the performance of the ADC unit.
The basics for DC measurement include things like...
1. ADC Driver Stage: You want to drive the ADC input with a low-noise, low-impedance source. High-value resistive dividers are generally a no-no, but in low-speed applications probably OK. When selecting a buffer op-amp, low voltage offset and noise are good things to look for (gets more complicated for AC measurements).
2. ADC Voltage Reference: Stability and noise performance are critical features. If a precision device is desired, an external voltage reference is almost a must - the power supply is usually more prone to fluctuations and noise.
3. ADC Power Supply: Low-noise supply is required for high-performance digitization (although in 10-bit systems you don't have to be terribly concerned with this).
Hope this helps a bit. You can get better results from an external converter (better linearity & resolution) but you have to be very careful with the above 3 factors as resolution increases. _________________ -Matthew A. Aurand |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Apr 21, 2009 10:39 pm |
|
|
Post a very short test program, so we can look at your ADC clock divisor,
delay after channel change, and your math operations.
The program should have the #include, #fuses, #use delay, and any
other necessary #use statements. It should have a main(), etc., and
it should compile with no errors. Also post your compiler version.
Run the program on the actual hardware to verify that it shows the
problem. Then post it. |
|
|
Guest
|
|
Posted: Wed Apr 22, 2009 8:58 am |
|
|
Hi All,
Here is a short test program that compiles fine with v4.050. I've stripped out everything but the A/D routines, and a code to send the result to a terminal display.
Code: |
#include <16F876a.h>
#device ADC=10
#fuses HS, NOWDT, NOPROTECT, NOPUT, NOLVP
#ROM 0x2100={191,103} //Voltage with scale of 2656
#use delay(clock=20000000)
//-----< General Pin Assignment Defines >-----
#define Tx_Out Pin_B1 // serial data transmit pin to PC
//-----< Serial Port Definition >-----
#use rs232(baud=9600, xmit=Tx_Out, stream = Console)
// Here we read the ADC 8 times, take the average, and return the result
long read_adc_average()
{
long value;
int i;
//set_adc_channel(A/D_Input);
set_adc_channel(0);
delay_ms(150);
value=0;
for ( i=0 ; i<8 ; i++ ) {
value += read_adc();
delay_ms(10);
}
/* divide by 8 */
value = value / 8;
return value;
}
void main()
{
int16 VoltsScaleFactor;
int32 ScaledReading;
VoltsScaleFactor=make16(READ_EEPROM(1), READ_EEPROM(0));
// Here we setup the PIC hardware peripherals
setup_adc_ports(AN0);
setup_adc(ADC_CLOCK_INTERNAL);
//Here we used 'scaled integers' to avoid memory hungry 'float' operations. The correct 'display' value is shown
//by scaling the A/D reading, and then correctly positioning the decimal point.
//'5000000' = 5.000 on the GLCD display, so we divide this number by 1023 (max output of 10 bit A/D) to
//obtain the ScaleFactor. 5000000/1023 = 4888, which we convert into binary (1001100011000), and then
//into two separate 8 bit words (0:24d, 1:19d)
//Note: Voltage is measured with a 66.5K and 15K divider (0.184 ratio). With 20V applied to the divider, the output
//will be 3.68V. Also, the output of the divider will be 5.00V when 27.17V is applied. Therefore the scale needs to
//be 27170000/1023 = 26559, which we convert to binary (1100111 10111111), and then into two separate 8 bit words
//(0:191d, 1:103d)
while(1)
{
//Here we read the A/D converter, and display the appropriate reading on the LCD.
ScaledReading=((int32)read_adc_average()*VoltsScaleFactor)/1000;
// Here we send the reading to the serial port
fprintf(Console, "%04.3w\n\r", ScaledReading);
delay_ms(250);
}
}
|
Thanks,
Doug |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Apr 22, 2009 10:17 am |
|
|
Quote: | #include <16F876a.h>
#device ADC=10
#fuses HS, NOWDT, NOPROTECT, NOPUT, NOLVP
#ROM 0x2100={191,103} //Voltage with scale of 2656
#use delay(clock=20000000)
// Here we setup the PIC hardware peripherals
setup_adc_ports(AN0);
setup_adc(ADC_CLOCK_INTERNAL); |
Read this section of the 16F876a data sheet:
Quote: | 11.2 Selecting the A/D Conversion Clock |
With a 20 MHz oscillator, the recommended A/D clock divisor is 32. |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|