How to Measure Angle and Direction of Rotation with Arduino and Rotary Encoder

Introduction

Welcome to the world of Arduino and rotary encoders! In this guide, we’ll explore How to Measure Angle and Direction of Rotation with Arduino and Rotary Encoder. Rotary encoders are versatile devices that provide precise rotational position feedback, making them essential components in various projects ranging from robotics to user interfaces. Let’s delve into the fascinating world of rotary encoders and discover how they can enhance your Arduino projects.

Hardware Required

You will require the following Hardware Components for how to measure angle and direction of rotation using a rotary encoder module with Arduino.

Components#Buy From Amazon
Arduino UNO1Buy Link
Rotary Encoder Module1Buy Link
37 in 1 Sensor kit (Optional)1Buy Link
9v DC Adapter (Optional)1Buy Link
Jumper Wires5Buy Link
Breadboard1Buy Link

What is a Rotary Encoder?

A rotary encoder is a versatile device used to determine the position and angular velocity of a motor or drive, commonly interfaced with processors like Arduino.

In the realm of DIY electronics projects, electromechanical rotary encoders are frequently encountered. While they may resemble potentiometers externally, they operate differently both electronically and behaviorally.

These encoders generate digital pulses with each rotation, typically with a common pulse count of 256 per turn. Many models also include a button that triggers when the encoder is pressed.

While not ideal for direct position sensing due to coupling difficulties and low resolution, rotary encoders excel as control interfaces. They’re commonly used for tasks like adjusting screen brightness, device volume, or motor angles.

How does a Rotary Encoder work?

Inside, the encoder consists of two brushes that glide along a metal track featuring divisions. As the shaft rotates, a small metal ball makes contact, functioning as a push button.

arduino-encoder-interior-design

Typically, rotary encoders feature two outputs, effectively forming a system akin to having two buttons (referred to as Channel A and B). These buttons are positioned offset from each other, creating what’s known as a quadrature encoder.

In a quadrature encoder, there’s a phase difference between the two sensors, causing their signals to be shifted electrically by 90 degrees. Visually, the signal of both channels relative to the rotated angle would appear as follows:

arduino-encoder-working

The benefit of quadrature encoders extends beyond position and speed detection; they also enable the determination of rotation direction.

To illustrate, let’s focus on the rising or falling edges of Channel A as event triggers. When rotating clockwise (CW), events occur at t0, t1, t2, t3… tn.

Observing Channel B during these events, we note that its signal is consistently opposite to that of Channel A.

arduino-encoder-cw

If we reverse the rotation direction and use the falling or rising edges of Channel A as reference points, we observe that at instants (t0, t1, t2, t3… tn), the signals from both Channel A and B are consistently identical.

arduino-encoder-ccw

In reality, whether the rotation direction is clockwise (CW) or counterclockwise (CCW) depends on factors such as the sensor’s internal construction and the channel used as a reference.

Nevertheless, it’s possible to differentiate the rotation direction simply by comparing the signals obtained from the quadrature encoder. Assigning a CW or CCW meaning is straightforward by testing the setup once.

As for precision, we have multiple options:

  1. Single precision: recording a single edge (rising or falling) on a single channel.
  2. Double precision: recording both edges on a single channel.
  3. Quadruple precision: recording both edges on both channels.

Pinout of Rotary Encoder Module

Rotary-Encoder-Module-Pinout

Pin Configuration of Rotary Encoder

Pin NameDescription
GNDConnected to GROUND
+Connected to +5V
SWOutput of internal button
DTContact A output or DATA
CLKContact B output or CLOCK

Circuit Diagram

The following circuit shows you the connection of How to Measure Angle and Direction of Rotation with Arduino and Rotary Encoder, Please make the connection carefully

How-to-Measure-the-angle-and-direction-of-rotation-with-Arduino-and-rotary-encoder-Circuit

Circuit Connections

ArduinoRotary Encoder Module
++5V Pin
GNDGND Pin
CLKD2
DTD3
SWD9

Installing Arduino IDE Software

First, you will require to Download the updated version of Arduino IDE Software and Install it on your PC or laptop. if you Learn How to install the Arduino step-by-step guide then click on how to install Arduino Button given Blow

Code Examples

Single or double precision per pool:

In this initial example, we’re reading the encoder by polling without relying on interrupts. We can utilize any two digital inputs, such as D9 and D10, for this purpose. The precision can be set to either double or single, and to switch between the two, you’ll need to modify the commented line within the conditional statement. However, I can’t think of a reason to prefer single precision over double in this context.

//For more Projects: www.arduinocircuit.com

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

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

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

const int timeThreshold = 5;
unsigned long currentTime;
unsigned long loopTime;

bool IsCW = true;

