Analog IN - floating voltage (no input)

I have a basic circuit where i am reading voltage on two of the analog input pins (A0 & A5), it will trigger some other action based on detecting 5v (1023) on one of the input pins.

here is the code (truncated for example):

const int hvacDownPin = 0; 
const int hvacUpPin = 5; 

void setup() {
  Bridge.begin();
  Console.begin();

  pinMode(hvacDownPin, INPUT);
  pinMode(hvacUpPin, INPUT);
}

void loop() {  
  int hvacDownState = analogRead(hvacDownPin);
  int hvacUpState = analogRead(hvacUpPin);
  
  Console.println(" ");
  Console.print("HVAC DOWN value = ");
  Console.println(hvacDownState);
  Console.print("HVAC UP value = ");
  Console.println(hvacUpState);
}

Even with NOTHING plugged into the YUN (except power via micro-USB), here is what the console is showing:

If i have ANYTHING plugged into it, not even feeding voltage, the readings jump around.
Yesterday i plugged in some cabling i ran from the attic to the basement, and it would spike to 1022 , 1023 with no power source...
When i put a volt meter on the same cable from the attic, i get readings of 0.002-0.008 volts... which would be something like 0 or 1 on the 1024 scale...

Why is there all of this variation ?
Is my YUN bad ?

(btw, i initially tried the same on digital pins, and the readings were just a sporadic, i thought i could isolate it better on the analog side... but clearly i am missing something fundamental).

Thanks in advance for your collective support !

Added a couple more lines to make it clearer to me in terms of voltage:

int hvacDownState = analogRead(hvacDownPin);
  int hvacUpState = analogRead(hvacUpPin);
  int sensorValueUP = analogRead(A5);
  int sensorValueDOWN = analogRead(A0);
  
  float voltageUP = sensorValueUP * (5.0 / 1023.0);
  float voltageDOWN = sensorValueDOWN * (5.0 / 1023.0);
  
  Console.print("HVAC DOWN value = ");
  Console.print(hvacDownState);
  Console.print("   Voltage = ");
  Console.println(voltageDOWN);
  Console.print("HVAC UP   value = ");
  Console.print(hvacUpState);
  Console.print("   Voltage = ");
  Console.println(voltageUP);

And here is the output:

HVAC DOWN value = 227 Voltage = 1.09
HVAC UP value = 230 Voltage = 1.12
All is okay...

HVAC DOWN value = 225 Voltage = 1.05
HVAC UP value = 223 Voltage = 1.08
All is okay...

HVAC DOWN value = 221 Voltage = 1.04
HVAC UP value = 215 Voltage = 1.05
All is okay...

HVAC DOWN value = 226 Voltage = 1.10
HVAC UP value = 228 Voltage = 1.12
All is okay...

HVAC DOWN value = 230 Voltage = 1.13
HVAC UP value = 238 Voltage = 1.17
All is okay...

HVAC DOWN value = 233 Voltage = 1.15
HVAC UP value = 244 Voltage = 1.19
All is okay...

!!!!
const int hvacDownPin = A0; // This is A0
const int hvacUpPin = A5;

Hard to say without knowing what you are using for input circuitry, and what the output impedance is of your sources, but here are a few guesses.

  1. The input impedance of the ATmega analog inputs are 100 Mohm, so with no input it will be floating to some arbitrary voltage. I read around 250 with a floating input.

  2. If your wiring have long cable runs of non-shielded wires, you can expect noise pickup, and with the high input impedance the spiking you see is not surprising.

I would suggest a resistor to ground on the input, if that is OK with your source, 1k to 10k might be a good value. Even better would be a voltage divider of let's say 1k series and 10k to ground. This will lose you about 9% of the reading so you would have to adjust your calculation based on that, but would allow you to put a small filter capacitor across the 10k resistor to get rid of any remaining noise.

bjarne:
2. If your wiring have long cable runs of non-shielded wires, you can expect noise pickup, and with the high input impedance the spiking you see is not surprising.

