Skip to main content

How to use a rotary encoder

What is a rotary encoder?

A rotary encoder is an electromechanical device that converts the angular position or motion of a rotating shaft into electrical signals. These signals can be processed to determine rotational direction, position, and speed, making rotary encoders a key component in many types of control systems.

Wiring

rotaryencodercircuit.png11102-02.jpg

Different models of rotary encoders will have different colour codes. I am using an Incremental Rotary Encoder, YUMO E6B2-CWZ3E, the colours referred to below will only apply to this model.

There are four wires:

  1. GroundCommon (Blue) - GND
  2. Voltage (Brown) - 5V
  3. A switch (Black) - 2
  4. B switch ( White ) - 3

IMG_0048.jpgrotaryencodercircuit.png

Getting started

RotaryThe encodersencoder workproduces usingpulses twoon switchesthe whichA and B channels as it rotates. These pulses are operated slightly90° out of phase,phase meaning(quadrature), thatwhich inlets oneyou directiondetect switchboth the amount of rotation and the direction. By reading these pulses with interrupts (which are triggered whenever the state of A thenor B pulsechanges), fromthe LOWArduino tocan HIGH,keep track of how far and in the otherwhich direction switchthe encoder has moved.

Key Types of Rotary Encoders

Incremental Rotary Encoder
  • Outputs: Two signals (A and B thenchannels) are generated as the shaft rotates, and these signals are in quadrature (90° out of phase).
  • Working Principle: The encoder produces pulses as the shaft rotates. By counting these pulses, you can determine the angle or the distance travelled. The direction of rotation is determined by the relative timing of the A and B pulses.
  • Applications: Motor control, robotics, CNC machines, etc.
  • Endless rotation: They can rotate endlessly without resetting, but they only provide relative position information.

Here’s a simple visual explanation of how an incremental rotary encoder works:

         A Signal:   __|‾|__|‾|__|‾|__|‾|__|‾|
         B Signal:   _|‾|__|‾|__|‾|__|‾|__|‾|_
                    ← Rotate CW ←        ← Rotate CCW ←

When the shaft rotates, the A and B signals switch between high and low states. By detecting which signal changes first, you can determine the direction of rotation. Each pulse LOWcounts thena HIGH,step, enablingwhich is related to the angular movement of the shaft.

Absolute Rotary Encoder
  • Outputs: A unique signal (digital or analog) for each specific position of the shaft.
  • Working Principle: Absolute encoders generate a unique code or position value for every possible shaft angle. This allows you to detectalways bothknow thatthe exact position, even after power is cycled.
  • Applications: Industrial automation, robotics, and anywhere precise positional feedback is needed.
  • Single-turn vs. Multi-turn: Single-turn encoders measure the position within a pulsesingle happenedrotation, i.e.while thatmulti-turn it was rotated, butencoders also inkeep whichtrack direction.

    of the number of rotations.

Basic Example

In this basic exampleexample, the encoder outputs the value as a positive or negative number from it'sits starting position.

#define// enc1A_pinPin 2definitions
#defineconst enc1B_pinint 3encoderPinA boolean= enc1A_prev;2;
booleanconst enc1B_prev;int encoderPinB = 3;

// Variables to store current and previous states of the encoder
volatile long enc1encoderValue = 0;
longvolatile prev_enc1int lastEncoded = 0;

void setup() {
  // Setup the encoder pins as inputs
  pinMode(encoderPinA, enc1A_pin, INPUT_PULLUP )INPUT);
  pinMode(encoderPinB, enc1B_pin,INPUT);
  
  INPUT_PULLUP// )Enable pullup resistors on the encoder pins
  digitalWrite(encoderPinA, HIGH);
  digitalWrite(encoderPinB, HIGH);
  
  // Attach interrupt to the encoder pins
  attachInterrupt(digitalPinToInterrupt(encoderPinA), updateEncoder, CHANGE);
  attachInterrupt(digitalPinToInterrupt(encoderPinB), updateEncoder, CHANGE);

  Serial.begin( 9600 )9600);
}

void loop() {
  boolean// enc1APrint the encoder value (step count)
  Serial.print("Encoder Value: ");
  Serial.println(encoderValue);
  delay(100); // Adjust for your needs
}

void updateEncoder() {
  // Read the encoder pins
  int MSB = !digitalRead( enc1A_pin )encoderPinA); boolean// enc1BMSB = !most significant bit
  int LSB = digitalRead(encoderPinB); enc1B_pin// );LSB = least significant bit
  
  int encoded = (MSB << 1) | LSB; // Combine A and B into a single value
  int sum = (lastEncoded << 2) | encoded; // Combine previous and current values

  // Determine the direction of rotation
  if ( enc1A_prevsum == 00b1101 &&|| enc1Asum == 10b0100 &&|| enc1B_prevsum == 10b0010 &&|| enc1Bsum == 10b1011) ){
    enc1+encoderValue++; // Clockwise
  } else if ( enc1A_prevsum == 10b1110 &&|| enc1Asum == 10b0111 &&|| enc1B_prevsum == 00b0001 &&|| enc1Bsum == 10b1000) ){
    enc1-encoderValue--; if// ( prev_enc1 != enc1 ) {
    Serial.println( enc1 );Counter-clockwise
  }

  if ( enc1A_prev != enc1A ) enc1A_prevlastEncoded = enc1A;encoded; if// (Store enc1B_prevthe !=current enc1Bstate )for enc1B_prevthe =next enc1B;
  
  prev_enc1 = enc1;loop
}