Voltage Changing Across All Analog Pins?

Hi Everyone,

The Background:

I have two SPDT (ON-OFF-ON) switches attached to my UNO R3, one Momentary switch and one Maintained switch.
The idea is to use these as a kind of throttle and direction control with the Maintained switch being (Fast-Med-Slow) and the Momentary switch being (Up-Stopped-Down).

I have 5V going to both switches.
The Momentary switch is wired to A0
The Maintained switch is wired to A1

(for both switches Pin 1 = 5V, Pin 2 = Analog In, Pin 3 = Ground)

the rest of the Analog pins are empty.

in my mind I should be able to just read the analog pins and have my direction and speed.

A0 = 0, A1 = 0, Slow Up
A0 = 0, A1 = 512, Med Up
A0 = 0, A1 = 1023, FastUp
A0 = 1023, A1 = 0, Slow Down
A0 = 1023, A1 = 512, Med Down
A0 = 1023, A1 = 1023, Fast Down
Anything else = Stopped

(I know this isn't exact and I can expect some fluctuation especially with the med range, but it is a general overview of what I'm aiming for and how I plan to get there)

The Problem:

I put together a quick code to monitor my analog pins so I could get an idea on what is going on and what I could expect as I start my actual coding. Originally I was only looking at the 2 pins i was using but i expanded it to look at all 6 to try and figure out what is going on, even though there is nothing wired to the remaining 4 pins.

the issue is that I am seeing the voltage fluctuate across all the analog pins depending on what state the switches are in.

the largest issue is when the Maintained switch is in the OFF position, A1 can read an almost full 5V or almost completely grounded depending on where my momentary switch is (the momentary switch should only affect A0).

I'm confused if this is something I did (or didn't do) or maybe just an issue with the board. any help is appreciated.

I have attached a txt file of my output as I go through different switch configurations.

Here is the code I used to monitor the analog pins

/*
  Analog input monitor
*/

// These constants won't change. They're used to give names to the pins used:
const int analogInPin1 = A0;  
const int analogInPin2 = A1;  
const int analogInPin3 = A2;  
const int analogInPin4 = A3;  
const int analogInPin5 = A4;  
const int analogInPin6 = A5; 

void setup() {
  // initialize serial communications at 9600 bps:
  Serial.begin(9600);
}

void loop() {

  // read the analog in value:
  // print the results to the Serial Monitor:
  Serial.print("A0 = ");
  Serial.print(analogRead(analogInPin1));
  Serial.print("\t A1 = ");
  Serial.print(analogRead(analogInPin2));
  Serial.print("\t A2 = ");
  Serial.print(analogRead(analogInPin3));
  Serial.print("\t A3 = ");
  Serial.print(analogRead(analogInPin4));
  Serial.print("\t A4 = ");
  Serial.print(analogRead(analogInPin5));
  Serial.print("\t A5 = ");
  Serial.print(analogRead(analogInPin6));

  if (analogRead(analogInPin1)==0 and analogRead(analogInPin2)==0) {
    Serial.println("\t SLOW UP");
  }
  else if (analogRead(analogInPin1)==1023 and analogRead(analogInPin2)==0) {
    Serial.println("\t SLOW DOWN");
  }
  else if (analogRead(analogInPin1)==0 and analogRead(analogInPin2)==1023) {
    Serial.println("\t FAST UP");
  }
  else if (analogRead(analogInPin1)==1023 and analogRead(analogInPin2)==1023) {
    Serial.println("\t FAST DOWN");
  }
  else {
    Serial.println("\t STOPPED");
  }
  // wait 2 milliseconds before the next loop
  delay(2);
}

AnalogOutput.txt (55.1 KB)

Very difficult to work out what is happening without a proper schematic.

However if the switch is in the OFF position maybe the A0 and A1 inputs are floating ?

Attach 2 x 10K resistors to each analog pin. One to 5V and the other to ground.

As to direction I don't understand why not use digital inputs? Set digital inputs to internal pullup and just switch them to ground.

You do not mention the motor or how the motor speed is controlled? If the motor can use PWM you may want to just use a pot and run an analog voltage into A0 and map the value to a digital PWM out. Matter of fact using a cheap L298 module you could likely drive the motor and have forward/reverse and speed control based on a few inputs to your Arduino.

Ron

If the switch is in the center position, the pin will be connected to nothing, floating anywhere between 0 and 1023. You need to connect a 22k resistor from the switch center pin to GND and enable the internal pullup resistor on the input pin.Then you will have 5V (1023), on one side, 0V on the other and somewhere in the middle (300 to 700 ?)at the center position.

val = analogRead(A0);
if(val < 300)
  do_this;
else if(val > 700)
 do_that;