I would suggest a resistor to ground on the input, if that is OK with your source, 1k to 10k might be a good value. Even better would be a voltage divider of let's say 1k series and 10k to ground. This will lose you about 9% of the reading so you would have to adjust your calculation based on that, but would allow you to put a small filter capacitor across the 10k resistor to get rid of any remaining noise.

Yea, situation #2 is mine.

I'm a relative newb at this, could you, or anyone else on this board, draw a diagram for how i should incorporate a resistor to ground or a voltage divider... i thought i could just close the circuit by grounding to one of the 'GND' pins on the board.

Thanks again for the responses.

What effect did adding a couple of "A"s in correct places ?

knut_ny:
What effect did adding a couple of "A"s in correct places ?

None.

It is my belief that if you are calling an analogRead, it will look to A0-A5, whether you call out pin A0 or 0... it won't look to D0.

I will try to draw a 'schematic' later, but for the simple case of adding a 10k resistor to ground: connect the resistor between the two wire from your cable and then (as before) connect one wire to ground and one wire to your signal input. Not knowing the source of your signal (or its output impedance) it is impossible to say if the resistor will put too much load on your source, but I am guessing that 10k is a safe value.

bjarne:
I will try to draw a 'schematic' later, but for the simple case of adding a 10k resistor to ground: connect the resistor between the two wire from your cable and then (as before) connect one wire to ground and one wire to your signal input. Not knowing the source of your signal (or its output impedance) it is impossible to say if the resistor will put too much load on your source, but I am guessing that 10k is a safe value.

Ah, yea, that is simple enough.

So the source is the Arduino 5v output pin... it sends +5v out one wire [over a substantial distance, maybe 30 meters], to a remote pan that surrounds a furnace. Another wire [open distance of ~3 cm between these two wires] is set in the pan and is connected to A0.

Should the pan flood with water, the circuit will close and a program listening on A0 will see ~+5v and trigger a series of events.

Problem i am having is that with all of the fluctuation and spikes on A0 without a load present is causing false-positive triggers.

HTH

Thanks,
_ Garrett

So the switch is a mechanical switch with very low ON resistance? Or is it a device, and in that case what is the part number?

What you describe sounds like potentially a very noisy setup with the two wires separate. One improvement would be running a twisted pair.

I would first try the 10k to ground and maybe then the divider if you still get noise spikes. It also sound like you could use a digital input (which I think you mentioned that you tried), but that would have the same noise problem.

bjarne:
So the switch is a mechanical switch with very low ON resistance? Or is it a device, and in that case what is the part number?

What you describe sounds like potentially a very noisy setup with the two wires separate. One improvement would be running a twisted pair.

I would first try the 10k to ground and maybe then the divider if you still get noise spikes. It also sound like you could use a digital input (which I think you mentioned that you tried), but that would have the same noise problem.

You're correct, very low, to no 'ON' resistance, the wires are run in parallel (i believe it is solid core 18/2 copper wire) in the pan their ends are stripped and sit a few cm apart from each other to create a physical/mechanically opened circuit that the presence of water would close to complete the loop back to A0. I will try the 10k resistor shortly and see how what the readings are on A0.

Sounds like the wiring is OK. If the 10k resistor improves the situation, I would suggest that we try the voltage divider and capacitor next, but we can talk about that after your test. I never like to have a microprocessor pin directly exposed to the outside world, and a series resistor will give some protection.

So the 10k resistor did change the input values, but it did not stop the spiking... the voltages were a little lower, but it kept spiking for some reason.

I would try the divider route next, but I am also trying to understand your output. I can see that the 'value' is the data from the AnalogRead, but how do you get the voltage, it does not always seem consistent with the value. For example:

HVAC DOWN value = 469 Voltage = 3.51
HVAC UP value = 405 Voltage = 1.98

The ratio value/Voltage does not seem to be the same in the two cases, so how do you compute it?

I know this is not your main problem, but I am curious.

To implement the divider, cut the wire for the signal so that the 10k is on the pin side, and insert a 1k resistor in the cut wire. Also put a capacitor across the 10k resistor. I would use something like a 1uF capacitor, but anything from 0.1 to 100uF would work, since the signal from the switch is very slow. If you use a polarized capacitor the positive should go the the signal side.

