Rotary Encoders (and interrupts)

Hi

I'm designing some projects that need multiple rotary encoders (let's say 6) to be read by a single Arduino. I've searched the forums and found useful stuff in the playground under rotary encoders at - http://www.arduino.cc/playground/Main/RotaryEncoders (although I can't find the referrence to encoders.h anywhere in my dev environment).

The nature of my project means I must use interrupts with the 6 rotary encoders so I need the functionality where any movement on any encoder fires an Arduino interrupt. Would using an MCP23016 with the Wire Library and I2C be overkill? If you have any relevant experience or suggestions I'd love to hear it because I'm a bit stuck with this one.

In the forums I've found these which have been useful... - http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1233843430- http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1205879808- http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1205879808 and various others.

Thanks, Paul.

when you spin a rotary encoder it doesnt just send 1 signal so you will probally want to dumb its signal down

when I did "pimp my pong" I had a situation where the pong game had its inputs hooked up to basic on off tactile switches, I wanted a paddle to marry the 2 I used a 74hc74, that is a dual type D flip flop chip, which reduced the encoders output to simple pulses on 2 output pins, one for "up" one for "down"

course if you spin the thing 10 clicks in 1 direction you get 10 output pulses which may cause you problems

http://www.piclist.com/images/www/hobby_elec/e_ckt10_3.htm

the above is where I found the mentioned "up down" circuit

For my implementaton, each 'click' of the rotary encoder will need to be sensed & either add one or subtract one from a counter in order to control software, so when I spin it 10 clicks in one direction it's important I get them and react to them. Well, fairly important - the nature of the application means I can skip the odd one :-)

Thanks for the information and the link - great stuff about chatter!

I still have to get my head around how I'm going to wire all this together. I'm hoping someone's done something similar and I don't have to reinvent the wheel - there's enough else to do for this project.

Paul.

if you need a 1:1 click to int ratio then the 7474 found on that page will do the trick, but two directions it will need 2 inputs per encoder (again one for up or down, which from here on out we will call ccw and cw)

depending on how much other stuff you need to hook up it may not work for you

Ok i cant stand it, what is "the project" :D

First if would be helpful to determine how fast the encoder signals can spin for the six encoders, because if they turn too fast then interrupts are needed, but there are not enough user interrupts on a standard Arduino (pins 2 & 3 only) to support six encoders. It is possible to use full port interrupts (generates an interrupt if any of the 8 bits of a port changer), but that's not an Arduino core command and you would have to work out the low level control registers software yourself.

If they turn slow enough you can read six encoders using 12 input pins, just using polled I/O operation. You can gain some speed in polling by using direct port access I/O commands. So to repeat, a lot depends on the maximum speed of the six encoders you are using.

Lefty

Heh heh, the project is for flight simulator control systems. An example is a mode control panel which will need lots of extras with a Duemilanove. I’m thinking generic Boeing 700 series. Taking the Altitude control knob as an example (and all the knobs work like this), turning cw needs to be passed from the Arduino to the control software on the pc so it can increase the altitude value, which can be read by more software and passed back to an array of seven segment LEDs through the Arduino. Ccw the other way too.

The 7474 is very cheap but I have more experience of higher level chips and software than lower level circuitry, so it’s still very tempting to go the MCP23016 route. Sigh I should really try to understand how the 7474 works before I write it off. Keep it coming!

Paul.

Hi Lefty,

Thanks for the response. There’s so much going on with the Arduino on this project that I suspect polling would be too slow. The only components that are timing critical here are these knobs and there’s 6 of them (at least!). The MCP23016 (proven to work with the Arduino) has an output pin that changes whenever any one of the inputs change so for this application I’d just connect that output to an Arduino interrupt and check in the interrupt handler which knob(s) were twiddled.

Also, thinking ahead, how fast the knob is turned (and for how long) can be used in software to give the control a more intuitive feel, which is how I suspect it’s done on the aircraft. That will definately need to be interrupt driven.

Paul.

Yeah, the interrupt on change from the MPC23016 is going to get you the notice that you need to read the encoders. But that is ALL you get in the interrupt.

Then you have to go read the i2c, which you aren't going to do in an interrupt service routine, to get the values, and run them through the quadrature decoders. That isn't very fast, but it's pretty easy.

I think the tradeoff here is what skills you have, what your budget is, and how much time you have.

The MPC is gonna work, pretty much for sure, and it's not going to take a whole lot of your time to get it to work, as long as you understand how the quadrature signals show up and how you decode them. It also uses minimum pins on the Arduino. On the other hand, it's expensive, and its slow.

If your programming skills are up to it, and your budget is strapped, and you have some time, then I'd try to get the interrupt on any bit change feature in the AVR to work, hook the encoders directly to the Arduino pins (and I'd be looking at a MEGA or something else with a 644) and skip the i2c.

