Rotary Switches

Hello!

I'm new at arduino and I'm really stuck, been searching online for hours to figure it out. Can someone please help?

I am trying to make multiple rotary switches (2 poles 6 positions) work with an arduino uno, and not being able to. At the moment I'm only wiring up 2 rotary switches, but only one works. I already made sure they're not broken, so they do work individually, but I cant get readings from both at the same time. So the code runs well, except that one of the rotary switches' readings is always "not working". Is there maybe something about wiring multiple rotary switches to an arduino that I'm missing?

I do not want to use potentiometers (even though ideal because less pins to wire up....) because i need the knobs of my art installation to have that "click" feel when turning, rather than being a smooth rotation.

Here's my code, please ignore the terrible naming and yes, I know I should use variable arrays instead.
Thank you in advance!! :slight_smile:

const int RotaryPinone = 2;
const int RotaryPintwo = 3;
const int RotaryPinthree = 4;
const int RotaryPinfour = 5;
const int RotaryPinfive = 6;
const int RotaryPinsix = 7;

const int RotaryOne = 8;
const int RotaryTwo = 9;
const int Rotarythree = 10;
const int RotaryFour = 11;
const int RotaryFive = 12;
const int RotarySix = 13;

void setup() {
for( int i=RotaryPinone; i<= RotaryPinsix; i++) {
pinMode( i, INPUT);
digitalWrite( i, HIGH); // turn on internal pullup resistor
}
Serial.begin(9600); // let's talk to the world
Serial.println("RotarySwitch ready!");

for( int x=RotaryOne; x<= RotarySix; x++) {
pinMode( x, INPUT);
digitalWrite( x, HIGH); // turn on internal pullup resistor
}
Serial.println("Rotary2nd ready!");
}

// returns the position of the rotary switch, 1-4
// or returns 0 if no rotary switch is hooked up

int getRotaryValue() {
for( int i=RotaryPinone; i<= RotaryPinsix; i++) {
int val = digitalRead( i ); // look at a rotary switch input
if( val == LOW ) { // it's selected
return (i - RotaryPinone + 1); // return a value that ranges 1 - 5
}
}
return 0; // error case
}

int getRotaryValue2() {
for( int x=RotaryOne; x<= RotarySix; x++) {
int val = digitalRead( x ); // look at a rotary switch input
if( val == LOW ) { // it's selected
return (x - RotaryOne + 1); // return a value that ranges 1 - 5
}
}
return 0; // error case
}

void loop() {
int rotaryPos = getRotaryValue();

if( rotaryPos == 1 ) {
Serial.println("1");
}
else if( rotaryPos == 2 ) {
Serial.println("2");
}
else if( rotaryPos == 3 ) {
Serial.println("3");
}
else if( rotaryPos == 4 ) {
Serial.println("4");
}
else if( rotaryPos == 5 ) {
Serial.println("5");
}
else if( rotaryPos == 6 ) {
Serial.println("6");
}
else if( rotaryPos == 7 ) {
Serial.println("7");
}
else {
Serial.println("uh oh, somethings wrong");
}
delay(100); // slow down the loop() so we don't spam the serial port

int rotaryPos2 = getRotaryValue2();

if( rotaryPos2 ==8 ) {
Serial.println("8");
}
else if( rotaryPos2 == 9 ) {
Serial.println("9");
}
else if( rotaryPos2 == 10 ) {
Serial.println("10");
}
else if( rotaryPos2 == 11 ) {
Serial.println("11");
}
else if( rotaryPos2 == 12 ) {
Serial.println("12");
}
else if( rotaryPos2 == 13 ) {
Serial.println("13");
}
else {
Serial.println("NOT WORKING");
}
delay(100);

}

Please click the More button in the bottom right and select MODIFY
Highlight ONLY your code
Click the CODE TAGS toolbutton ("</>") (top row, first on the left)
Click the SAVE button.

Then read this

