Rotary encoder with Arduino in detail with example codes

Rotary encoder with Arduino in detail Rotary encoder with Arduino in detail

In this detailed tutorial learn how to interface a Rotary encoder with Arduino and display the encoded directional values on 16X2 LCD display when rotated in clockwise and anti clockwise directions. And also learn about Rotary encoder and how it works with Example Arduino program codes.

What is Rotary Encoder?

A rotary encoder is an input device which looks like a potentiometer, but it outputs a series of pulses, which are different from others and unique. When rotary encoder knob is turned clockwise or anti clockwise, it rotates in small steps which produces analog or digital signals. These signals are ideal to control stepper motors, servo motors, Dimming and brightening of lights, incrementing/decrementing digital values, measuring the lengths and many more.

How Rotary Encoder works?

A rotary encoder is an electromechanical transducer, which means it converts mechanical movement into electrical pulses. It consists of a knob, when rotated in steps produce a sequence of pulses, each conductive steps are placed on the disc with predefined lengths and gaps. There are many types of encoders each with their own working mechanism, which we already learnt in our previous article, Now as we are using KY040 incremental rotary encoder Arduino in this tutorial lets learn about it.

rotary encoder working

The internal mechanical structure of the encoder is shown in the above image. It basically of a disc (black) non conductive material and a conductive pads(white gaps) placed on surface of that disc. These conductive pads are placed at regular equal intervals. The output pins are fixed on this disc so that when the knob is rotated, the conductive pads touch output pins and generate waveforms. There are two output pins here, Output A and Output B, as shown in the above image.

The output waveforms produced by output pin A and output B are represented in dark blue and sky blue respectively as shown in the above image. When the conductive pad makes contact with the pin, it goes high, and when the conductive pad is moved away from the pin, the pin goes low for the waveform shown above. So by counting the number of pulses we can determine how many steps it moved.

rotay encoder directional waveform

We need 2 pins and 2 waveforms to determine the direction in which the knob is rotated, If we use only one we may end up with just the movement but we cannot find the direction. If you look at these two pulses, you will notice that they are both 90° out of phase. So when the knob is turned clockwise, output A will go high first, and when the knob is turned anticlockwise, output B will go high first.

To know more about Rotary Encoder principle and its working in detail refer this Article: What is Rotary Encoder? Types, Principle, working in detail

Required components:

  • Rotary encoder
  • Arduino microcontroller
  • 16X2 LCD display with I2C adapter
  • Few connecting wires.

KY-040 Rotary Encoder Pinout Diagram

Rotary encoder pin out diagram

There are total of 5 pins from which GND and + pins are used to power the encoder which we need to connect to 5V supply. The encoder also has a switch (active low) which we can use it by pressing the knob from top whose signal can be obtained from the pin SW. Finally it has two output pins CLK and DT which produce the waveform as described above. Now let’s learn how to interface encoder with Arduino.

Arduino Rotary Encoder Circuit Diagram:

Here we are using Arduino UNO board, you can use Other Arduino versions also, for pin diagrams refer article: What is Arduino?. Now connect Rotary Encoder with Arduino UNO and LCD display as shown in the below circuit diagram.

Arduino Rotary Encoder Circuit Diagram

From the above circuit diagram you can see that the rotary encoder is connected to Arduino as the power pins VCC and GND of encoder are connected to 5V and GND of Arduino respectively, The output pins CLK and DT are connected to digital pin6 and digital pin 7 respectively.

As we are using an LCD display with I2C adapter, it has only 4 pins. The power pins of LCD display which are VCC and GND are connected to 5V and GND of Arduino respectively and the I2C communication pins SDA and SCL are connected to A4 and A5 respectively.

If you wish to use LCD display without I2C adapter refer this article: Interfacing LCD Display with Arduino in detail

To use the feature of switch you need to use the pin SW and connect a 10K ohm resistor is connected from a 5v supply to pull up the signal.

Arduino Rotary encoder Example code to read position and direction of Rotation:

Now its time to upload the code. connect Arduino to a PC where Arduino IDE is installed. Choose the board as Arduino UNO or which ever you use and select the correct port from the Tools menu. Install required libraries from the built in Library manager or you can download the latest version from the below links

Required Libraries:

  • Download LiquidCrystal_I2C – Link