I guess you also have to decide how many pins you need for the rest of the problem: you may need some kind of port expander no matter what. The MPC is an expensive port expander, but it is pretty easy to use. I would think burning pins on encoders is better then burning them on 7 segment displays, but I don't know how many displays, or what else the Arduino has to do.

Sounds like a cool project tho.

Hi brtech

Thanks for your input, it's all good. The way I understand it should work (and I could very well be wrong here - my status should really be über-newbie) is that the rotary switch is moved, the MPC will generate an interrupt on the Arduino so the interrupt handler I have written will fire and I can do what I need to - either fully handle it or at the very least update a variable so I can handle it when the main program loop gets to it. Is there something stopping me using Wire to read the MPC from an interrupt handler? I've had a quick look around but I can't see anything. As for the money, an MPC only costs an extra US$1 to the project, a MEGA is more than double the cost of a Duemilanove.

There are lots of other inputs and outputs in this project but they're all much more straight forward and I've got circuitry I'm quite confident can handle all that although I have lots of testing to do over the next couple of months! The most challenging part of it will be to make 6 rotary encoders work on a Duemilanove and posts like yours help by forcing me to look at all the options. Now, I wonder where I can find out more about the interrupt on any bit-change thing ... ? :-?

Paul.

Yeah, you get an Arduino interrupt (the MCP output has to be on pin 2 or 3 of the Arduino). What you can't do in the ISR is to read the MPC. That's an entire I2C transaction, and I don' think you want to do that in the ISR. So you want to set a flag in the ISR and run the MPC read in the main loop, along with the quadrature decode.

That will work, but may not get you much more than a timed poll of the encoder state would.

Like any thing else, start small. Hook one encoder to 2 pins of the Arduino and get that to work first. Then, if you are going to use the MPC, hook a switch to it and get that to work. Then get an encoder working on the MPC with a simple loop poll, then more than one encoder, and then do the Interrupt.

If you want a bigger Arduino without doubling cost, look into a Sanguino.

More great information! I need to be reminded to start small because it's so tempting to get stuck in all the ideas as they develop, then dive straight in on the last one I have. I'm feeling a development system coming on.

If it is possible to to do the I2C transaction in the Interrrupt Service Routine, the nature of this project means that it doesn't matter if everything else is held up because it takes a long time. Or at least that's where I am with it at the moment. First stage 'proof-of-concept' breadboard testing will show if it's viable or not before I start wielding the soldering iron :-/

Any pointers from anyone to similar/relevant existing schematics would be very welcome.

Paul.

I was just looking at goldmine for a power supply, and noticed they have some really nice rotary encoders for $.99. They are new, 30 steps. They even have a momentary push switch (and don't forget folks, since it's all software, momentary can be turned into alternate on/off with code). http://www.goldmine-elec-products.com/prodinfo.asp?number=G16267

Goldmine has a $10 minimum, and fairly high shipping costs for small orders. They still have the 24 x 1 LCD for $.99, a $7 16 x 2 LCD, a $2.29 =5V 700 ma wall wart (with a weird DC connector) and several other decent parts to make up a good order. I even noticed a $2 pactec case that has a battery compartment.

That encoder from electric gold-mine is not worth the 99 cents. In my opinion.

In any mechanical encoder, there is going to be a lot of bouncing. You'll need to figure out a way to handle that.

Optical encoders would be easier to deal with, since they don't have bounce issues.

More issues! If electronics was easy, I'd have given up years ago and moved onto making wine. This is worth a read ... http://en.wikipedia.org/wiki/Rotary_encoder.

For my project I'm looking at using "An incremental rotary encoder, also known as a quadrature encoder or a relative rotary encoder ..."

This is also interesting http://sensors-transducers.globalspec.com/LearnMore/Sensors_Transducers_Detectors/Encoders_Resolvers/Encoder_Incremental_Rotary

Here in the UK Maplin do these http://www.maplin.co.uk/module.aspx?TabID=1&criteria=usb&ModuleNo=2417&C=SO&U=Strat15.

But this one from RS is looking favorite (2nd link is the datasheet) http://uk.rs-online.com/web/search/searchBrowseAction.html?method=getProduct&R=0320180 http://docs-europe.origin.electrocomponents.com/webdocs/007a/0900766b8007a1e8.pdf

Around 1-2US$ I can live with but the optical versions are looking WAY more expensive. Am I correct? Why can't I find any when you can make them yourself like this ... ?

http://yo6pir.files.wordpress.com/2009/04/rotary-encoder.pdf

Perhaps I'm not looking hard enough :-[ Paul.

