Rotary encoders

In an attempt to deal with bounce in rotary encoders, I’m starting from the code at the bottom of this page.
It does everything I need, but I want to understand how it does it. I understand the principal of what it does (it compares the changes of the encoder output values to a set of valid changes stored in an array and ignores everything else as effects of bounce) but I’m struggling with one aspect.

NB: My code is subtly different from the original: I’ve changed a couple of variable types / hex to bin / syntax / etc to ones I find it easier to work with: I realise some may now not be best practice, but the sketch still works perfectly.
I’ve commented on all the significant lines with what I think they’re doing, but I’m really stuck with the last comparisons in the read_rotary() function.

#define pinA 6           // Input pin for rotary encoder output A
#define pinB 7           // Input pin for rotary encoder output B
int prevNext = 0;        // bits 0 and 1 are the current current encode values, bits 2 and 3 are the previous vlaues 
int store = 0;           // The next and previous values of prevNext
int count = 0;           // Number to increment/decrement with the rotary encoder
int rotateChange = 0;    // Value to be added to count

void setup() 
  pinMode(pinA, INPUT_PULLUP);
  pinMode(pinB, INPUT_PULLUP);
  Serial.begin (9600);

void loop() 
  rotateChange = read_rotary();
  if (rotateChange != 0) 
    count = count + rotateChange;

int read_rotary()
// Array to show which changes of values for pinA and pinB represent 
// valid movement of the rotary encoder, ignoring erroneous values eg doe to bouncce
  static int rot_enc_table[] = {0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0};

  prevNext <<= 2;                   // Shift the bits 2 left. ie next becomes previous
  if (digitalRead(pinA)) prevNext = prevNext | 0b0001;      // if pinA = 1, then set xxx1
  if (digitalRead(pinB)) prevNext = prevNext | 0b0010;      // if pinB = 1, then set xx1x

  prevNext = prevNext & 0b1111;                             // Limits prevNext to 4 bits

  if  (rot_enc_table[prevNext] )                            // Does nextPrev represent a valid rotation
    store <<= 4;                    // Shift the bits 4 left. ie next becomes previous
    store = store | prevNext;       // Bits 0 to 3 of store are changed to 0 to 3 of prevNext
    if ((store & 0b11111111)==0b00101011) return -1;        // DON'T UNDERSTAND
    if ((store & 0b11111111)==0b00010111) return 1;         // DON'T UNDERSTAND
  return 0;

With the two lines I don’t understand:
Assuming the previous and next values of pinA and pinB represent valid rotary encoder changes (eg you can’t go directly from 00 to 11 or from 01 to 10)

store & 0b11111111    // limits store to 8 bits.

… this is then compared to 0x2b or 0x17 to determine which direction the encoder has turned, if at all.
I’ve tried working though the changes to all the variables one at at time on paper, but I’ll be damned if I can work out the significance of 0x2b and 0x17

Can anyone help me out?

It's using store to build a history of the states of the two encoder pins. I think that rot_enc_table checks the latest state information collected in prevNext to defend against bounce.

store accumulates history and the high bits are the oldest. The code only cares about the latest eight bits which represent the last four sets of useful readings. They are:

So, 0b00101011 is this pattern:
B & A were low.
B went high.
B stayed high.
A went high too.

If you look at the encoder pattern diagram, I suspect that that's a step counter clockwise. You can decode the other mystery number and no doubt it will resolve to a step clockwise, hence the -1 and 1.

It's clever, but as you have seen, a bit tricky to see what's going on.

Thanks Bill
I'm still struggling to see how store gets to match those values for each direction, but to **** with it. It works, so I'll hang my head in shame and just use it. :confused:

It may be clearer if you try and match the patterns represented by those two magic numbers to the usual picture of the encoder pulses in the encoder documentation that illustrate clockwise and anti-clockwise rotation.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.