Next copy the below code and paste it in IDE workspace and press upload button. That’s it the code will be uploaded.

// Tested and compiled with no errors
// Rotary encoder with Arduino to print position and direction of rotation
// source - www.circuitschools.com
#include <LiquidCrystal_I2C.h>
#define outputA 6
#define outputB 7

// Initialize the LCD library with I2C address and LCD size
LiquidCrystal_I2C lcd (0x27, 16,2);

int counter = 0;
int currentStateA;
int lastStateA;
String currentDir ="";

void setup() {
  
  // Set encoder pins as inputs
  pinMode(outputA,INPUT);
  pinMode(outputB,INPUT);


  // Setup Serial Monitor
  Serial.begin(9600);
  lcd. init ();
// Turn on the backlight on LCD. 
  lcd. backlight ();
  lcd.print ("CIRCUITSCHOOLS..");
  lcd. setCursor (0, 1);
  lcd.print ("ROTARY ENCODER");
  
delay(2000);
lcd.clear();
     lcd.setCursor(0, 0);
lcd.print("Rotate the knob");
  // Read the initial state of outputA
  lastStateA = digitalRead(outputA);
}

void loop() {
  
  // Read the current state of outputA
  currentStateA = digitalRead(outputA);


  // If last and current state of outputA are different, then pulse occurred
  // React to only 1 state change to avoid double count
  if (currentStateA != lastStateA  && currentStateA == 1){

    // If the outputB state is different than the outputA state then
    // the encoder is rotating CCW so decrement
    if (digitalRead(outputB) != currentStateA) {
      counter ++;
      currentDir ="CW";
    } else {
      // Encoder is rotating CW so increment
      counter --;
      currentDir ="ACW";
    }

    Serial.print("Direction: ");
    Serial.print(currentDir);
    Serial.print(" | Counter: ");
    Serial.println(counter);
lcd.clear();
    lcd.setCursor(0, 0);
lcd.print("Position: ");
lcd.setCursor(10, 0);
lcd.print(counter);
lcd.setCursor(0, 1);
lcd.print("Dir: ");
lcd.setCursor(5, 1);
lcd.print(currentDir);
  }

  // Remember last outputA state
  lastStateA = currentStateA;

  // Put in a slight delay to help debounce the reading
  delay(1);
}

Output:

After uploading the code open serial monitor at baud rate 9600 and check the position of the knob and direction of the rotation. So when you rotate the knob in Anti clock wise direction the counter position increases, and decreases when you rotate in anti clockwise direction.

rotary encoder with arduino output on serial monitor

 

Also the same information is displayed on the LCD display which we connected as shown in the below image.

rotary encoder with arduino position and direction on lcd display

Example 2: Measure distance with Rotary Encoder

Please refer this DIY article for this example: DIY Measuring Wheel using Arduino and Rotary Encoder

If you like this Arduino Rotary encoder project please subscribe to our YouTube Channel “Circuit Schools to encourage us to publish more interesting projects. If you have any doubts write to us from below comment section.

4 comments
  1. Excellent tutorial.. Thank you! I’ve tried about 10 others before this, but this is the first one that worked correctly. It doesn’t skip values and is completely consistent. I skinnied down the loop as much as possible (print value only to lcd, no serial.print, left in the 1ms delay) and get between 20 and 25 increments/decrements per turn. Nice job! Keep up the good work!!

    1. This example is polling the inputs. Have you tested those examples that use hardware interrupts (with RotaryEncoder.h and those dedicated hardware interrupt pins)? I plan to use a rotary decoder alongside with an SPI LCD (again, on dedicated HW pins) and a PID. The main loop will be quite big and I’m using a Pro Mini at 3.3V (8MHz) so a polling rotary encoder may not be the best solution. I may be back with some results if you’re interested.

  2. Thank you for this tutorial and for sharing the code for this. I didn’t have a KY040 but was able to use a basic encoder (A / GND / B) by pulling the input pins high:

    pinMode(outputA,INPUT_PULLUP);
    pinMode(outputB,INPUT_PULLUP);

    and it works perfectly.

  3. While this is ok for learning purposes but will not work in practical application because buttons and switches must use hardware interrupts otherwise the mcu will not respond to user inputs.

Leave a Reply

Your email address will not be published. Required fields are marked *