TITLE: Quadratrack: Using Mechanical Rotary Encoders
AUTHOR: Chuck McManis
LAST UPDATE: 12-Feb-2001

Introduction

I’ve been having a lot of fun with my LAB-X3 lately. This time I wanted to figure out how to read rotary encoders. If you aren’t familiar with them, a rotary encoder looks like a potentiometer, except that instead of a variable resistor it an encoder wheel. Also, unlike a potentiometer they don’t have a “stop” point generally. Thus you can turn them around and around and around. They have become very popular on electronic equipment because you can create a “soft” control that is digital from the start. Further, because they have become fairly popular the costs have gone down such that the one I used from Grayhill is only $4.70 from Digikey ( GH3071-ND) qty 1.

Description

These mechanical encoders generate a “quadrature” signal. I don’t know the origin of the term quadrature but basically it means there are four states that this device can be in. Further, transition from one state to the next is well defined so with a simple circuit or some software you can translate the pulses into rotation movement.

The three pins on the device are A, B, and Common. Since they are mechanical they are simply switches that connect the A pin, the B pin, and then both the A and B pin to the C pin. A simple circuit for hooking this up is shown below.


Encoder Reading Circuit

As you can the outputs will appear to be 5V when the encoder is not connecting either A or B to C and they will be at ground potential (logic 0) when they are being connected.

The output of the encoder is a two bit gray code, specifically it has the sequence

Relationship of Rotation to Signal Changes
Clockwise Rotation ->
00 01 11 10 00
<- Counter Clockwise Rotation

Or more specifically, if the output is 00 and it goes to 01 you know that the encoder has moved one “tick” clockwise, if it is 00 and goes to 10 then you know it moved one tick counter clockwise. If it goes from 00 to 11 you know you missed an intermediate tick. It can be useful to flag this case so that you know your input isn’t accurate, but generally its safe to ignore it as if the knob didn’t move.

Now there are a couple of ways you can read this device, the simplest is to set your microcontroller to interrupt when ever the state of the two pins changes. Then by knowing the previous state and the current state you can tell what happened. This is easy to do with the PIC which has the ‘change on PORTB’ interrupt mode. An alternative is to hook the two pins up to input capture pins of the Motorola 68HC11. When you capture a rising or falling edge on either input you can update the position state. Finally, there is an even easier way (but its a bit risky) which is to sample the pins every n microseconds and see if their state has changed.

I chose to use the sampling technique and sample at 1Khz (1 mS per sample). My reasoning was as follows:

  1. We’re talking a human here who is turning this knob, and if they spin it as hard as they can they worse they can do is miss one state. Normal use is unaffected.
  2. If there is any “bounce” in the switch (and I’ve not detected any) then the mS sampling will cover for it.

Source Code

The code to read these is fairly straight forward, I’ll save you from digging from the full file by just pulling out the relevant bits. If you want the whole thing email me and I’ll send it to you.

I’m using the PIC16F628 in a LAB-X3 proto board. The encoder was soldered into the prototyping area with the appropriate pull up resistors. Note that you could use the ‘weak pullups’ feature on PORTB but I didn’t want to turn those on for all the pins. Anyway, as I’m not using the serial port in this example I jumper the Encoder to pins RB1 and RB2 on the PIC.

The code to set up a 1Khz interrupt from TMR0 on a 4Mhz system is as follows:

Then you have the following in the interrupt service routine:

As you can see the TMR0 is reloaded first to insure an accurate tick rate (also TMR0 is the first interrupt checked!) Once you know you’re set to get the next “tick” on time, then you can check the quadrature state. In the ISR I call QUAD_STATE and this is written as follows:

The INC_COUNT and DEC_COUNT limit the resulting value to between 0 and 200 because that was what my application called for, however it could just as easily have kept an 8, 16, or even 32 bit absolute value. Clearly this code would also work with quadrature encoders on wheels of a robot but there you have to take into account that if your robot is moving quickly you will definitely want to adjust the sample rate accordingly!

Late breaking news:

An alert reader pointed out that I could just write a subroutine for the quadrature encoder that returned +1 or –1 or 0 and then added that to the value. To that end, the following subroutine was created:

Now, instead of calling INC_COUNT or DEC_COUNT, I just call this routine with the computed value of QUAD_ACT and the add W to the COUNT variable. After the addition I test for over flow or underflow and update the value accordingly. Given that the top 4 bits of PORT B can be configured for “interrupt on change” I’ve got to assume this is how they implement computer mice with two quadrature encoder wheels.

The updated QUAD_STATE routine is shown below.

In a final bit of cleverness, if you skip a state, and you remembered that you were turning clockwise or counter-clockwise, you could choose to increment or decrement by 2. That would keep the count accurate.

Conclusions

Using mechanical rotary encoders is easy to do and they provide an excellent “frob knob” for your projects. Software can set them to be anything from simple on/off switches, to linear or log potentiometers, or arbitrary value adjusters.

The amount of code needed to use them is comparable to the ‘pseudo analog’ techniques of pulling the line low then high and counting ticks until it crosses the logic 1 threshold (example the POT command on the Stamp). They do consume 2 digital I/O’s rather than an analog I/O which is a detriment, but with an R2R ladder on the output they could use an A/D input.

Finally if you’re using quadrature encoders on your wheels, you’ve probably already got the code in your system to deal with them and they are then nearly a total win.