else 
  do_the_other;
1 Like

I hate it when people use analog when they really want digital, but a couple of hints:

  1. "print out" the actual analog readings for testing & debugging.

  2. Look for a range of numbers instead of an exact value. i.e. Maybe less than 100 instead of zero, greater than 900, and between 300 & 600, etc. And, maybe decide what to do if none of those are true or don't leave any undefined gaps, etc.

0 & 1023 might work but 512 most-likely won't be reliable and looking for exact analog numbers will just generally give you trouble...

Digitally, you can read all 3 conditions/positions from one switch using 2 digital inputs (4 inputs to handle both switches and all possible states). And by enabling the internal pull-up resistors you don't need any additional components.

You can get -
11 (high-high center position)
01 (low-high)
10 ( high-low)

Any input pin that is open circuit has an undefined voltage on it, so never let that happen. This is
a basic rule to learn when working with CMOS logic chips.

CMOS inputs are electrically isolated by gate-oxide layers so their voltage will wander around dependent
on surrounding wiring, leakage currents, and other ill-defined influences unless they are always connected
via resistors or switches to some part of the circuit.

Thanks everyone for your feedback and help.

srnet:

Yeah I understand, I a visual learner as well. unfortunately I've never been great with circuit diagrams and I couldn't get the simulator to look as nice as I wanted.

Floating inputs isn't something that I am familiar with so I will have to keep an eye on that in the future.

PaulRB:

Doing this and enabling the internal pull-up resistors ended up working the best

JCA34F:

Your explanation was very good (caught myself going "well duh"). your solution would have worked but there did seem to be more fluctuations with that setup than there were with PaulRB's setup

DVDdoug:

Thanks for your feedback but I feel like you missed some parts in my original post.

  1. "print out" the actual analog readings for testing & debugging.

This is exactly what my code in my first post does and I even attached the output file to that post.

  1. Look for a range of numbers instead of an exact value. i.e. Maybe less than 100 instead of zero, greater than 900, and between 300 & 600, etc. And, maybe decide what to do if none of those are true or don't leave any undefined gaps, etc.

0 & 1023 might work but 512 most-likely won't be reliable and looking for exact analog numbers will just generally give you trouble...

I never intended to look for exact values, those were just examples to illustrate what I was trying to accomplish. I even stated that I know I can expect fluctuations and that the whole purpose for my code was so that I could define those ranges.

Ron_Blain and DVDdoug:

The digital questions are legitimate, and my original plan was to do exactly what DVDdoug described. unfortunately, this takes up too many pins. not only would it be difficult to finish out everything I have left to do, it would make it impossible to do future expansion on a single board (Pin conservation, the struggle is real).

The project as it stands is to control the Z-axis of an old microscope (focusing) I got from work.
The microscope has all the hardware in it but the computer and software are long.
The Z-axis has an 8 wire stepper motor and an upper and lower kill switch that I need to start coding (they are already hooked up on the digital side).

If I end up getting the stage back then that is a couple more stepper motors and kill switches for the X-Y axis that I will have to work with, but there is still a couple different ways I am thinking about handling that.

MarkT:

Thanks, that is a handy bit of information, this is my first time working with an Arduino.

In college I did quite a bit of data acquisition well as driver and circuit building with LabVIEW (I think i still have a myDAQ floating around my house somewhere), but that was 10+ years ago and I've forgotten a lot ha ha ha.

for those that are interested, here is my updated code and output data file.

/*
  Analog input monitor
*/

// These constants won't change. They're used to give names to the pins used:
const int analogInPin1 = A0;  
const int analogInPin2 = A1;  

void setup() {
  // initialize serial communications at 9600 bps:
  Serial.begin(9600);
  pinMode(analogInPin1,INPUT_PULLUP);
  pinMode(analogInPin2,INPUT_PULLUP);
}

void loop() {

  // read the analog in value:
  // print the results to the Serial Monitor:
  Serial.print("A0 = ");
  Serial.print(analogRead(analogInPin1));
  Serial.print("\t A1 = ");
  Serial.print(analogRead(analogInPin2));


  if (analogRead(analogInPin1)<=50 and analogRead(analogInPin2)<=50) {
    Serial.println("\t SLOW UP");
  }
  else if (analogRead(analogInPin1)>=1000 and analogRead(analogInPin2)<=50) {
    Serial.println("\t SLOW DOWN");
  }
  else if (analogRead(analogInPin1)<=50 and analogRead(analogInPin2)>=1000) {
    Serial.println("\t FAST UP");
  }
  else if (analogRead(analogInPin1)>=1000 and analogRead(analogInPin2)>=1000 ) {
    Serial.println("\t FAST DOWN");
  }
  else if (analogRead(analogInPin1)<=50 and analogRead(analogInPin2)>=500 and analogRead(analogInPin2)<=600) {
    Serial.println("\t MED UP");
  }
  else if (analogRead(analogInPin1)>=1000 and analogRead(analogInPin2)>=500 and analogRead(analogInPin2)<=600) {
    Serial.println("\t MED DOWN");
  }
  else {
    Serial.println("\t STOPPED");
  }
  // wait 2 milliseconds before the next loop
  delay(2);
}

