CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

A/D converter performance.....

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Guest








A/D converter performance.....
PostPosted: Tue Apr 21, 2009 9:46 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Tue Apr 21, 2009 10:25 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Tue Apr 21, 2009 10:39 pm     Reply with quote

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








PostPosted: Wed Apr 22, 2009 8:58 am     Reply with quote

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

View user's profile Send private message

PostPosted: Wed Apr 22, 2009 10:17 am     Reply with quote

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.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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