Why is the A/D port not linear ?

For C and ASSEMBLY users to post questions and code snippets for programming in C and ASSEMBLY. And for any other C or ASM course related questions.

Moderators: Benj, Mods

Post Reply
David Halliday
Posts: 9
Joined: Tue Jan 10, 2006 4:36 pm
Location: Hampshire
Contact:

Why is the A/D port not linear ?

Post by David Halliday »

Hi

I've beening testing the response from an A/D input RA0. By putting the results directly onto an LCD display. but it does not seem to be as linear as I expected . Here are the results that I've achieved.

Tested using DC bench supply.

1.0V = 192
2.0V = 384
2.5V = 480
3.0V = 527
4.0V = 704
5.0V = 824

I assumed that @ 2.5V the digital response would be around 412 counts but it seems to be a long way out. It also seems to jump periodically in larger increment when you increment slowly from 0-5V. I've added filtering caps and resistors to the input but this does not seem to make any difference.

I've tried adding an external reference to AN3 (After changing adcon settings) which give the following results

1V = 240
2V = 480
2.5V = 574 expect to see 511 counts ?
3V = 655
4V = 896
5v = 1023

but the result is still not a linear response.

Here is the code which I have been using can anyone see what I'm doing wrong

Code: Select all


#include<system.h>
#include"AD channels.h"

unsigned char ADCRESL@0x9e;  // control reg for A/D
unsigned char ADCRESH@0x1e;

int ad_delay(int loop)// Allow A/D to settle
{
int t;
for(t=0;t<loop;t++);
}


unsigned int display1_value (unsigned int value,char position)                         
{                                                                                                                            
                                                                                
     //  first get the digits                                                      
                                                                                
    unsigned int thou,hunds, tens, units;                                                                                                
                                                                                
    //  first get the digits                                                          
      units= value % 10;
        value= value/10;
        tens=  value % 10;
        value= value/10;
        hunds= value % 10;
        value= value / 10;
        thou = value % 10;                                        
          
    lcd_cursor(position,1);  // Result position upon on display 
    lcd_print_ch ('0' +  thou);                                                        
    lcd_print_ch ( '0' + hunds );                                                
    lcd_print_ch ( '0' + tens );                                                
    lcd_print_ch ( '0' + units );
    }                



int read_adc0 (char adcon_0 ) // Main A/D conversion sub 
{ 

   unsigned char h, l =0; 
   int result=0; 
    
   adcon0 = adcon_0 & 0xFb;  /* Switch ADC channel*/ 
    
   ad_delay(15);

   adcon0 = adcon0 + 0x04;  //start conversion 

   while ( adcon0 & 0x04 );//spin while the conversion runs  
    
   h = ADCRESH; 
   l = ADCRESL; 
    
      result = (256 * h) + l; // Add high byte-to-low 
      return result; 
} 


unsigned char ad_Channel_0() //Channel_0 of A/D PORT RA0   Set for forward power readback
{
unsigned CH0_adcon0=0x05;  // Select channel 1 
unsigned int result;
           
    result= read_adc0(CH0_adcon0);      // analog conversion result
    display1_value(result,4); // Display result and position on screen correctly

}
Many thanks Dave :?: :?:

User avatar
Benj
Matrix Staff
Posts: 15312
Joined: Mon Oct 16, 2006 10:48 am
Location: Matrix TS Ltd
Has thanked: 4803 times
Been thanked: 4314 times
Contact:

Post by Benj »

Hello Dave

It may be possible that you are not allowing enough time for the analogue capacitor to charge up correctly. Try allowing for a longer delay and see if this improves the results.

Post Reply