Go Down

Topic: quesetion about interfacing with rotary switch (Read 1 time) previous topic - next topic

wrybread

I picked up an old 11 position rotary switch:

http://www.smcelectronics.com/SWROT06.JPG
http://www.smcelectronics.com/DOWNLOADS/SWROT06.PDF

I'm not sure what the technical way to describe it is, but it has one pin that I'd call "common", and 11 pins that make contact with the common pin as the switch changes position.

I'm wondering what the proper and most efficient way to connect this to the arduino is. Do I connect what I'm calling the "common" pin to +5v, and each of the other pins to ground via a resistor and then to an input pin on the arduino?

Is there a more efficient way than connecting each output pin of the switch to both ground and an input pin?

Thanks for any help.

Grumpy_Mike

Connect the common to zero volts or ground. The you could connect each of the other pins to an Arduino input pin but this does take up a lot of pins. Alternately you can use one or more of:-
# 74147: 10-Line to 4-Line Priority Encoder
# 74148: 8-Line to 3-Line Priority Encoder

To encode the 11 inputs into a 4 bit binary number.

wrybread

#2
Apr 01, 2009, 11:47 pm Last Edit: Apr 01, 2009, 11:59 pm by wrybread Reason: 1
I'm trying that but its super flaky. It'll read the input correctly a few times and then stop. But if I touch the rotary switch it'll then read it again.

Interestingly if I touch or even put my hand near the ground wire or input wires, it then reads it correctly again.

Is that a debounce issue?

retrolefty

Most likely the effects of "floating" inputs. You should either wire external pull up resistors or activate the internal pull-ups associated with the digital input pins being used.

Lefty

Grumpy_Mike

Just thought of another way to do what you are after last night. Put 1K resistors between each of the pins, with the last connected to ground and the last on the other end connected to +5V. Then take the common and connect it to an analogue input and read the voltage.

Quote
interestingly if I touch or even put my hand near the ground wire or input wires, it then reads it correctly again.


Enable the pull upp resistors on you pin inputs by doing a :-
digitalWrite(pin, HIGH);
On all your input pins during the setup.

wrybread

Quote
Put 1K resistors between each of the pins, with the last connected to ground and the last on the other end connected to +5V


Tasty! I'll give this a try when I get home on Monday.

I've been experimenting with a pot and simulating a rotary switch by making each range of the pot be a different setting, broken into 10 parts. This works works but it definitely lacks the nice satisfying "click" of a true rotary switch.

Thanks, this is really a great idea.

Anachrocomputer

Quote
Interestingly if I touch or even put my hand near the ground wire or input wires, it then reads it correctly again.


Definitely sounds like floating input pins.  You'll need 11 pull-up resistors (about 10k Ohms).

Andy Brown

#7
Jul 15, 2010, 10:49 pm Last Edit: Jul 15, 2010, 10:53 pm by foxbat Reason: 1
Quote

Just thought of another way to do what you are after last night. Put 1K resistors between each of the pins, with the last connected to ground and the last on the other end connected to +5V. Then take the common and connect it to an analogue input and read the voltage.


This is a great technique. Only one pin required regardless of the number of stops. Here's a C++ fragment to decode the analog pin value into an integer switch stop number without the need for calibration or hardcoding stop values  :)


Code: [Select]

class RotarySwitchImpl
{
private:
     int _analogPin;
     int _numberOfStops;
     
public:
     void setup(int analogPin_,int numberOfStops_);
     int readPosition();
};



Code: [Select]

void RotarySwitchImpl::setup(int analogPin_,int numberOfStops_)
{
     _analogPin=analogPin_;
     _numberOfStops=numberOfStops_;
}


int RotarySwitchImpl::readPosition()
{
     int idealStep,value,i,nearestStop,diff,nearestDiff;

     value=analogRead(_analogPin);
     idealStep=1024/(_numberOfStops-1);

     for(i=0;i<_numberOfStops;i++)
     {
           diff=abs(value-i*idealStep);
           if(i==0 || diff<nearestDiff)
           {
                 nearestDiff=diff;
                 nearestStop=i;
           }
     }

     return nearestStop;
}
Home of the Nokia QVGA TFT LCD hacks: http://andybrown.me.uk

lol3BB

Hello, that's my first post here.
Will it work when I connect the common to the digital instead of analog input? I've ran out of analog's in my project. How should I change the code then?

lol3BB


Ran Talbott

If you have a spare analog pin,  you could wire up the switch sort of like a "stepped potentiometer".

Start with a resistor of about 1/2 a K (470 or 510).  Hook one end to +5,  and the other to the "common" pin of the switch.  Then hook up the other pins to ground through increasingly-large resistors:  .5K, 1K, 1.5K, etc.

That'll give you a voltage at the "common" pin that starts at about 2.5V,  and steps up to about 4.5V.  To make it easier to decode in software,  you can pick the resistor values so the voltage increases in fairly-consistent steps.  But you'll still need to do a fuzzy comparison to the A/D value,  because it'll vary by a few counts from one pass to the next.

Go Up