How to use the Sparkfun rotary encoder
Happy holidays everyone. The other day I finally put together some code to read the SparkFun rotary encoder (http://www.sparkfun.com/products/9117) that I bought last May for my birthday. I thought I might as well put down some of my observations on using it in an email to share with others.
The encoder uses detents to provide a kind of touch and feel. There are 12 detents per rotation. Rotating the encoder from one detent to the next the encoder goes through four state transitions, giving a total of 4*12 = 48 state transitions per rotation.
The first order of business was of course to debounce the encoder. At rest in a detent both of the encoder's contacts are open. So using pullups at the input pins, the AVR will read a 3. To avoid having to initialize the debouncing code to expect a 3 when it first runs I negated the pins so the debouncing code would expect a zero instead - which I could initialize using a static variable.
To accurately track the encoder I made my debouncing code run 2000 times per second. Of course to accurately debounce the encoder this is probably too fast. 1000 times per second (even 500 times per second) worked for tracking purposes but if you rotated the encoder too quickly a state transition was often lost. This isn't that much of a problem actually since the user probably won't notice it, plus the tracking code will spot the error. Unfortunately missing two transitions will look like you are rotating the encoder the other way which probably should be avoided. I went with the .5 ms interval just to be safe.
Rotating the encoder clockwise from one detent to the next, it outputs the following sequence: 2310. Rotating it counterclockwise, 1320. Instead of counting each state transition as a movement, I decided to count just one, in effect reducing the resolution of the encoder by four. This is in practice the resolution the user will likely experience especially with this encoder so I went with it.
Initially I wrote the code to count the 1 -> 0 state transition as one move CW and the 2 -> 0 transition as one move CCW. Unfortunately the encoder has a very slight backlash so state transitions of 2 -> 3 -> 1 -> 0 -> 2 -> 0 sometimes occurred resulting in a total move count of zero. To solve this problem I focused instead on the state transition in the middle, counting 2 -> 3 as one move CW and 1 -> 3 as one move CCW. This solved the backlash issue.
Hope this helps!
Dec 20, 2010: Unfortunately counting 2->3 as a move CW and 1->3 as a move CCW can cause inaccurate decoding in certain circumstances. For example, the tracking logic when confronted with a transition from 2->3 and then a transition back to 2 would count the complete sequence as one move CW even though the rotary encoder moved back CCW to 2.
To remedy this I changed my code to use the reverse state transition of CW for CCW, namely 3->2 instead of 1->3. Nevertheless the backlash issue still remained so as to prevent any movement instability I refrained from using 1->0 as CW and the reverse 0->1 as CCW.