Contents

Rotary Encoder: How It Works and How to Use with Arduino

Overview

In this tutorial, you’ll get to know how to use the rotary encoder. First, you’ll see some information about the rotational encoder, and then you’ll learn how to use a rotary encoder with three practical examples.

What You Will Learn

What Is a Rotary Encoder?

The rotary encoder is an electromechanical device that converts the position of the shaft angle to digital data. Rotary encoder has a circular plate with some holes and two channels A and B. By rotating the circular plate, when A and B channels pass the holes, a connection between that channel and a common base is established. These interruptions cause a square wave in the output channel. By counting these pulses, we can find the amount of rotation. On the other hand, channels A and B have 90 degrees of the phase difference, so you can also find the rotation direction depending on which channel pulse is ahead.

An encoder can be installed directly on the motor shaft or made as a module. The rotary encoder module, including 5 pins, is the most common rotating encoder. 2 pins support encoder supply, SW is a push button on the module, and CLK and DT show the A and B channels. Some of the features of this module are:
  • The ability of Rotate to infinity
  • 20 pulse resolution
  • 5V supply voltage

How to Use a Rotary Encoder?

To use a rotary encoder, we should count the pulses of channels A and B. To do this, we used Arduino UNO and performed three projects for positioning the encoder, controlling the LED light and controlling the speed and direction of the DC motor.

Rotary Encoder Module Pinout

This module has 5 pins:

  • CLK: Output A
  • DT: Output B
  • SW: Push Switch output (It is normally High, by pressing the knob, it will be LOW).
  • VCC: Module power supply – 5V
  • GND: Ground

You can see the pinout of this module here.

Required Materials

Hardware Components

Arduino UNO R3 × 1
Rotary Encoder Module with Push Switch × 1
Male to Male jumper wire × 1

Software Apps

Arduino IDE

Determining the Position of the Rotary Encoder Shaft

Connect the + to 5V, GND to GND pin, CLK to pin number 6, and DT to pin number 7.

You need to know the position of the shaft to use the encoder. The position of the shaft varies depending on the amount of its rotation. It changes from 0 to infinity for clockwise rotation, and from 0 to minus infinity for the counterclockwise rotation.

Upload the following code on your Arduino and see the position of the shaft encoder in the serial monitor. You can use this code for all your projects with an encoder.

/*
Rotary Encoder - get the position
modified on 23 Feb 2019
by Saeed Hosseini
Home
*/ #define encoderOutA 6 // CLK #define encoderOutB 7 // DT int counter = 0; int State; int old_State; void setup() { pinMode (encoderOutA, INPUT); pinMode (encoderOutB, INPUT); Serial.begin (9600); //Read First Position of Channel A old_State = digitalRead(encoderOutA); } void loop() { State = digitalRead(encoderOutA); if (State != old_State) { if (digitalRead(encoderOutB) != State) { counter ++; } else { counter --; } Serial.print("Position: "); Serial.println(counter); } old_State = State; // the first position was changed }

To determine the encoder position, we need to connect channels A and B as inputs to Arduino. We read and save the initial value of Channel A at the beginning. Then, we read the instantaneous value of channel A, and if the value of Channel B was ahead of it, we decrease the counter. Otherwise, we increase the counter number.

Controlling a LED Light with Shaft Rotation

Circuit

Code

/*
Rotary Encoder - LED Brightness Control
modified on 23 Feb 2019
by Saeed Hosseini
Home
*/ #define encoderOutA 6 // CLK #define encoderOutB 7 // DT #define LED 9 // LED , must connect to pwm pin int brightness = 0; int State; int old_State; void setup() { pinMode (encoderOutA, INPUT); pinMode (encoderOutB, INPUT); pinMode (LED, INPUT); Serial.begin (9600); //Read First Position of Channel A old_State = digitalRead(encoderOutA); } void loop() { State = digitalRead(encoderOutA); if (State != old_State) { if (digitalRead(encoderOutB) != State) { brightness ++; } else { brightness --; } if (brightness >= 255) brightness = 255; if (brightness <= 0) brightness = 0; Serial.print("brightness: "); Serial.println(brightness); } old_State = State; // the first position was changed analogWrite(LED , brightness); }
At first you need to get the shaft position, and then you can reduce or increase the LED light with PWM. Since the PWM has some value between 0 to 255, we set the shaft position in this range in the code too.

Controlling DC Motor Speed and Direction with Interrupt

Circuit

Code

First, install the Adafruit_Motor_Shield_library on your Arduino IDE.

Then, upload the following code on your Arduino Board.

/*
  Rotary Encoder - Controlling a DC Motor using L293D Shield
  modified on 23 Feb 2019
  by Saeed Hosseini
  
Home
*/ #include <AFMotor.h> #define CLK 2 #define DT 5 #define SW 3 AF_DCMotor motor(1, MOTOR12_64KHZ); int motor_dir = 0; int State; int old_State, change; volatile int motor_speed = 0; volatile boolean buttonState = false; void setup() { Serial.begin(9600); pinMode(CLK, INPUT); pinMode(DT, INPUT); pinMode(SW, INPUT_PULLUP); old_State = digitalRead(CLK); attachInterrupt (digitalPinToInterrupt(CLK), encoder_detect, CHANGE); attachInterrupt (digitalPinToInterrupt(SW), button_detect, FALLING); } void loop() { if (!buttonState) { if (motor_speed > 0) { motor.setSpeed(motor_speed); motor.run(FORWARD); Serial.print("Move Forward: "); Serial.println(motor_speed); } else if (motor_speed < 0) { motor.setSpeed((motor_speed) * (-1)); motor.run(BACKWARD); Serial.print("Move Backward: "); Serial.println(motor_speed); } } if (buttonState == true || motor_speed == 0) { motor.run(RELEASE); Serial.println("Break"); } } void encoder_detect () { buttonState = false; State = digitalRead(CLK); if (State != old_State) { if (digitalRead(DT) != State) { motor_speed ++; if (motor_speed >= 255) motor_speed = 255; } else { motor_speed --; if (motor_speed <= -255) motor_speed = -255; } } old_State = State; } void button_detect() { buttonState = true; }

In this code, we have used an interrupt to read the shaft and key position. For more information about interrupts, you can check the Arduino Website.

The motor breaks by pushing the encoder key or setting the encoder in position 0.

You can see how to drive DC motor with the L293D shield here.

Liked What You See?​
Get Updates And Learn From The Best​

Comments (6)

  • matteo Reply

    great mate i appreciate your help to finish school project.cheers!

    November 18, 2019 at 8:58 am
    • Saeed Hosseini Reply

      Thats great, we always try to do our best

      November 24, 2019 at 11:01 am
  • lol Reply

    i am not able to make this it shows’ expected unqualified id before numeric constant’

    July 7, 2020 at 2:47 am
    • Mehran Maleki Reply

      Which line exactly do you get the error from?

      December 9, 2020 at 6:09 am
  • Otto Reply

    I got this web site from my pal who informed
    me regarding this web page and now this time I am visiting this web site and reading very informative articles or reviews
    at this place.

    May 23, 2021 at 3:12 pm
    • Mehran Maleki Reply

      Hi my friend.
      We are so happy to hear this. If you ever come up with any question, you’re so welcome to ask.

      May 24, 2021 at 4:24 am

Leave a Reply

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