From looking through the search results for "rotary encoder" here, I see that we have a number of bona fide experts on rotary encoders. I recently developed my own polling and pin interrupt routines for cheap mechanical quadrature encoders, using no hardware debouncing, and I thought they were pretty cool. And indeed they worked fine on the pretty good Bourns encoder that I had on hand, but not so well with the noisier encoder that came with my DSO150. So back to the drawing boards, including taking another look at the lookup table method made popular by Oleg Mazurov of CircuitsAtHome.com (a member here too) and Bex Buxton of Buxtronix.net.
But I've always had a question about the polling version of the lookup table method. Here's Oleg's code:
/* returns change in encoder state (-1,0,1) */
int8_t read_encoder()
{
static int8_t enc_states[] = {0,-1,1,0,1,0,0,-1,-1,0,0,1,0,1,-1,0};
static uint8_t old_AB = 0;
/**/
old_AB <<= 2; //remember previous state
old_AB |= ( ENC_PORT & 0x03 ); //add current state
return ( enc_states[( old_AB & 0x0f )]);
}
So as I understand it, the encoder pins are bits 0 and 1 of the port. Going in, the variable old_AB contains the pins state from the last poll, and that is shifted left two bits, then the current state is read in, ANDed with 0b11, and ORed into old_AB. We now have a 4-bit value containing the previous poll state in the upper two bits, and the current state in the lower two bits. With four bits there are 16 possible combinations, and the current one is used as an index into the lookup table. The value fetched there is either a valid CW transition (1), a valid CCW transition (-1), no change (0), or an invalid transition caused by bouncing (also 0). There are eight possible valid transitions, four possible no-changes, and four possible invalid results.
The problem I have is that if an invalid result occurs, we presumably have a current value that does not represent a nominal valid state of the switches, but only bouncing noise. Yet that value is carried forward to the following poll and used as the old_AB for that poll. So we are comparing what may be a valid reading on the new poll with what is likely a fictitious state for the old poll, and that seems likely to produce another invalid transition, or one that appears to be valid, but isn't.
It seems that what should be done if an invalid transition is detected is to shift old_AB back to the right two places to restore the old (valid) reading as the current reading, and discard for all purposes the invalid reading we just got. Then the next poll is much more likely to generate a valid transition.
I think this would require changing the 0 values in the lookup table to maybe 0x55 for the four invalid transitions, which are at indexes 3, 6, 9 and 12. Then for a 55 you would still have 0 change, but would restore old_AB. The values at indexes 0, 5, 10 and 15 would remain as no-change 0's not requiring old_AB restoration.
Has this ever come up before? Would this change make any difference? Seems like it would. Well, I have more cheap encoders on the way, and will test this, but I just thought I would see what the experts thought.