Measure Angle and Direction with Rotary Encoder

Learn how to measure angles and rotation direction using Arduino and rotary encoders.

What is a Rotary Encoder?

A rotary encoder is a device that measures angular position and speed by generating digital pulses when rotated. It can also detect rotation direction.

Rotary Encoder

How Does it Work?

The encoder generates pulses using a quadrature system with two channels (A and B) that are offset by 90°. By analyzing these pulses, we can determine rotation direction and distance.

Encoder Operation

Wiring Diagram

To connect the rotary encoder to Arduino, follow the wiring diagram below:

Rotary Encoder Wiring Diagram

Code Examples

1. Single/Double Precision (Polling)


const int channelPinA = 9;
const int channelPinB = 10;

unsigned char stateChannelA;
unsigned char stateChannelB;
unsigned char prevStateChannelA = 0;

const int maxSteps = 255;
int value = 0;
int prevValue = 0;

void setup() {
  Serial.begin(9600);
  pinMode(channelPinA, INPUT);
  pinMode(channelPinB, INPUT);
}

void loop() {
  stateChannelA = digitalRead(channelPinA);
  stateChannelB = digitalRead(channelPinB);

  if (stateChannelA != prevStateChannelA) {
    if (stateChannelB) {
      if (value < maxSteps) value++;
    } else {
      if (value > 0) value--;
    }
    prevStateChannelA = stateChannelA;

    if (prevValue != value) {
      prevValue = value;
      Serial.println(value);
    }
  }
}
            

2. Double Precision (Interrupt)


const int channelPinA = 2;
const int channelPinB = 10;
volatile int ISRCounter = 0;
int counter = 0;

void setup() {
  Serial.begin(9600);
  pinMode(channelPinA, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(channelPinA), doEncode, CHANGE);
}

void loop() {
  if (counter != ISRCounter) {
    counter = ISRCounter;
    Serial.println(counter);
  }
}

void doEncode() {
  if (digitalRead(channelPinA) == digitalRead(channelPinB)) {
    ISRCounter++;
  } else {
    ISRCounter--;
  }
}
            

Important Notes

Using interrupts improves precision but consumes interrupt pins. Use polling for simple applications where performance is less critical.