void setup() {
  Serial.begin(9600);
  pinMode(channelPinA, INPUT);
  pinMode(channelPinB, INPUT);
  currentTime = millis();
  loopTime = currentTime;
  value = 0;
  prevValue = 0;
}

void loop() {
  currentTime = millis();
  if (currentTime >= (loopTime + timeThreshold))
  {
    stateChannelA = digitalRead(channelPinA);
    stateChannelB = digitalRead(channelPinB);
    if (stateChannelA != prevStateChannelA) // For single precision if((!stateChannelA) && (prevStateChannelA))
    {
      if (stateChannelB) // B is HIGH, is CW
      {
        bool IsCW = true;
        if (value + 1 <= maxSteps) value++; // Make sure we don't exceed maxSteps
      }
      else // B is LOW, is CWW
      {
        bool IsCW = false;
        if (value - 1 >= 0) value = value--; // Make sure we have no negatives
      }

    }
    prevStateChannelA = stateChannelA; // Save values ​​for next

    // If the value has changed, display it
    if (prevValue != value)
    {
      prevValue = value;
      Serial.print(value);

    }

    loopTime = currentTime; // Update time
  }
  
  // Other tasks
}

Double precision with one interruption:

In this example, we substitute one of the digital inputs with an interrupt, enabling us to register both rising and falling edges. As a result, we achieve double precision.

//For more Projects: www.arduinocircuit.com

const int channelPinA = 2;
const int channelPinB = 10;

const int timeThreshold = 5;
long timeCounter = 0;

const int maxSteps = 255;
volatile int ISRCounter = 0;
int counter = 0;

bool IsCW = true;

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

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

void doEncode()
{
  if (millis() > timeCounter + timeThreshold)
  {
    if (digitalRead(channelPinA) == digitalRead(channelPinB))
    {
      IsCW = true;
      if (ISRCounter + 1 <= maxSteps) ISRCounter++;
    }
    else
    {
      IsCW = false;
      if (ISRCounter - 1 > 0) ISRCounter--;
    }
    timeCounter = millis();
  }
}

Quadruple precision with two interruptions:

In this final example, we employ interrupts for both channels, capturing events on both rising and falling edges. This configuration allows us to achieve quadruple precision. However, it comes at the cost of leaving most Arduino models with limited or no additional pins available for interrupts.

//For more Projects: www.arduinocircuit.com

const int channelPinA = 2;
const int channelPinB = 3;

const int timeThreshold = 5;
long timeCounter = 0;

const int maxSteps = 255;
volatile int ISRCounter = 0;
int counter = 0;

bool IsCW = true;

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

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

void doEncodeA()
{
  if (millis() > timeCounter + timeThreshold)
  {
    if (digitalRead(channelPinA) == digitalRead(channelPinB))
    {
      IsCW = true;
      if (ISRCounter + 1 <= maxSteps) ISRCounter++;
    }
    else
    {
      IsCW = false;
      if (ISRCounter - 1 > 0) ISRCounter--;
    }
    timeCounter = millis();
  }
}

void doEncodeB()
{
  if (millis() > timeCounter + timeThreshold)
  {
    if (digitalRead(channelPinA) != digitalRead(channelPinB))
    {
      IsCW = true;
      if (ISRCounter + 1 <= maxSteps) ISRCounter++;
    }
    else
    {
      IsCW = false;
      if (ISRCounter - 1 > 0) ISRCounter--;
    }
    timeCounter = millis();
  }
}

Applications

  1. Motor Control: Rotary encoders are widely used in motor control systems to precisely monitor the position and speed of rotating shafts. By integrating rotary encoders with motors, you can achieve accurate control over motor movements in robotics, CNC machines, and industrial automation applications.
  2. User Interfaces: Incorporate rotary encoders into user interfaces for interactive control and navigation. These encoders can be used as input devices for adjusting settings, scrolling through menus, or controlling volume and brightness in electronic devices such as audio systems and digital displays.
  3. Navigation Systems: Utilize rotary encoders in navigation systems to measure angular displacement and direction of rotation. In applications such as compasses or directional gyroscopes, rotary encoders provide precise feedback on orientation and heading changes.
  4. Camera Pan-Tilt Mechanisms: Implement rotary encoders in camera pan-tilt mechanisms to enable precise control over camera movements. By coupling rotary encoders with servo motors, you can create stabilized camera platforms for capturing smooth and steady footage in photography, videography, and surveillance systems.

Conclusion

With their versatility and precision, rotary encoders offer endless possibilities for enhancing control and measurement capabilities in Arduino projects. Whether you’re building a robotic arm, designing a user interface, or implementing navigation systems, rotary encoders provide reliable feedback for precise rotational measurements. Let’s get started with building our angle and rotation measurement system with Arduino and a rotary encoder!

How to Make an Optical Encoder with an Opto Switch and Arduino

Leave a Comment


error: