Decode a quadrature encoder in software
Sid Levingston, Gentec-EO, Lake Oswego, OR; Edited by Martin Rowe and Fran Granville -January 20, 2011
Quadrature encoders work in many applications to determine displacement and direction of mechanical travel. They vary in design, but they all do the same thing: supply a set of square waves 90° out of phase. Figure 1 shows the typical output signals.
The encoder rotates clockwise when Channel A leads Channel B. If Channel B leads Channel A, the encoder is rotating counter clockwise. By counting the pulses and the direction of rotation, you can find the position of the encoder. Although ICs can decode quadrature encoders, you can easily and less expensively have the processor decode the signal. The signals from Channel A and Channel B go through a Schmitt trigger if necessary, but many encoders and processors include this trigger internally. The signals are then applied to two I/O pins on the processor that support edge-triggered interrupts. The code in the interrupt handler implements a standard decoder algorithm, but all algorithms typically follow these steps:
- Set up a state table like the one in Table 1. The table wraps around from State 3 to State 0.
- Initialize a counter.
- Measure the current state of Channel A and Channel B. Find that state in the table and set a pointer to it.
- Enable the interrupts.
In the interrupt handler, use the following steps:
- Read the state of Channel A and Channel B.
- If the state is the one preceding the pointer, decrement the counter.
- If the state is the one following the pointer, increment the counter.
- Set the pointer to the new state. 5. Clear the interrupt.
| Read More|
Now, consider what happens in the real world. If the I/O pin generates an interrupt on a rising edge, then when the interrupt happens, that channel goes from low to high. Therefore, there’s no reason to read the state of the pin that interrupted. The other channel did not interrupt because the signals are 90° out of phase. So, to determine the current state, you need only to read the state of the pin that didn’t initiate the interrupt. The state of the unchanged low or high signal tells which way the encoder rotated. If it is low, then the interrupting pin is leading. If it is high, then the interrupting pin is trailing. You can use these facts to implement an efficient interrupt handler with no state table and no memory of a previous state.
The code in Listing 1 was tested on an MSP430F processor connected to an Encoder Products model 15T. The encoder monitored the position of a linear stage. The stage traveled 85 mm and could be tracked with resolution of 5 microns.
The define statements (highlighted in red) make the code more readable. The initPort() function (highlighted in blue) sets up the rising-edge interrupt on channels A and B. The final piece is the interrupt handler (highlighted in green). Note that it contains only six lines of code compared with the 20 or 30 lines it would take to implement the traditional method of decoding the channels.