Interfacing A Digital Rotary Switch

digital_rotary_switch

[hw640] has put together a well written and detail packed explanation of how to interface with a digital rotary switch. These digital opto encoders have just two outputs with four possible logic levels (00, 10, 11, 01). The relative position of the switch is insignificant but the direction of rotation is what matters.

The short and dirty: Each of the switch’s 2 output pins is attached to a pin change interrupt on the microcontroller. Every time the switch moves it generates either a rising edge or a falling edge on one of the two pins; both edges cause an interrupt. By checking which pin caused the interrupt, then comparing the logic levels of the two pins after that interrupt, we can determine the direction the switch was rotated.

Although this explanation uses a PIC and code written in PicBasic Pro the concepts are discussed in the abstract and would easily be adapted to an AVR or another microcontroller of your choice.

19 thoughts on “Interfacing A Digital Rotary Switch

  1. a nice replacement for potentiometers and up/down-buttons. But one interrupt and a digital input pin should be enough, there are µC with only few interrupt pins.
    Interrupt -> look if pin is high (-> rotation left) or low (-> rotation right). But dont forget to set the interrupt on rising/falling edge :-)

  2. props for the pic posting. microchip products seem to go relatively unnoticed in the wake of all this arduino bs. It should be noted (perhaps the tutorial does this) that certain pics come with quadrature interfaces built directly into the hardware, in addition to multiple pwm modules.

  3. Too weird, I’ve been wanting to play with a rotary encoder hooked up to a PICAXE chip for the past week, but I’ve lost my bag full of old/broken mice to steal a scrollwheel from :(

  4. Very nice. I like to do these with analog pins and voltage dividers (you can easily have 2 or 3 working off a single pin). But this does require more processing time to calculate the direction.

  5. @talking jazz: clever, never thought of the analog approach.

    …and I’ve got one of the pictured encoders – I found it very disappointing… Though reasonably expensive (from digikey), it’s very rickety and cheap feeling. The detents make a very plasticy click when rotating the knob and the pushbutton bounces something fierce. I’m a big fan of rotary encoders for input, but I’d recommend a differnt model.

  6. @medix Why the arduino hate? People like you are ruining hack-a-day. The arduino opens up a lot of doors to beginning hackers, and even opens new doors do experienced hackers. The creation of the arduino itself was a cool hack! So knock it off.

  7. i would have thought that quadrature encoding would be old hat by now… this is the same kind of interface that mice have been using for years, and a million robotic projects use the same idea for motion tracking.

  8. Using edge interrupts is how you NOT interface a rotary encoder. Products that do it like this are the ones that you curse about when after a few years turning the knob causes erratic jumps in volume or whatever you are controlling with it. The reason is that corrosion on the conductive traces or just the inexactness of the mechanics causes several additional short impulses whenever you turn the knob, not the nice one-impulse-per-step signals the article shows. Another problem is that using edge interrupts causes unpredictable timing of your program.

    A better way is to sample the inputs at a fixed rate (e.g., 1 kHz for human-turned knobs) and to use a small lookup table to tell apart valid from invalid state transitions. Unfortunately I don’t have a link to an explanation at hand (at least not in English).

  9. Instead of checking for changes on two pins, you can free up resources by only checking the pin for the least significant pin since the LSB would change every time MSB does.

  10. I remember this problem from a combinational logic class (no processor needed) I took … er … a looong time ago … :-). (No! it *was* after we landed on the moon, thank you, not.)

    “spacecoyote: i don’t see how that would work; this switch has 3 states: at rest, rotating left, and rotating right.”

    No no, you are 1 jump ahead of the game. You are describing the output of the uP. We want to *derive* that information from only knowing the past state (for example 01) and the next state (say 11). Then, given that we assume rotating clockwise will give us the sequence of numbers 00 01 11 10, we can conclude we are rotating clockwise. (So…bla bla bla if we see 00 then 10 bla bla bla rotating counter clockwise…)

    “Agent420: i would have thought that quadrature encoding would be old hat by now… this is the same kind of interface that mice have been using for years, and a million robotic projects use the same idea for motion tracking.”

    I am thinking this as well – people this is OLD school, really old. As this is hackaday.com – why doesn’t someone do something really interesting!

    How’s about someone hack a mouse and make a linear relative positioning thingy. Think of something you could slide back and fourth where knowing where it was, how fast it was moving or its direction is of value. Paint it with black and white strips and position the two light sensitive quadrature inputs from the mouse such that they are closer together then the width of any 1 stripe. Ideally half the width of a strip. The rest is easy as mice were design to interface with computers.

    Start hack’n…

  11. This implementation is fine if you’re using an optical or magnetic quadrature encoder. But for a mechanical one, like the one depicted, it’s awful. What I ended up doing was using transitions on either phase to mark clock pulses (removing duplicates), and keeping track of the last 3 transitions — it works pretty well (99%; the rest of the time the outputs are still bouncing before we transition to the next phase)

  12. Found a dead mouse yesterday and whipped the scrollwheel out of it, hooked it up to a PICAXE and began programming.
    I looked at some code others had written to read the rotary encoder but couldn’t quite work out how they were determining which direction the dial was turning, so I wrote my own code from scratch and got it down to about 20 lines to adjust the brightness of an LED, including lighting up two other LEDs which showed wether the main LED was getting brighter or dimmer.

    Now I’ve got to find a use for such a piece of code :)

Leave a Reply

Please be kind and respectful to help make the comments section excellent. (Comment Policy)

This site uses Akismet to reduce spam. Learn how your comment data is processed.