Another thing, is the ground wire connected to anything other than the switch and the Arduino? I am thinking of a possible ground loop her.

bjarne:
I would try the divider route next, but I am also trying to understand your output. I can see that the 'value' is the data from the AnalogRead, but how do you get the voltage, it does not always seem consistent with the value. For example:

HVAC DOWN value = 469 Voltage = 3.51
HVAC UP value = 405 Voltage = 1.98

The ratio value/Voltage does not seem to be the same in the two cases, so how do you compute it?

It's a great question and i'm glad to have your keen eyes looking for abnormalities such as that... here is the code for calculating 'voltage' from the analogIN:

void loop() {  
  int hvacDownState = analogRead(hvacDownPin);
  int hvacUpState = analogRead(hvacUpPin);
  int sensorValueUP = analogRead(A5);
  int sensorValueDOWN = analogRead(A0);
  
  float voltageUP = sensorValueUP * (5.0 / 1023.0);
  float voltageDOWN = sensorValueDOWN * (5.0 / 1023.0);
  
  Console.print("HVAC DOWN value = ");
  Console.print(hvacDownState);
  Console.print("   Voltage = ");
  Console.println(voltageDOWN);
  Console.print("HVAC UP   value = ");
  Console.print(hvacUpState);
  Console.print("   Voltage = ");
  Console.println(voltageUP);
  ...
}

which is odd, because it should not be 3.51v, but rather 2.29v ... for the first line.
but the second line at 1.98v is correct... very strange.

bjarne:
To implement the divider, cut the wire for the signal so that the 10k is on the pin side, and insert a 1k resistor in the cut wire. Also put a capacitor across the 10k resistor. I would use something like a 1uF capacitor, but anything from 0.1 to 100uF would work, since the signal from the switch is very slow. If you use a polarized capacitor the positive should go the the signal side.

Another thing, is the ground wire connected to anything other than the switch and the Arduino? I am thinking of a possible ground loop her.

let's address the grounding issue first, before the divider...
i have drawn this basic diagram to show my circuit; i guess i was assuming that the pins were grounded... otherwise this thing is all messed up.

add 1M from A0 to GND…
Salty water will give you a reading. As now the input is floating…

I now see your other post with the computation of the voltage, and that should produce consistent results. So that got me to thinking that I have had problems with totally weird results when my sketch was fairly large and especially when I had many strings. I think that with the limited ram it is possible to run out heap and get some of the variables overwritten. This problem completely went away when I cut down on the number of string and I also try to do as much processing on the Linino side to make the sketch size sampler.

So do you think that could be part of the problem?

And you posted the last one while I was typing this :slight_smile:

bjarne:
I now see your other post with the computation of the voltage, and that should produce consistent results. So that got me to thinking that I have had problems with totally weird results when my sketch was fairly large and especially when I had many strings. I think that with the limited ram it is possible to run out heap and get some of the variables overwritten. This problem completely went away when I cut down on the number of string and I also try to do as much processing on the Linino side to make the sketch size sampler.

So do you think that could be part of the problem?

And you posted the last one while I was typing this :slight_smile:

could be, but when compiled the sketch uses 61% of program storage space... i hope that isn't over-running the memory, but certainly i could cut down on the output... that is just for debugging... but the actual analogRead value is what is used to trigger the events... so the actual voltages could be ignored.

knut_ny:
add 1M from A0 to GND..
Salty water will give you a reading. As now the input is floating..

what do you mean by that first statement ?
that i should put a large resistor between A0 and GND ? I had thought this too...
my biggest resistor, on-hand, is 10K ohm... would that be large enough ?

It is not the sketch side itself that I had problem with, but rather (I think) the number of string that I used, which would used up variable space with being shown as global variables. For a test try to make your strings a shorter, or even get rid of some of them. I used to make changes in places totally unrelated to where my problem showed, and it went away.

Do you have a URL or part number for the sensor or switch you have in the pan.

You might not need a ground wire, but since you already have a 10k series resistor, the readings should have been cut in about half, did they? I am assuming they 10k resistor is in addition to the one you added for the test.