When you have finished reading that,
draw a schematic of how you have your rotary switches are wired on a blank sheet of printer paper
photograph it
post it as an attachment using the "Attachments and other options " link below
Click SAVE
Put the mouse cursor over the attachment file and right click the mouse button and select "copy link address"
Click MODIFY
Click the "insert image toolbutton " (computer monitor icon)
Right click and select "paste"
Click OK
Click SAVE
Then wait for a reply.

  for( int x=RotaryOne; x<= RotarySix; x++) { 
    pinMode( x, INPUT); 
    digitalWrite( x, HIGH); // turn on internal pullup resistor
  }

This only works if your pins are continuous between "one" and "six". Your pin assignments are going to change and you might have "two" connected to pin 13 in the future. That's not going to work.

Look up arrays. Every time you are tempted to have numbered variables, you probably need an array instead. That will allow you to use more calculations rather than "one" to "six".

Another fun way of using these switches which doesn't use up all of your digital pins is to use an analog pin. Connect a 1K resistor between each pin (5 resistors), one end of that string goes to IOREF (5v), the other to ground. Then the 'wiper' center contact goes to an analog pin. You can read out the switch position by comparing the analog value to a fixed set of reference values.

Then put that code into a function, call it readRotaryOne() or something. (Yes, you can have arrays of functions but if you're only going to have two, it may not be worthwhile making it an array.)

@MorganS,

Looking at the pinout of two rotary switches

and looking at the OP's code, doesn't it seem confusing with the pin names he has chosen ?

Wouldn't it be easier to follow the code if the rotary switch terminals were labeled as follows ?

Rotary Sw-A
sw_A_1
sw_A_2
sw_A_3
sw_A_4
sw_A_5
sw_A_6

Rotary Sw-B
sw_B_1
sw_B_2
sw_B_3
sw_B_4
sw_B_5
sw_B_6

@joanne5,
Why are you doing this ? Sometimes it helps if you tell us the "big picture".
Your post seems to be about reading rotary switches and nothing else.
Usually , posts have an objective, like a project. Your post is not (or at least does not seem to be) a project.
It looks more like (to us at least) , a school assignment.
While I know to you (being as you only registered a little or an hour ago) it might seem funny to hear this but almost ALL school assignments start with the following line: (with a few deviations):

I'm new at arduino and I'm really stuck, been searching online for hours to figure it out. Can someone please help?

Maybe you have never seen this before,but we have seen it countless times.
There doesn't seem to be any point to your post other than to learn how to read the switches, which by itself , has no value , unless it is a school assignment. Most people start their post by describing the goal, like to have a "black box" with rotary switches on it. Choosing some switch position makes something happen. They may start with the idea of using rotary switches and then after some suggestions decide to upgrade to rotary encoders. So , Joanne, why are you doing this ?

Some basic ideas for you.

These can all be byte vs int, save space in SRAM

const int RotaryPinone = 2;
const int RotaryPintwo = 3;
const int RotaryPinthree = 4;
const int RotaryPinfour = 5;
const int RotaryPinfive = 6;
const int RotaryPinsix = 7;

const int RotaryOne = 8;
const int RotaryTwo = 9;
const int Rotarythree = 10;
const int RotaryFour = 11;
const int RotaryFive = 12;
const int RotarySix = 13;

Then use arrays as suggested:

byte rotaryArrayPins[] = {2,3,4,5,6,7,8,9,10,11,12,13,}; // rotaryArrayPins[0] = 2

Wire the common to Gnd, and the internal pullup resistors

for (x=0; x<12; x=x+1){
pinMode (rotaryArrayPins[x], INPUT_PULLUP);
}

Loop thru the pins to see which is low:

for (x=0; x<12; x=x+1){
if digitalRead(rotaryArrrayPins[x] == LOW){
// my=maybe store results in a 2nd array
pinsLevel[x] = 0;
Serial.print ("Low pin detected, pin = ");
Serial.println (rotaryArrayPins[x] + 2); // add 2 since pinsArray[0] = 2.
}
else {pinsLevel[x] = 1;
}

Can make the code short & sweet for repetitive stuff.

@CrossRoads @MorganS thank you for your replies, i am going to try this right now and will keep you posted. Concerning the analog reading, I had seen something similar yesterday (http://letsmakerobots.com/node/27631) but was told that i was doing something stupid as i can just use arduino's internal pullup resistor, rather than using all these resistors. Makes sense though since i'm doing analog instead of digital readings....

@raschemmel you seem to be quite angry at my post, sorry about that. This is not just a "school assignment", I simply didn't think that writing my entire project's description would make the post any more relevant to you guys. Basically, i am doing an interactive game art installation, which will be exhibited in London in a couple of weeks.
The project is about the act of profiling in the context of U.S. drone strikes and algorithmic kill lists. In short, the participant will have to control a couple of knobs (hence rotary switches) and buttons through arduino as input, 'talking' to a python code which is the game's engine (containing a library of human profiles and characteristics that I'm working on), which will, depending on the input, send out the correspondent videos to 64x64 LED matrix modules (in total 9 of them) which I'm wiring in chain, and controlling via raspberry pi 3.

@raschemmel you seem to be quite angry at my post,

I don't see anything in my post denoting anger. You must be reading between the lines. Please quote whatever I said that led you to believe I was angry. I reread my post and all I see is comments and questions. Where is the anger in that ? Asking you why are doing this shouldn't make you think I am angry. It should make you think I am curious about your project and nothing more. I don't see why asking you if this is a school project would indicate anger. It's a simply yes or no question.

Asside from the word "YOU" do you see any ALL CAPS ?
Is there a single "!" in my post ?
Please don't read anger into a post that isn't there. If you see it there , you should quote it and ask "Did you mean to sound angry when you said this ?" I think that is only fair.

You may not be aware of it but it is very inconvenient when a new poster doesn't use the code tags toolbutton. Please fix your code.

This is not just a "school assignment", I simply didn't think that writing my entire project's description would make the post any more relevant to you guys. Basically, i am doing an interactive game art installation, which will be exhibited in London in a couple of weeks.
The project is about the act of profiling in the context of U.S. drone strikes and algorithmic kill lists. In short, the participant will have to control a couple of knobs (hence rotary switches) and buttons through arduino as input, 'talking' to a python code which is the game's engine (containing a library of human profiles and characteristics that I'm working on), which will, depending on the input, send out the correspondent videos to 64x64 LED matrix modules (in total 9 of them) which I'm wiring in chain, and controlling via raspberry pi 3.

Sound interesting. Let us know how it goes.
As far as digital vs analog switch input. Both work equally well. I think the rationale for one over the other is obvious. As MorganS , pointed out , why use up all you digital inputs when you can accomplish the same goal with one or two analog inputs ?

I am trying to make multiple rotary switches (2 poles 6 positions)

Do you have 2 of these rotary switches or one ? Are you detecting two halves of the same switch or one half each of two separate rotary switches, each with their own shaft ?

Has it occurred to you that knowing you were making a video game might lead to the suggestion to use a rotary encoder to give you more functionality ?

@Crossroads,
I think "x" needs to be defined here or in the definitions

for (x=0; x<12; x=x+1){
pinMode (rotaryArrayPins[x], INPUT_PULLUP);
}

and here:

for (x=0; x<12; x=x+1){
if digitalRead(rotaryArrrayPins[x] == LOW){
// my=maybe store results in a 2nd array
pinsLevel[x] = 0;
Serial.print ("Low pin detected, pin = ");
Serial.println (rotaryArrayPins[x] + 2); // add 2 since pinsArray[0] = 2.
}
else {pinsLevel[x] = 1;
}

joanne05:
This is not just a "school assignment", I simply didn't think that writing my entire project's description would make the post any more relevant to you guys.

No, but this is referred to as the "XY Problem", a favourite here.

There is a certain minimum amount of information required here, and a minimum standard of presentation described by the instructions linked at the top of every separate forum.

It is a concern for a start that you have not heeded those instructions when explained by raschemmel in reply #1 because he took considerable pains explaining them in detail. Choosing to shoot the messenger instead of following expert advice makes you, not him, look intransigent.

Now as mentioned regarding the "XY Problem", while you may have fixed on a 6 pole switch as your favourite, it is pretty obvious that you are the beginner and frankly, those replying are vastly more experienced. While it may be not unreasonable to actually use those switches, we do like to hear a full explanation of the actual requirements of the situation to see whether that choice stands up to scrutiny.

Salient aspects include:

  • You want the detent "click". OK, that's fine.
  • Do you need to label the six positions, or do you simply want six options? That is to say, do people need to know the topic from the escutcheon, or does the video display enumerate them, because that would make things much easier.
  • This is a public display, is it not? Do your six-position switches have end stops? Do you realise what happens to end stops when the public get to them? Have you thought about this? In general, a rotary encoder which has no end stops, is far more durable. And a rotary encoder only ever requires only two inputs to the Arduino for its rotary function.
    So as to the options. I note you understand the use of INPUT_PULLUP, albeit by the belt-and-braces approach of defining input mode and writing the pin HIGH. That's fine - I tend to do that myself as a legacy from the older versions of the IDE.

The use of a resistor ladder is probably clever but you need to perform the calibration procedure for it to work properly and I am somewhat averse to it due to my bad experiences with consumer devices which use it to encode their various control buttons. The other similar option is to use a basic diode matrix with three inputs from each switch. For six positions that requires six diodes per switch (the first three positions directly pull one line low, the other three positions use diodes to pull a different pair of the three lines low). That would be the solution I would advise and there are various ways of coding for it.

Speaking of coding, your code - which I really would prefer to see properly laid out using code tags after processing with "Auto Format" (under "Tools" or simply "Control-T") is pretty scattered!

  • Your CamelCase capitalisation of the "Rotary" variables is inconsistent.
  • You have six pins but
  • Your functions "return a value that ranges 1 - 5"
  • And you have eight print values from your if-else chains including the "default". This should be a switch/ case construct.
    I think I will leave it at that until further developments! Time for my sleep.

Hi,

Welcome to the forum.

Please read the first post in any forum entitled how to use this forum.
http://forum.arduino.cc/index.php/topic,148850.0.html
then look down to item #7 about how to post your code.
It will be formatted in a scrolling window that makes it easier to read.

Can you please post a copy of your circuit, in CAD or a picture of a hand drawn circuit in jpg, png?

Thanks .. Tom.... :slight_smile:

@Paul,
Thanks, and FYI I already have a working, tested sketch for reading the rotary switch. I bought 2 of them at "The Shack" ,(3 blocks from my house).
I would have posted the sketch yesterday but since the OP responds poorly to insructions (and apparently doesn't care to follow them) , reading anger into simple questions and comments where there is none, I decided not to post it because she might interpret that as anger as well. There's no need to calibrate the sketch. All you have to do is print the read values once and use them to add a S/W HYSTERESIS constant. No brainer. I haven't wired the second switch yet . I'll do that today but since it will be read using a different analog input I can just duplicate the circuit for sw-1 and use constants with the same values but different names ( like sw_A_1, and sw_B_1), compare the "A" values for sw-1 and the "B" values for sw-2.
( even though sw-1 values are the same as sw-2 values, they're read by different analog inputs. This method will support 6 switches on an UNO using all the analog inputs.
@joanne05,
"When you have eliminated all the possibilities ,save one, the remaining one must therefore be the truth..."

Hi,
How many rotary switches are you going to connect?
You can get potentiometers with DETENT feel to them, try digikey, farnell E14, RS.

Tom... :slight_smile:

Hi,
Your sketch looks like you are connecting every rotary switch pin to the digital input of the UNO.

Why don't you place resistors between the switch pins, and connect the ends of the string of resistors to +5v and gnd, then using analog input on the switch wiper, measure the voltage and then with a bit of software decode the switch position.

Less wiring and saves I/O pins.

Tom... :slight_smile:

"I think "x" needs to be defined here or in the definitions"
as do the arrays. Some things I leave as an exercise to the reader.

@ Crossroads,
ha, ha. The "reader" could use some exercise...
@Tom,
MorganS was the first to suggest the analog approach . I explained the reason for his suggestion.
I tested it successfully yesterday with one switch. Today I'll add the second switch.

I don't think so. The initial post showed good understanding, just unfamiliarity with arrays.

I got the second rotary switch working on A1 analog input.

TomGeorge:
Please read the first post in any forum entitled how to use this forum.
http://forum.arduino.cc/index.php/topic,148850.0.html
then look down to item #7 about how to post your code.
It will be formatted in a scrolling window that makes it easier to read.

Can you please post a copy of your circuit, in CAD or a picture of a hand drawn circuit in jpg, png?

As laid out in reply #1 perhaps?

raschemmel:
I already have a working, tested sketch for reading the rotary switch. I bought 2 of them at "The Shack" ,(3 blocks from my house).

So let me get this straight. You went and bought two switches purely for the exercise and to assist the evanescent OP?

raschemmel:
There's no need to calibrate the sketch. All you have to do is print the read values once and use them to add a S/W HYSTERESIS constant.

That process as you describe it would then be called "calibration".

TomGeorge:
Why don't you place resistors between the switch pins, and connect the ends of the string of resistors to +5v and gnd, then using analog input on the switch wiper, measure the voltage and then with a bit of software decode the switch position.

As laid out in reply #2 perhaps?

raschemmel:
I got the second rotary switch working on A1 analog input.

The next trick for "extra credit" is to get both rotary switches encoded to one analog input. :grinning:

Well, not exactly. I did it because it just sounded too easy. ( of course having a RadioShack 3 blocks away helped). I've never interfaced rotary switches anf it just sounded like a fun way to spend the weekend.

There's no need to calibrate the sketch. All you have to do is print the read values once and use them to add a S/W HYSTERESIS constant.
That process as you describe it would then be called "calibration".

Well, somehow the way you described made it sound like it took more than the 5 minutes that it took.

The next trick for "extra credit" is to get both rotary switches encoded to one analog input

Yeah, no. I tried that and the problem was the switchposition of switch A affected the voltage of the switch b voltage divider because the common connected to ground changed the all of the voltages at all of the points on both the switch A voltage divider and the switch B voltage divider. It's like a catch-22.
I could use some suggestions on how to add error checking so it will print an error message if one of the wires came loose and the voltage didn't fall into one of the six bands listed in the definitions.

@Paul,

Basically, i am doing an interactive game art installation, which will be exhibited in London in a couple of weeks.
The project is about the act of profiling in the context of U.S. drone strikes and algorithmic kill lists. In short, the participant will have to control a couple of knobs (hence rotary switches) and buttons through arduino as input, 'talking' to a python code which is the game's engine (containing a library of human profiles and characteristics that I'm working on), which will, depending on the input, send out the correspondent videos to 64x64 LED matrix modules (in total 9 of them) which I'm wiring in chain, and controlling via raspberry pi 3.

I have an 8x8 led matrix display. I was thinking of hooking it up so the rotary switches control the X & Y axis and determine which dot lights up on the led matrix. I could make a sort of game where one dot lights up , blinking slowly and another dot , controlled by the x,y, rotary switches is blinking faster . When you move the x,y coordinates the faster blinking dot tracks them and when you get that dot on top of the slower blinking dot the matrix display starts a 5 second countdown after which the display explodes in a pattern that starts in the center and moves outward in all directions at the same time. I have no idea how to write the code to do that but it sounds like a challenge.

The OP has not demonstated anything to indicate she deserves any help from us. Several posters have requested that the OP use code tags and instead she has just ignored everyone. If I were the only one requesting it then it would just seem like she was being uncooperative to spite me but she blew off everyone. I think they should lock the thread for showing a blatent disregard for forum rules. I'm still waiting for the OP to present some proof to substantiate the allegation that I seemed angry. You've seen my posts when I get frustrated with an OP ( with "!" and ALL CAPS and my initial reply in this post didn't even come close. There were no "!" and only ONE word in all caps. If the OP wants any help she'll have show cause for accusing me of "seeming quite angry" when there's nothing to support that accusation.

raschemmel:
I have an 8x8 led matrix display. I was thinking of hooking it up so the rotary switches control the X & Y axis and determine which dot lights up on the led matrix. I could make a sort of game where one dot lights up , blinking slowly and another dot , controlled by the x,y, rotary switches is blinking faster.

Sounds like something better implemented with rotary encoders!

For the number 3 reason in reply #7.

Sounds like something better implemented with rotary encoders!

I'll look into it.