circuitcellar.com
Magazine Support   Digital Library   Products & Services   Suppliers Directory 
 
 





 

Issue 152 March 2003
Using Rotary Encoders as Input Devices


TWO-BIT BINARY ENCODERS

As the name implies, these devices translate the encoder’s shaft position into one of four possible states; nonetheless, these encoders generally have from 16 to 32 detents or positions per 360° rotation. Therefore, it is the microcontroller’s job to keep track of those cases in which the encoder advances from the 3 position back to the 0 position (analogous to a "carry" situation in binary math). Equally important, it must also sense when the encoder is rotating in the opposite direction and goes from the 0 state to the 3 state (i.e., a "borrow").

For this reason, it’s important that the microcontroller be constantly aware of any changes in the encoder’s position. For most applications, this means that both of the encoder outputs must be connected to interrupt inputs on the microcontroller. Failing that the least you have to do to ensure proper operation is configure the microcontroller to respond to an internal timer interrupt occurring every 5 ms or so, and let the timer ISR check the state of the two encoder outputs.

You’re familiar with the normal binary number sequence, but the term Gray code may not be familiar to you. Because 2-bit rotary encoders are often configured to produce Gray code outputs rather than straight binary coding, I’ll explain the concept. The term Grey code is also used in the literature. I assume this means that a person called Gray, or Grey, did not invent the code, because I would expect the spelling to be consistent if it referred to a person’s name.

If you think for a moment about the normal binary sequence, you’ll notice that, as the sequence progresses, there are certain transitions during which many of the bits change at the same time. The most striking example of this in 8-bit binary code occurs during the transition from 127 to 128, where the seven LSBs all go from a one to a zero, and the MSB goes from a zero to a one. Transitions like 63 to 64 and 31 to 32 are less dramatic, but still result in a lot of bits changing simultaneously.

Because rotary encoders are basically mechanical devices subject to physical tolerances and wear, any multi-bit encoder would suffer from problems arising because the exact opening/ closing timing of the many internal switches wouldn’t be the same. The problem would manifest itself most blatantly at those positions where the codes changed drastically.

Rotary encoders have been around for years and were connected to discrete logic chips early on. Therefore, during the brief intervals where the switches were not perfectly in-sync with each other, there existed the possibility of numerous false position codes being generated at the output of the logic devices connected to the encoder.

To eliminate this problem, an alternate coding scheme—the Gray code—was devised, in which any transition in a straight up or down sequence would only differ from its neighbor by a single bit change. For a rotary encoder, which only changes in a sequential fashion, this meant that at no time would more than one switch be opening or closing. This eliminated the switch synchronization problems that I mentioned earlier. Table 1 shows the bit patterns for both a standard 2-bit binary sequence, as well as its Gray code equivalent.

For the microcontroller to keep track of a 2-bit encoder’s shaft position, in absolute terms, those carry/borrow types of transitions must be recognized when they occur. To achieve this the microcontroller must keep a record of the encoder’s last 2-bit position, as well as the current position, when any change occurs. Because there are four possible output codes and two directions in which the encoder could have turned in each of them, eight possibilities have to be evaluated.

This evaluation can be performed in code using four IF statements, each of which contains two additional nested IF statements (i.e., a total of 12 IF statements). The four IF statements would test for each of the four current positions, and the two nested IF statements would check to see which of the two possible positions the encoder is in prior to the change. This solution results in numerous lines of code, and its execution time will vary from one case to another, depending on how far down through the IF blocks the program must go before it finds the matching criteria. Later, when I discuss code examples for a specific encoder, I’ll introduce a more elegant solution.