Rotary Encoder - learn this if you have about 400 hours of time.

Hi;

My experience with rotary encoders is very frustrating. At first I load tutorial example, works. I add code and -POOF- the rotary signaling appears to become unstable. I understand the a/b signalling from a rotary encoder interface and have used high-grade "FANUC' mpg dial encoders to trigger CNC jog dial interface, through a linux basic pc software application. The little cheap plastic knobs are different, for reasons unknown to me - seems to send at least twice and sometimes 4 times more triggers very fast for each click of a dial, where the pro-grade FANUC dials just simply send one for every click.

My application uses lots of delays and such. Its musical, so it plays notes, on, off, delay, etc... "select a program, push to play" type of thing.

So I can play a song, then the application appears to become unstable - I rotate in either direction and it skips about 2, 4, 8 or whatever number of signals. This has consumed so much time - I feel I need to switch to experiment using TFT touchscreen interface, and ditch using a rotary encoder - just to push the project along, though it is not my ideal intent. I am only using ONE rotary encoder now, and to think I could possibly add 2 or 3 more seems too overwhelming - for a sophisticated processor that handles millions of executions PER SECOND to simply take a couple +/- signals from a dial!

Is anyone reading this has mastered using a rotary encoder interface successfully in an application that does something other then display the number on the screen ? Please advise me.

First advice is often to post your code (use the # button for code tags)
Also post a schematic how things are connected as we can only guess.

Many questions pop up:
Do you use interrupts?
If so are the interrupt variables volatile?
Do you use delay or print statements in interrupts?
Does your code have deadlock or livelock or race conditions?
do you use pull up/down resistors?
etc

We just cannot tell without code / schema

A good way is to strip your code to a minimal version that still show the problematic behaviour as that is easier to fix than code that includes a complete complex project.

Right now I am testing prototype using Arduino LCD shield with rotary encoder, and the sample code that goes with that. After I found a problem with the encoder, I did some more internet research and found TOO MANY other options to handle rotary encoder interfaces, it got overwhelming. Yes - The sample code uses interrupts.

The end product I plan to use is a 16x2 LCD display, with a SERIAL spi module (to free up all the all the pins needed to interface that with), and seperate pushbuttons & rotary encoder mounted into a control panel.

A problem in the past I have found, I have to test with the exact rotary encoder I plan to use to produce the product - since if I buy one that works, then 100 more from different manufacturer at a cheaper cost - SURPRISE!! The signalling changes! I have to totally re/do the project.

As it turns out, I believe the two digital pins 2 & 3 (on the arduino lcd shield) needed a re-solder, after I did that - the project appears stable (for now, again). As of now I'm not having trouble with the encoder interface (yet). I fear more "Ghost" will appear once the interface is mounted in control panel with vibration from truck driving, and or whatever electric interface from engine noise.

You must be doing something wrong. Rotary encoders work fine (even the cheap ones).

By "work fine" I mean they either work or they don't. They don't mysteriously stop working on alternate Tuesdays. If they do then suspect the software.

Interrupts are bad for reading switches/rotary encoders because of switch bouncing. Unfortunately most of the libraries use interrupts because newbies can't stop using "delay()", which means polling won't work for them.

In short, the first and most important thing if using manually operated rotary encoders is - do not use interrupts.

And the second follows - you need a proper debounce routine.

Something which I am working on at present (as it happens).

And of course, we have to say.

I like this little Rotary Encoder chip
LS7184N

http://www.lsicsi.com/encoders.htm
http://www.edgeelectronics.com/manufacturer.asp?name=lsi_computer_systems_lsicsi

Gives a nice clean pulse and direction (hi/low) as the knob is turned.
1 resistor sets the clock width that comes out.
Use a bunch connected with PCINTs to signal that a pulse has come in.
When one does, read the direction line and then act accordingly.

Gemini seems to have them in stock

LS7183_LS7184.pdf (190 KB)

Sounds like your first experience with a mechanical encoder. Optical encoders are a little easier to deal with, but mechanical encoders need debounce. This limits the speed you can turn them but works well for UI applications.

Here is some great info on debouncing...

http://www.ganssle.com/debouncing.pdf

DavidOConnor:
mechanical encoders need debounce.

No they don't. Quadrature encoding makes debouncing unnecessary, only one switch can be bouncing at any given time.

All they need is to be polled at an interval which is short enough that you don't miss any pulses. You'll find they're perfectly reliable if you do that.

Years ago originally, I tried doing this reading from parallel port signals on a PC - with lots of frustration. I moved to PIC micro-controller testing, before I tried Arduino. I have a little box with about a 1/2 dozen different types of cheap plastic encoders from different manufacturers that appear to give a different signal triggering from each one.

As of now I am just focusing efforts on the LCD shield with the rotary encoder and a joystick switch built into it.

I have to move the project off the LCD shield, and use the nice LCD 16x2 with the serial spi interface, that only uses 2 pins instead of a billion pins on the shield prototype. So I have to pick out a rotary encoder with circuitry to use for the project. Its just a manual knob to control a display menu, (not a CNC data-capture from a positioning motor, where super accuracy is absolutely needed).

I have to use "DELAY" command in my program, since it plays music from air-horns triggered by solenoids (or a piezo buzzer to test without having neighbors call cops to house again for excessive noise disturbance). Trigger digital pin on, delay, trigger pin off - another delay, play next note, etc... If anyone can offer a better way to play notes without using DELAY statement, I am willing to entertain suggestions. I guess your talking about using the DELAY to handle the encoder routines.

"blink without delay" is your friend.
Note the time, start an action, monitor the time to see when to stop the action.

DrStein99:
I guess your talking about using the DELAY to handle the encoder routines.

Nope. I'm talking about not using "delay()" at all.

Ok.

I managed to create my working project on separate circuitry using a separate encoder without interrupts. Simply 10k pull down resistors on the encoder. No problem, appears to work great.

DavidOConnor:
Here is some great info on debouncing...
Debouncing Contacts and Switches

And the pivotal statement from that:

The undebounced switch must connect to a programmed I/O pin, never to an interrupt.

fungus:

DavidOConnor:
mechanical encoders need debounce.

No they don't. Quadrature encoding makes debouncing unnecessary, only one switch can be bouncing at any given time.

Not so sure about that - it has been pointed out to me that as many use wiping contacts, there can be noise on the contacts.