Jump to content
Dave_H

Problem With A/d Input Channel

Recommended Posts

Hi

 

I've beening testing the response from an A/D input RA0. By putting the result 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.

 

Here is the code that I have been using

 

 

#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

}

 

 

Can anybody spot what I'm doing wrong ?

 

Many thanks for any help recieved

 

Dave_H

Share this post


Link to post
Share on other sites

What is your reference voltage, where are you deriving it from and how many bits is your ADC? With a 10bit ADC I would expect 1023 from 5v input and a 5v reference.

David.

Share this post


Link to post
Share on other sites
What is your reference voltage, where are you deriving it from and how many bits is your ADC? With a 10bit ADC I would expect 1023 from 5v input and a 5v reference.

David.

 

Hi thankyou for the reply

 

5V direct from a thandor test supply.

 

VREF+ = 5v VDD

VREF- = 0V VSS

 

ADCON1=0X82;

AN0-AN4=ANALOG.

AN5-AN7 DIGITAL.

 

I assumed that the ADC is 10bits wide once ADRESH and ADRESL is added together before the result is returned ??

 

Dave

Share this post


Link to post
Share on other sites
What is your reference voltage, where are you deriving it from and how many bits is your ADC? With a 10bit ADC I would expect 1023 from 5v input and a 5v reference.

David.

 

Hi DaveT

 

I tried it with 5V ref on AN3 and also get a response of 1023 @ 5V. But again if I move the voltage down to 2.5V the response come out as 574 not 511.

 

also 1V = 240

2V = 480

3V = 655

4V = 896

5v = 1023

 

I trying to control an amplifier which requires a D-A setpoint between 0-5 V. Which Then give an actual value back between 0-5V.

 

Many thanks Dave H

Share this post


Link to post
Share on other sites

The ADC bits are determined by the chip you are using. Perhaps let us know what that is.

 

To vary input voltage for testing you are presumably using a different/dual supply. To remove one complexity may I suggest you tie your PIC's input to Vdd so it definitely has the same voltage. The result really should be 1023 (if 10bit) irrespective of the exact voltage. 0 when tied to ground.

 

Without having checked your code fully, are you telling the PIC what Vref to use? (Vdd or external).

David.

Share this post


Link to post
Share on other sites
The ADC bits are determined by the chip you are using. Perhaps let us know what that is.

 

To vary input voltage for testing you are presumably using a different/dual supply. To remove one complexity may I suggest you tie your PIC's input to Vdd so it definitely has the same voltage. The result really should be 1023 (if 10bit) irrespective of the exact voltage. 0 when tied to ground.

 

Without having checked your code fully, are you telling the PIC what Vref to use? (Vdd or external).

David.

 

I'm using a 16F877A. The first test was done using vdd . The second set of tests where done using vref on analog 3. After changing the adcon setting .

 

Dave

Share this post


Link to post
Share on other sites

I would log the values of key registers (eg: adcon0/1) and ADC conversion values in EEPROM next. I think you need to trap actual settings when the conversion is performed (read them via your programmer to check them). I have some EEPROM code on this link and other examples if you need it. Different chip but should be easy to convert:

http://www.flyelectric.ukgateway.net/pic-temp2.htm

David.

Share this post


Link to post
Share on other sites

Hi

 

I have a similar problem using a 16F690.

Using two 1K resistors as a voltage divider, and Vdd as reference voltage, I get:

 

ADC value at ground rail = 0

ADC value at Vdd rail = 1023

ADC value at mid point of divider = 450 or thereabouts

 

This occurs on any ADC channel I use.

 

I thought perhaps it may be because the source impedence is different at different points on the divider, thus affecting capacitor charging time in the ADC? Repeating the test with 15K resistors in the divider produces the same results, so perhaps the impedance idea is wrong.

 

I am at a loss to explain it - have you had any luck with this sort of problem? Can anyone help?!

 

 

Also, I have discovered a second problem:

When I enable weak pull-ups (which exist only on PORTA and PORTB), ADC measurements on PORTC become inverted, i.e. where ADC at Vdd was 1024, now it becomes 0!! I cant find reference to this in the datasheet - has anyone any idea what is going on?

 

I'd be grateful for any assistance!

Share this post


Link to post
Share on other sites

With the following code with a 16F690 I get 515 from two 1k5 resistors dividing 5.01v supply. The resistors yield 2.525v at their junction which should be an ADC value of 516. Spot on given a 1 step error rate.

 

#include <system.h>				//Settings/Target 16F690

//Core configuration option_regs:
#pragma DATA _CONFIG, _FCMEN_OFF & _IESO_OFF & _BOR_ON & _CPD_OFF & _CP_OFF & _MCLRE_OFF & _PWRTE_ON & _WDT_OFF & _INTOSCIO

void write_data()				//Function to write to EEPROM flash memory
{
intcon.7 = 0;				//Disable interrupts
pir2.4 = 0;					//EEIF: Clear this bit which gets set after each write

eecon2 = 0x55;				//Required before writing to memory
eecon2 = 0xAA;				//Required before writing to memory
eecon1.1 = 1;				//WR: Writes data eedata to address eeadr

while(eecon1.1==1);			//Wait for write to complete (becomes 0 when complete)

eeadr++;					//Increment the address by 1 for next write
}

void main()
{
//Initialise all ports
porta=0; portb=0; portc=0;

//Main port settings (1=Input 0=Output)
trisa = 0;			//All pins Output except...
trisa.2 = 1;		//RA2 (Pin17)	AN2

trisb = 0;			//All pins Output
trisc = 0;			//All pins Output

//ADC port settings (1=Analog 0=Digital)
ansel = 0;			//All pins digital except...
ansel.2 = 1;		//RA2 (Pin17)	AN2
anselh = 0;

//Static EEPROM data logging settings
eecon1.7 = 0;				//EEPGD: Access data memory
eecon1.3 = 0;				//WRERR: clear on startup in case previously set
eecon1.2 = 1;				//WREN: enable writing to memory
eeadr = 0;					//Start address

//Static ADC settings
adcon1 = 0b1010000;			//AD Conversion Clock Fosc/16
pie1.6 = 0;					//ADC interrupts disabled
  	adcon0 = 0b10001001;		//Right justify, Vdd as ref, AN2 active, AD module enabled

//Run ADC
char i;						//Declare variable for timer
for(i=0; i<1; i++);			//Delay for acquisition capacitor to charge
pir1.6 = 0;					//ADIF: Clear the ADC interrupt flag
adcon0.1 = 1;				//GO: Start ADC acquisition
while(adcon0.1==1);			//Wait for conversion to complete (becomes 0)

//Store results
eedata = adresh;			//High register
write_data();				//Write to EEPROM

eedata = adresl;			//Low register
write_data();				//Write to EEPROM

while(1);						//Wait here

}								//end main

Share this post


Link to post
Share on other sites

Thanks! Your code gives me 511 - perfect.

The important difference difference is you used _INTOSCIO in the config, whereas I was using _INTOSC.

I cannot fathom why _INTOSC messes things up - can't see anything in the datasheet. Do you have any idea why _INTOSCIO causes the ADC to work fine, but _INTOSC doesnt?

 

Cheers

Share this post


Link to post
Share on other sites
Thanks! Your code gives me 511 - perfect.

The important difference difference is you used _INTOSCIO in the config, whereas I was using _INTOSC.

I cannot fathom why _INTOSC messes things up - can't see anything in the datasheet. Do you have any idea why _INTOSCIO causes the ADC to work fine, but _INTOSC doesnt?

 

Cheers

The difference is that _INTOSC provides the FCYC clock output on the RA4/AN3/T1G/OSC2/CLKOUT pin.

 

This should have no affect on the ADC but perhaps your circuit has something connected to the RA4 pin that will be an issue if the PIC were to drive this with a 1MHz clock.

Share this post


Link to post
Share on other sites

Join the conversation

You are posting as a guest. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

×
×
  • Create New...