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

One ADC channel affecting reading of another

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



Joined: 21 Nov 2006
Posts: 129

View user's profile Send private message

One ADC channel affecting reading of another
PostPosted: Wed Jul 18, 2007 7:28 am     Reply with quote

Hi,

I am reading several different voltages with the ADC channels on a 18F2520. Compiler version is 4.030.

For testing, I have just one of the channels connected to a TI DAC5571 digital to analog converter, and I'm initializing it to something around 2.5V. Other channels are just floating. Vdd in my system is 5.6V.

The problem I'm having is that applying the voltage to one pin affects the reading of the channel being read right after the one with the voltage applied.

The ADC is set up for 8 bit. I'm initializing it like this:
Code:

setup_adc(  ADC_CLOCK_INTERNAL  );
setup_adc_ports( AN0_TO_AN4 );


And my code to read the ADC channels is this:

Code:

output_voltage_PS = 0.0;
input_voltage_PS = 0.0;
     
set_adc_channel(0);
delay_us(10);
     
for(i=0;i<20;i++) output_voltage_PS += (float)read_adc();
output_voltage_PS = output_voltage_PS / 20.0;
output_voltage_PS = (output_voltage_PS * 2.1875); // 5.6/256 * 100
     
set_adc_channel(3);
delay_us(10);
     
for(i=0;i<20;i++) input_voltage_PS += (float)read_adc();
input_voltage_PS = input_voltage_PS / 20.0;
input_voltage_PS = (input_voltage_PS * 2.1875); // 5.6/256 * 100


There are other channels being read, but the code looks identical for those, with the exception of the channel number. The only channel that is affected is the one following the one with the voltage applied. If I switch the code around so a different channel follows the first with the voltage applied, then that channel gets the erroneous reading and the other is fine.

So in this example, I get approximately 281.53 for the output_voltage_PS value, and 38.28 for the input_voltage_PS (which I would expect to be zero since that channel is not hooked up to anything). The traces are well separated. I understand that the PICs ADC channels are multiplexed, and I'm guessing it has something to do with that. But I really am puzzled.

Thanks in advance.
SherpaDoug



Joined: 07 Sep 2003
Posts: 1640
Location: Cape Cod Mass USA

View user's profile Send private message

PostPosted: Wed Jul 18, 2007 8:02 am     Reply with quote

If a pin is floating there is no reason to expect it to read zero volts. The A/D specifies a maximum input impedance, and an unconnected pin clearly has too high an impedance to meet the spec.
The A/D has some input capacitance, and it takes current flow to change voltage on a capacitor. With an open pin only current through internal leakage can get the A/D to read a different voltage than the last one it read. As a general practice you should tie unused A/D inputs to some fixed voltage, such as GND or VCC.
_________________
The search for better is endless. Instead simply find very good and get the job done.
evsource



Joined: 21 Nov 2006
Posts: 129

View user's profile Send private message

PostPosted: Wed Jul 18, 2007 8:06 am     Reply with quote

I think I just figured out the problem from reading this post:

http://www.ccsinfo.com/forum/viewtopic.php?t=5366

Sounds like floating pins will retain a portion of the previous reading's value. Since these other ADC pins will eventually be connected to voltage sources, I don't imagine this will be a problem.
jfk1965



Joined: 21 Oct 2003
Posts: 58

View user's profile Send private message

PostPosted: Wed Jul 18, 2007 8:06 am     Reply with quote

The PIC ADC cannot read float values only Int or Long int. Remove the float before the read_adc command and set PS as INT or long.

JFK
evsource



Joined: 21 Nov 2006
Posts: 129

View user's profile Send private message

PostPosted: Wed Jul 18, 2007 8:14 am     Reply with quote

SherpaDoug wrote:
If a pin is floating there is no reason to expect it to read zero volts. The A/D specifies a maximum input impedance, and an unconnected pin clearly has too high an impedance to meet the spec.
The A/D has some input capacitance, and it takes current flow to change voltage on a capacitor. With an open pin only current through internal leakage can get the A/D to read a different voltage than the last one it read. As a general practice you should tie unused A/D inputs to some fixed voltage, such as GND or VCC.


This makes sense. What I don't understand: if the previous voltage reading was 2.5V, and the subsequent reading on another channel is 2.2V, then that internal ADC capacitor will have to discharge a portion of its charge through the second channel, i.e. the circuitry connected to the second channel will be sinking current instead of sourcing it. How does this work? I'm assuming that the impedance of the voltage source of the second channel will determine the ability of that source to "sink" current. Looking at the DAC I'm using, it has an output impedance of 1 ohm. Does that mean that the charge in that internal capacitor will discharge to ground through a 1 ohm resistor if the second channel was connected to this exact DAC? Please set me straight if I'm way out there!
evsource



Joined: 21 Nov 2006
Posts: 129

View user's profile Send private message

PostPosted: Wed Jul 18, 2007 8:16 am     Reply with quote

jfk1965 wrote:
The PIC ADC cannot read float values only Int or Long int. Remove the float before the read_adc command and set PS as INT or long.

JFK


That's just casting the read value (a single byte) to a float to add it to a variable that is of type "float". I imagine if I didn't cast it as a float, it would be handled by the compiler and still work correctly. I've just found that making things explicit is better than wondering what the compiler will do with it.
SherpaDoug



Joined: 07 Sep 2003
Posts: 1640
Location: Cape Cod Mass USA

View user's profile Send private message

PostPosted: Wed Jul 18, 2007 8:41 am     Reply with quote

evsource wrote:
What I don't understand: if the previous voltage reading was 2.5V, and the subsequent reading on another channel is 2.2V, then that internal ADC capacitor will have to discharge a portion of its charge through the second channel, i.e. the circuitry connected to the second channel will be sinking current instead of sourcing it. How does this work? I'm assuming that the impedance of the voltage source of the second channel will determine the ability of that source to "sink" current. Looking at the DAC I'm using, it has an output impedance of 1 ohm. Does that mean that the charge in that internal capacitor will discharge to ground through a 1 ohm resistor if the second channel was connected to this exact DAC? Please set me straight if I'm way out there!


That is pretty close. The DAC impedance works for both sourcing and sinking. Ideally the second channel would behave like a 1 ohm resistor tied to an ideal 2.2V source. In reality the DAC probably also has a current limit so that 1 ohm is only good for small voltage changes. Also there are other small impedances such as the A/D input mux and the signal and ground traces between the DAC and A/D. In practice the slew rate and overshoot of the DAC output amp is the first place I would look for speed or accuracy limitations.
_________________
The search for better is endless. Instead simply find very good and get the job done.
Bill Boucher



Joined: 04 Feb 2005
Posts: 34
Location: Chatham,ON,CA

View user's profile Send private message Send e-mail Visit poster's website

PostPosted: Wed Jul 18, 2007 9:01 am     Reply with quote

Typical PIC ADC input impedence is such that your signal source should have an impedence less than 10 kohm. It can be higher (i.e. 47k) if you put a capacitor on the signal near the PIC (i.e. 1nF to 100nF depending on how much filtering you want).

Another thing, the typical settling time of the internal capacitance of the ADC is about 20 us. Just increase your delay_us(10) after changing channels and you will see a dramatic reduction in "crosstalk" between channels. Be aware that the larger the difference in voltage between channels you are switching between, the larger the crosstalk error will be. Increasing the settling time solves this. I usually allow 100 us as rule of thumb. Better too much than not enough.
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