View previous topic :: View next topic |
Author |
Message |
evsource
Joined: 21 Nov 2006 Posts: 129
|
One ADC channel affecting reading of another |
Posted: Wed Jul 18, 2007 7:28 am |
|
|
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
|
|
Posted: Wed Jul 18, 2007 8:02 am |
|
|
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
|
|
Posted: Wed Jul 18, 2007 8:06 am |
|
|
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
|
|
Posted: Wed Jul 18, 2007 8:06 am |
|
|
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
|
|
Posted: Wed Jul 18, 2007 8:14 am |
|
|
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
|
|
Posted: Wed Jul 18, 2007 8:16 am |
|
|
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
|
|
Posted: Wed Jul 18, 2007 8:41 am |
|
|
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
|
|
Posted: Wed Jul 18, 2007 9:01 am |
|
|
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. |
|
|
|