I'm using a horribly inefficient hardware solution to using a rotary encoder with my
Dosing Computer. THat solution is great for measuring the speed of a moving part on a robot with minimal interference in the code running the robot, but it's doing nothing for us here. I set about a solution that only involved connecting the rotary encoder. I had planned to add it to the Doser post, but it gets into so many juicy Arduino topics, that I thought it merited it's own post.
The end goal of this effort is a simple solution to using a rotary encoder with any arduino program to scroll menus or input values, wrapped into a simple library so that the user need only attach the variable to the encoder when necessary and detach when no longer needed.
For those who want to know more about how a rotary encoder works,
see this from WikiPedia or see
this from the Arduino Playground.I am using
this encoder. It's part number
858-EN16-V22AF15 from
mouser.com .
I'm also using the Arduino-UNO in this project.
This thing puts out grey-code, which basicly means that you have two pins that are pulsed, and depending on the direction you are turning it, one pulse leads the other. Here's a picture from the Arduino Playground that explains it.
I was having trouble with it so I put it on the scope, and this one is a little less desireable than some of the other gery-code encoders I've played with. The pulses seem longer on one pin than the other. I think that is related to the mechanical detent positions (the spots where it clicks). If you look at the
data sheet you can see what I mean. The detent positions aren't symmetrical to the wave, so when you are clicking slowly, you end up with one long pulse and one short one.
The consequence of this has turned out to be that you can only use the rising edge of one signal and the falling edge of the other reliably. If you look at it on the oscilloscope while you click through it slowly, there is a long pulse on one pin, and a short pulse on the other pin, either right at the beginning of the long pulse or right at the end depending on the direction.
For scrolling through menu's and setting values in a prgram like this, I don't care. I only want one increment per click anyway, so I really only need to use one of the four transitions.
How are we going to accomplish this efficiently? We're going to use an interrupt.
Here's a quick lesson on how that works. Suppose you have a friend that is coming over to visit sometime today, but you aren't real sure exactly when. You could go every so often to the door and check to see if your friend is there, but that would really impede you getting anything else done. The alternative is to have a doorbell. Then you can go about your normal activity right up until the moment your friend arrives. As soon as you hear the bell, you INTERRUPT what you were doing and go take care of the door.
The same with the program, I could poll the pins that the encoder are connected to every so often. The problem is, some of these pulses are very very short, so if the program is busy, it may miss a lot of clicks. By using an interrupt, the program can keep up with what it has to do and only deal with the interrupt when it needs to.
More on this topic later when we write it.
Lets write a test program to use on the Arduino for playing with an encoder. We need a variable to increment and decrement with the encoder. We'll need the serial monitor so we can watch the number in the variable go up and down. And we'll need to set up for the rotary encoder. Let's use this for right now, I'll explain some of the pieces as we go.