Output2.txt (14.4 KB)

Doing this and enabling the internal pull-up resistors ended up working the best

The internal pullups should not be used for this. Their value is not as precise or stable as external resistors, and will vary from pin to pin, chip to chip, and with circuit voltage and temperature. They are fine for their intended use, as pull-ups, where the exact resistance does not matter. But here you want to make a voltage divider to give a known, stable input to the pin when the switch is in the centre position.

Pin conservation, the struggle is real

With a careful choice of resistors, you could connect both switches to a single analog input, and get 9 different readings corresponding to the 9 possible combinations of switch positions.

You would still have the 10K from the analog pin to 5V and 10K from the pin to ground. Then connect the centre tag of one switch to the pin with another 10K. The other 2 tags connect to 5V & ground. Connect the centre tag of the second switch to the pin with a higher value resistor like 22K (or 2x10K in series). Again, the other 2 tags of the second switch to go 5V & ground. Try that and test if the 9 different readings you get are sufficiently different from each other so that noise in the readings isn't enough to make the switch positions ambiguous.

PaulRB:
The internal pullups should not be used for this. Their value is not as precise or stable as external resistors, and will vary from pin to pin, chip to chip, and with circuit voltage and temperature. They are fine for their intended use, as pull-ups, where the exact resistance does not matter. But here you want to make a voltage divider to give a known, stable input to the pin when the switch is in the centre position.

I see, thats a handy piece of information.

PaulRB:
With a careful choice of resistors, you could connect both switches to a single analog input, and get 9 different readings corresponding to the 9 possible combinations of switch positions.

You would still have the 10K from the analog pin to 5V and 10K from the pin to ground. Then connect the centre tag of one switch to the pin with another 10K. The other 2 tags connect to 5V & ground. Connect the centre tag of the second switch to the pin with a higher value resistor like 22K (or 2x10K in series). Again, the other 2 tags of the second switch to go 5V & ground. Try that and test if the 9 different readings you get are sufficiently different from each other so that noise in the readings isn't enough to make the switch positions ambiguous.

Super clever, that looks like it will work. there a few values that are pretty close (less than 50 apart), but I will have to play around with it a bit more.

Random-noob:
there a few values that are pretty close (less than 50 apart)

Worse than that, some will be less than 15 apart if using 22K!

20K would be better, that would keep them at least around 30 apart.

18K better still, at least 45 apart.

Screenshot from 2020-05-30 11-41-38.png

Screenshot from 2020-05-30 11-41-38.png

PaulRB:
Worse than that, some will be less than 15 apart if using 22K!

20K would be better, that would keep them at least around 30 apart.

18K better still, at least 45 apart.

Screenshot from 2020-05-30 11-41-38.png

By sheer accident I actually found 32k worked the best.

I was testing everything with a bunch of resistors in series, but I got more resistors in yesterday and when I was testing out the 22k I only took out one of my 10k. :roll_eyes:

At least from everything I have seen it all seems to be reproduceable to +/- 1

Great! What circuit have you used to get readings from 0 to 1023?

I'm using the simple voltage divider for testing, once get my stepper motor moving I'll switch over to this one.

If I remember how to draw circuit diagrams correctly I think it looks like this.

Random-noob:
I think it looks like this.

How can any combination of switch positions produce a reading of 0 or 1023? That's what I was asking. The reason I was asking is because I was trying to think of a way to achieve that earlier, but I couldn't.

PaulRB:
How can any combination of switch positions produce a reading of 0 or 1023? That's what I was asking. The reason I was asking is because I was trying to think of a way to achieve that earlier, but I couldn't.

Ah I see.

Since terminal 3 (T3) on both switches is connected to ground, if both switches are set to T3 then everything is going directly to ground and equals 0.

Terminal 1 (T1) on both switches is connected to 5V.

So if STDP1 is set to T1 and STDP2 is set to T3 then there is 3.82V at A0.

And if STDP1 is set to T3 and STDP2 is set to T1 then there is 1.19V at A0.

Thus if both switches are set to T1 then that adds up to a full 5V at A0 which reads 1023.

I measured all the values and thought that made sense since there is 3 times the resistance coming out of STDP2 as there is coming out of STDP1.


Ah, I get it, good thinking.