## Incremental rotary encoders (Part 1)

Part 1234567, 8, 9, 10

Note: This post is the starting point for a whole series of post dedicated to rotary encoders. Please read through thme all in order to benefit from all the improvements brought to the original code.You may also want to read about this  heat control application which features encoders.

An absolute encoder has a number of binary outputs that indicate the switch shaft’s absolute rotational position referenced to some spot on the switch’s body. The direction is derived from the difference between previous and actual BCD counting.

An incremental rotary encoder, will not tell where the shaft is positioned. It will only tell which direction the shaft is being turned and how fast. Incremental encoders have only two outputs called phases. Each outputs a square wave. Turning the shaft one direction causes one phase to lead the other by 90 degrees. Reversing the direction will cause the other phase to lead. The frequency of the output is proportional to the rotational speed of the shaft. Incremental encoder may incorporate an additional switch which is activated by pressing down the encoder shaft. In this way the incremental rotary encoder can be used as a simplistic user interface.

Warning: The pinout may differ from one encoder to the other

The switching pattern looks like:

```  ---     ---     ---            ---     ---     ---
|   |   |   |   |   |     A    |   |   |   |   |   |
-     ---     ---     -        -     ---     ---     --
---     ---     ---                ---     ---     ---
|   |   |   |   |       B      |   |   |   |   |   |
---     ---     ---        ---     ---    ---
Turn Left                       Turn right
A 1 1 0 0 1                    A 1 1 1 0 1
B 1 0 0 1 1                    B 0 1 0 0 0```

Note: This is the ideal case. In the real life, we will have to care about the bouncing effect!

The most obvious way to analyze the signal consists in attaching an externally driven interrupt to one output, and to measure the signal from the other output.

An alternative consists in sampling periodically both signals. Comparing previous and actual outputs combination gives the direction indication: no change, cw rotation ccw rotation. This principle does not require interrupts and simplifies the code, its debugging and its maintenance.

This is the minimal set up content:

```void setup() {
// Setup encoder pins as inputs
DDRB  &= ~(1 << ENC_PIN_B);
DDRB  &= ~(1 << ENC_PIN_A);
// Bias inputs
PORTB |=  (1 << ENC_PIN_B);
PORTB |=  (1 << ENC_PIN_A);
// Set global variable
int counts = 0;
}```

The periodical encoder test can be part of the loop() routine

```void loop() {
enc_test();
}

void enc_test(void) {
// Test encoder outputs
static int lastCount = 0;
if (encoder) {
counts += encoder;
lastCount = counts;
}
}```

And this is the encoder reader

Note: Most encoders will experience multiple state changes per step. The encoder reader buffers these changes up to a predefined value (stored in the pulsesPerStep variable) before incrementing or decrementing the counter.

```int enc_read(void) {
// returns change in encoder state (-1: ccw, 0: no change, 1: cw)
int result = 0;
static byte prevState = 0;
static int bufferedCounts = 0;
byte startState = State(); // Get current state
delayMicroseconds(samplingTime); // Wait safety bounce time
byte stopState = State(); // Get current state
if ((startState == stopState) && (stopState != prevState)) { // check if the previous state was stable
if (stopState == nextEncoderState[prevState]) {
bufferedCounts++;
}
else if (state == prevEncoderState[prevState]) {
bufferedCounts--;
}
prevState = state; // Record state for next pulse interpretation
if (abs(bufferedCounts) == pulsesPerStep) {
result = int(bufferedCounts / pulsesPerStep);
bufferedCounts = 0;
}
}
return(result);
}

byte State (void) {
return(((PINB >> ENC_PIN_B) & 0x01) | (((PINB >> ENC_PIN_A) & 0x01) << 1));
}```

The bouncing filter is pretty simple (not to say simplistic) but it works great.

Next post on same subject