" section.
Alex Brown's Optical Encoder Tutorial
There are a number of methods of decoding optical encoders, implemented in both
hardware and software. (See the sections below) Every decoding method, though,
will require clean square wave signals with sharp transitions.
The traditional signal conditioning method places a
Schmitt trigger
circuit between the photodetector and the decoding circuitry. The Schmitt trigger
circuit produces the nice, sharp transitions required by your decoder circuit or
software.
If you are using a microcontroller to decode your optical encoder, read the data sheet carefully. You might find that your chosen microcontroller is designed with Schmitt trigger inputs. You might be able to save some external hardware.
The quadrature decoder produces two square wave signals, 90 degrees out of phase
with one another. When the encoder is rotated in one direction, Phase A leads
Phase B. When the encoder is rotated in the other direction, Phase B leads
Phase A.
With a quadrature encoder, you can both count the number of rotation pulses and
detect the direction of rotation.
This is what a quadrature signal looks like, when the encoder is rotated both
clockwise and counterclockwise:
A software quadrature decoder is often implemented as an interrupt-driven
state machine, based upon a state table.
Let's build a state table by referring to the phase diagram, above. For the moment,
just consider the clockwise rotation case.
Starting with the Phase A = 0, Phase B = 0 condition and moving left to right, the
states you encounter are these:
|
|
Phase A
|
Phase B
|
|
State 0
|
0
|
0
|
|
State 1
|
1
|
0
|
|
State 2
|
1
|
1
|
|
State 3
|
0
|
1
|
Now look at the diagram for counterclockwise rotation. Find the Phase A = 0,
Phase B = 0 state. Moving left to right, the next state will be Phase A = 0,
Phase B = 1. Then Phase A = 1, Phae B = 1, and finally Phase A = 1, Phase B = 0.
Compare the CCW states with the CW state sequence in the table above.
Phase A = 0, Phase B = 0 is State 0. Phase A = 0, Phase B = 1 corresponds to
State 3. The next corresponds to State 2, and the last corresponds to State 1.
Notice that the state sequence is the same for either direction of rotation. Only
the direction you take to step through the state table varies.
So you can use the same state table for both clockwise and counterclockwise rotation.
The state table is actually circular, with State 3 wrapping around to
State 0, and State 0 wrapping around to State 3, as shown in the figure below.
If you measure your current state and find it in the table, the next state must be
either the state directly above or the state directly below your current state. If
the state in question is the one directly above your current state, then the direction
of rotation is counterclockwise. If the state in question is the one directly below
your current state, then the direction of rotation is clockwise.
Note that "Clockwise," "Counterclockwise," "Phase A," and "Phase B" are relative
terms. In reality, the phases can be reversed with respect to the direction of
rotation. And in the real world, if you build a decoder that's telling you the
wrong direction of rotation, just swap the Phase A and Phase B connections.
Let's assume that you want a counter to increment when Phase A leads Phase B, and you
want the counter to decrement when Phase B leads Phase A.
Set up your state table to match the states in the table above, and establish a
state table pointer. Configure your interrupts for interrupt-on-change for both
the Phase A and Phase B inputs.
Initialization:
Intialize the counter.
Measure the current state of the Phase A and Phase B inputs. Locate that state in
the table. Initialize your state pointer to that state.
Enable interrupts.
Interrupt routine:
If the state is the one preceeding your state pointer, decrement the counter.
If the state is the one following your state pointer, increment the counter.
If neither of those state conditions are true, you have missed a pulse. Set an error
condition. (Depending upon your application, you might just ignore errors, flash an
LED, increment an error counter, etc.)
Point the state pointer to the current state.
The resolution produced by this algorithm depends upon your interrupt configuration.
If you generate interrupts on only one transition, say the positive-going transition
of either the Phase A or Phase B line, you will produce half the number of counts
per revolution as there are cells in your track. For a 250 cell track, you will
recover 125 counts per revolution.
If you configure your system to generate interrupts on two transistions -- say, the
positive-going transitions on both the Phase A and Phase B lines -- you will achieve
the same resolution as your wheel. If you have 250 cells in your track, you will
recover 250 counts per revolution.
If you are able to generate interrupts on all four transitions, that is, both the
postive and negative-going transitons on both the Phase A and Phase B lines, you will
double your wheel's resolution. A 250 cell track will produce 500 counts per revolution.
I've written a little example program for the PIC 12F683, that implements the algorithm
described above. This routine generates interrupts for all possible transitions of the
Phase A and Phase B lines, so it produces the maximum resolution possible from a quadrature
encoder.
Download the 12F683 Quadrature Decoder Listing
There are a plethora of quadrature hardware decoder circuits on the net. A Google
search will turn up more of them that you ever wanted to see!
I've tested the following two simple decoder circuits using
Multisim. For simple
applications, either should work well for you.
The first circuit, shown below, uses a single Dual-D flip flop IC (such as the
CD4013 shown in the sketch) to generate two output "pipes." One pipe squirts out
pulses when Phase A leads Phase B. The other pipe squirts out pulses when Phase B
leads Phase A.
This circuit produces 1/2 the number of pulses as there are cells in your quadrature
track, or for each quadrature track if you're using a two-track wheel. In other words,
if you've built a quadrature wheel with 200 cells per track, this decoder will produce
100 pulses per revolution.
Although this circuit doesn't recover all the resolution availble from quadrature
encoding, it is attractive due to its low chip count. One IC does all the decoding.
The following circuit produces more pulses per revolution, but isn't as low in
chip count as the first circuit.
This circuit uses a single D Flip Flop and a single XOR gate. In the example, I've
chosen 1/2 of a CD4013 Dual_D Flip Flop IC and 1/4 of a CD4030 Quad XOR IC.
The Q output of the flip flop is high when Phase A leads Phase B, and low for the
other direction of rotation.
The XOR gate produces one pulse per cell. In other words, if you've generated
a track with 200 cells, this decoder circuit will produce 200 pulses per revolution.
(If you were doing a simple, non-quadrature decode of a 200 cell track, you would
develop 100 pulses per revolution.)
Gil, N5UK, emailed me to say that he wanted to adapt a quad encoder to add a tuning
knob to a radio receiver that only used a pair of pushbuttons for tuning. I first
recommended the dual flip-flop single 4013 solution, above, but quickly realized that
there was a big problem using that circuit with Gil's radio. Depending upon the position
of the tuning knob when he removed his hand, one or the other of the flip-flops might
remain set. If the radio's pushbuttons auto-repeat, the radio would continue tuning
up or down until he moved the knob. That wouldn't be a workable solution at all.
So I brewed him up a "button pusher" decoder, shown above, that uses a pair of 555 monostables
for both the quad decoder and for timing the output pulses. This circuit gives one pulse for
each synthesized button push, and doesn't have the inadvertent continuous tuning problem
that the single 4013 decoder exhibits.
Roderick Wall, VK3BKO, uses this IC in his homebrew quadrature encoder IC. In
one package, the IC contains a dual infrared photosensor arrangement and full
decoding circuitry, providing direction and pulse outputs. This IC produces
one pulser per cell. For instance, if you've built your codewheel with 200
cells, this IC will produce 200 pulses per revolution.
Datasheet
There's a lot to be said for this IC. Its wire leads provide simple and flexible
mounting. This IC eliminates the need for critical alignment of the two separate photodetectors required for a conventional quadrature encoder, and eliminatds the
board real estate that might be required for other hardware decoder schemes.
Use of one of these ICs and a single infrared LED would greatly simplify your homebrew
encoder project.
As of July 29, 2008, this IC was available from
Allied Electronics for USD $5.57.
Lawrence Glaister, VE7IT
Unless you own or have access to a screw-cutting lathe, the likeliest source of
a codewheel mount is a salvaged potentiometer. Here's an example showing how
Lawrence Glaister, VE7IT, mounted a codewheel, salvaged from a computer mouse,
to the innards of a 2-watt pot:
VE7IT Codewheel Mount
Roderick Wall, VK3BKO
Roderick has designed a very clever quadrature encoder using nothing but
off-the-shelf parts. His original approach results in a very solid encoder
design that's very easy to construct and requires no special machining.
He also arrived at a very neat solution to the problem of punching an
accurately-located center hole in the codewheel: he clamped the codewheel between
two metal washers, then melted the center hole using a soldering iron! Much more
elegant and simpler than my method, using a Pittsburgh hand punch, and provides
goof-proof centering. Nice work, Roderick!
In his own words, here is how Roderick built his encoder:
"Shaft encoder was made up with a ball bearing clamped between two Car mud-flap washers.
The centre of the two washers was drilled (15mm diameter) to allow space for the two nuts that clamps the shaft (a bolt) onto the inner part of the ball bearing. Three 4mm diameter holes (120 deg apart) are drilled in the washers for three 4mm screws that are used to clamp the bearing between the washers and for mounting the shaft encoder to the front panel.
The shaft is a ¼ inch bolt with the head cut off. You may need to file the thread on the ¼ inch bolt to allow the 6mm inside diameter of the bearing to fit onto the bolt thread. Or use any 6mm outside diameter bolt.
Two Car Mud-flap washers with two nuts are used to clamp the optical disk to the shaft.
Parts: 4 x Car mud-flap washers (31.5mm outside diameter with ¼ inch hole) 1 x ¼ inch bolt (select one that has a shaft 6mm diameter) or any bolt with an outside diameter of 6mm. 4 x Nuts to fit above bolt 3 x 4mm 35mm long metal thread screws 6 x 4mm Nuts for above screws 1 x 6mm inside diameter, 19mm outside diameter, 6mm wide ball bearing 1 x Tuning knob (6mm shaft) (Rockby Electronics - Australia) Lead to balance the tuning knob (fishing sinker), an unbalanced knob will always turn.
All the above parts except for the ball bearing, tuning knob can be purchased from BUNNINGS WAREHOUSE (in Australia). "
Thanks very much, Roderick. A very impressive and clever design! --Tom
The program can generate the seven wheel types shown below.
The top four wheel types, Unencoded, Unencoded with Index Track, Two-Track
Quadrature, and Two-Track Quadrature with Index will probably be of most use to the
experimenter.
The two Absolute
Position wheels will be of possible interest to very advanced experimenters who
might wish to experiment with absolute positioning. Or might be used as a source
of abstract art. <g>
The Custom (User-Defined)
wheel type is there to cover any bases not addressed by the other wheels.
The illustration above might lead you to believe that the program generates
poor quality images. Not so. The jagginess is an artifact of reducing the
full-size .BMP images to web-size. The illustration below is a small chunk chopped
out of a full-size image generated at 4800 pixels per inch, showing that the
program can produce high quality imagery.
Full-size Image generated at 4800 pixels / inch
The Unencoded and Two-Track Quadrature wheels are the ones you'd want to try if
you want to build a quadrature encoder, as I do.
As you learned from Alex Brown's tutorial, you can implement a quadrature encoder
using a single track wheel, with the two photosensors offsent by 1/2 of the wheel's
cell width. When you consider the narrow cell width of very high resolution wheels,
the experimenter must precisely align the two photodetectors.
I don't really have the facilities in my workshop to precisely fabricate the small,
precision assemblies that I think might be required, so I included the Two-Track
Quadrature wheel to possibly reduce the precision required in photodetector positioning.
When I actually get around to building my encoder (hopefully very soon, now that this
program is finished), I'll make my first attempt using
a two-track quadrature wheel as shown in the figure above. This wheel will provide
accurate quadrature encoding with only a simple vertical alignment of the
photodetectors.
I can't build a precision, finely-adjustable photodetector mount, but I can easily drill
two tiny holes in precise alignment. So I'll fabricate a pinhole mask as shown above.
With a good mask, phototransistor mounting location is no longer critical.
At least it sounds good in theory...
I included this design so hobbyists who experiment with robotics, motor control,
and even folks who are building their own personal transport vehicles could build
cheap and simple encoders for wheel position and speed measurement, odometry,
navigation, etc.
One of these wheels might be in order for applications where the direction of
rotation is known. Because the code track and the index track are separate,
photodetector mounting location isn't at all critical in either the horizontal
or the vertical directions. You can quickly dash out a real "quick and dirty"
encoder that performs as well as the $$$ commercial encoders.
This wheel design would also be suitable for a single-code-track quadrature encoder
that requires an auxiliary index output. (If you'd like a two-track quadrature encoder
with an index mark, I'm afraid that you'll have to fabricate your design using the
custom wheel type.)
This wheel might be used for motor control applications where you need to
detect the direction of rotation, measure speed, and count the number of revolutions.
While these are of little use for hobbyists (I think... but I've been massively
wrong before), they might have some use in amateur industrial control applications
built by very experienced constructors.
An absolute position wheel's code output is a direct function of the angle of rotation.
As the shaft turns, the code increases until it reaches the maximum value
(or decreases until it reaches zero) and then rolls over.
These sensors require lots of tracks and lots of precisely-aligned photodetectors. A
256-position absolute positiong wheel (the largest this program can generate) requires eight tracks and eight photodetectors.
There are some multi-track SMD photosensors on the market that might ease construction
of an absolute positioning wheel, if your application absolutely demands one of these.
Personally, I think that if one of these wheels is actually ever used, it will be used
as the background for nametags at radio club meetings, and not as encoders. <g>
The program can generate codewheels encoded in either
Gray code or binary, and can be
configured to have the code value either increase or decrease as the wheel is rotated
in a given direction.
I've included the custom wheel design for applications not covered by the other five
wheel types.
You can build a custom wheel of from 1 to 8 tracks. Each of your tracks may contain
coding or can be configured as a blank track.
You define your coding for each track by entering a string into the appropriate
track data box. Strings don't have to be of equal lengths. If you want 250 cells
on the outer track and 6 cells on the next one, the program will accommodate your
desires. You'd enter a 250-character string for the outer track, and a 6-character
string for the next track.
In the string entries, "1" represents a filled cell, and "0" (zero) represents a
blank cell.
You can even enter a single digit for each track. For instance, if you build a
5-track custom wheel with each track defined by only a "1" or a "0", you'll wind
up with a pretty neat bullseye target!
The information in this section pertains to the overall operation and
application of the Codewheel program. For specific information on the use of
any particular feature, refer the the program's help file. To open the help file, press the F1 key after you've launched Codewheel.
At your first program launch after installation, the program should come up with
tool tips enabled. After you've learned the program's controls, you can turn
tool tips off by clicking the Tool Tips choice on the Help menu.
The program should work with any Windows-qualified graphic printer, including
virtually all the inkjet and laser printers on the market. For final output of
your codewheel image, I'd recommend either transparent stock or single-weight
glossy photo paper. Of course, for drafts, or if you're just fooling around with
the program, use the cheapest paper you have on hand.
Generating a codewheel is a very simple task.
Select the wheel type. As you click each button, a thumbnail will pop
up in the preview window so you'll have an idea of the structure of the chosen
wheel type.
Enter your desired number of tracks, the outside and inner diameters, and your
desired resolution. (Enter a resolution value that is at least as high as your
printer's best resolution, and preferrably even higher than that.)
(Note that the read-only .BMP file size box will automatically display the
estimated .BMP file size as you change the outer diameter and resolution
settings, and that the number and size of the track data boxes in the lower screen
area will vary in number and size based upon the wheel type and number of tracks.)
If you've selected an Absolute Position wheel, choose the direction for increasing
code value -- either clockwise (CW) or counter-clockwise (CCW).
Check the Negative box if you'd like to print a negative image.
If you wish, you can generate a low-resolution preview of your wheel's actual
configuration by clicking the Preview button.
Enter your track information in the track data boxes on the lower section of the
screen. For all but the Custom wheel type, you'll need to enter the number of
cells for a given track. For Custom wheels, enter the string that corresponds to
your desired track pattern. ("1" for a filled cell, "0" for a blank cell)
For the wheel types not mentioned below, you can select one or more blank
tracks by checking the appropriate No Code checkbox. You might choose a blank track
to provide spacing for a nice, professional-looking wheel.
If you don't select any blank tracks, the coding will extend from the periphery to
the wheel's inner diameter (or hub) circle.
The Unencoded with Index wheel's geometry is fixed at two tracks, with only the
number of cells on the outer track variable. You'll only see a single track data
entry box for this wheel type. If you choose more than two tracks, all extra tracks
will automatically be generated as blank space.
When you choose an Absolute Position wheel, the track data is fixed. You won't
be able to change the track data, or configure any blank tracks, for either of these
wheel types.
You're now ready to print and/or save your codewheel.
To print your wheel, click the Print choice on the File menu, or press Ctrl+P.
A printer selection box will appear. Choose the printer you'd like to use, then
configure the printer's settings. If you have the option, set your printer and
print driver to the maximum quality settings. Click OK.
Another box will pop up, showing you the configured print resolution, and asking if
you would like to proceed. If you click the Yes button, your codewheel will print.
To save your codewheel to a .BMP file, click the Save As... choice from the file
menu. A file selector box will appear. After you enter the filename, click the OK
button. The program will save your program to the named .BMP file.
If the program detects a setup data error, it will prompt you with either an
appropriate error message or turn one of the edit boxes red.
If you see a red box error, just click that box to clear the error condition and
enter the correct data.
1)