Hi all, I'm playing with rotary encoders too. Just bought an optical one from Greyhill (Series 61 are readily available) and yep they are expensive.(around $60AU) but very good. I'm planning to use mine from a timer interrupt as I'm doing critical timing. I'm going to drive two pins of my miniA via a 4013 dual D flipflop so as not to cause any jitter and allowing read from within intrpt. Only downside is need to clear the flipflops after the read. so needs another line. Seems this scheme might work with any number of encoders; the only limit to the read speed being the interrupt rate. A relatively slow rate could still easily count a 32 step encoder spun by hand. I hope. should know soon if it all comes together.

Wow! Yes, just checked them out. Too expensive for my project but nice quality and selection. It’d be great if you could post the results of your playings.

Paul.

Hmm, I like the idea of using cheap mechanical switches instead of expensive opto's. I was reminded of the humble 555 timer in my browsing through "Practical Electronics for Inventors" (pub McGraw-Hill), and how it can be used for "bounce-free switches". A web search bought this up ...

http://www.ecelab.com/circuit-debouncer-555.htm.

2 x 558 timer packages = 8 timers/switch debouncers (only need 6 of them). Cost is about $2.50US.

Exciting times Grin

Debounce in software.

Write once, share, everyone gets to use cheap encoders.

It's pretty easy because the transitions happen in a sequence that involves two signals, so if you get a LOW to HIGH and then a HIGH to LOW transition without the other signal changing, it has to be a bounce.

brtech.

Absolutely! Share, share and share some more.

In my research I've found there are 2 approaches to controlling bounce, hardware and software. I have some basic (and rusty) hardware skills but I've been an IT professional for 20 years so my main skills are in the software/microcontroller areas.

Unfortunately, the software solution involves waiting for those transitions and there's so much going on in this project that the wait could be a problem. The hardware solutions I'm considering will mean presenting a clean transition and it'll be cheap - cheap, noisy rotary encoder + cheap, simple cleanup components.

Believe me, if there was any way I could implement this problem in software, I would. There'd be almost no learning curve for me so it'd be quick and easy. As with most things in life, there's a tradeoff amongst many competing factors.

When I make this damn thing work, I will certainly be sharing the solution on here.

Back to specifics, a night of caffeine fuelled contemplation has pointed me away from the 555 solution. Which brings me to a basic electronics question. Can a CMOS logic output drive multiple CMOS logic inputs directly? If so, how many? are there extra components needed? The answer to this question is based on what the standard outputs and inputs are for these types of components, is there an easy way to find out this information?

Here's an example of what I'm asking ...

Forget the left hand side, my question has to do with the right hand side of this partial schematic.

Considering the output from the Schmitt trigger IC1A, is this electrically valid with no other components such as resistors capacitors etc?

Paul.

Paul, the output drive (also called "fan out" of a HC part is about 10. That means one output can reliably drive 10 HC inputs. (It's actually a bit higher than 10, but it doesn't hurt to be conservative here!)

If you're connecting the output directly to the arduino inputs, you'll need to check what the input current (or "standard load" or "fan in") is. If it's higher than a HC part (and it is) then you won't be able to drive so many inputs. Based on a quick squiz at the specs for the MCU,you should be able to drive at least 4 inputs reliably from one HC output.

Using a port expander means that your code will need to keep polling the expander via I2C reads to check for button presses, and you'll have to debounce in software if you use a mechanical encoder. That's a huge amount of overhead, so I'd rethink that option.

FWIW, I have a robot board (my own design, non-arduino, sorry :() that I needed to read 4 encoder inputs. In my case, I opted to go for a dedicated PIC 24FJ16GA002. (It's a slim 28-pin through-hole part so it's easy to breadboard.) This has 5 16-bit timers, 4 of which can be triggered by pin changes. So I've programmed it so that each encoder is connected to a timer input, and all that does is count down. Then, at any arbitrary time, I "read" the PIC24 using the other port pins on that controller to get the timer count for each input. This takes a few extra pins, and it would actually be pretty simple to provide I2C ability to read the timers. One of the really nice things about the 24FJ series chips is that you can re-route the pins to suit your board layout. Very cool, but more development time unfortunately! :-X

To drive the PIC, I bought some excellent Fairchild QRB1134 optical pickups from Junun Robotics (http://www.junun.org/MarkIII/Info.jsp?item=14), and I used the simple rotary encoder renderer written in PostScript from http://research.meei.harvard.edu/epl/Engineering/encoderdisk.html. You don't NEED postscript, if you have Photoshop it will load the file and render right on your screen, and you can then print it out, and of course you can change the resolution, whether it has quadrature (direction-sensing) steps, and much more.

I hope this gives you some ideas. I realise the PIC isn't a solution for the faint-hearted, but I'm already using a RTOS and native I2C drivers for accellerometers and multiple sonars and GPS, and it was easier to read the encoder data as a byte-wide count that I could then timestamp to normalise the encoder count, etc, etc.

Good luck!