Arduino - Rotary Encoder

by DIYables in Circuits > Arduino

16 Views, 0 Favorites, 0 Comments

Arduino - Rotary Encoder

This is a compact build guide. The full tutorial, with the wiring diagram and a line-by-line walkthrough of the code, is here: https://arduinogetstarted.com/tutorials/arduino-rotary-encoder

This project reads a rotary encoder with an Arduino Uno. As you turn the knob, the encoder's CLK and DT pins pulse out of phase with each other, letting the Arduino figure out how far and in which direction the knob moved, while a built-in pushbutton on the SW pin can be read separately. It's a direction-and-click input, useful anywhere you'd otherwise reach for a potentiometer.

Supplies

Wiring

Connect the rotary encoder's CLK pin to Arduino digital pin 2, the DT pin to digital pin 3, and the SW pin to digital pin 4. Connect the encoder's VCC pin to the Arduino's 5V (or 3.3V) pin and its GND pin to Arduino GND.

How It Works

Inside the encoder a slotted disc connects pins A and B to a common ground pin C as the knob turns. Because A and B touch ground at slightly different times, their signals (CLK and DT) are 90 degrees out of phase, a pattern called quadrature encoding. When CLK goes from LOW to HIGH, checking DT tells you direction: DT LOW means clockwise, DT HIGH means counter-clockwise. The SW pin is normally HIGH through a pull-up and goes LOW when the knob is pressed.

Code

The sketch sets CLK and DT as inputs and uses the ezButton library to debounce the SW pin. In the loop it reads CLK, and whenever it sees a LOW-to-HIGH transition it checks DT to decide direction, then increments or decrements a counter and prints the direction and count to the Serial Monitor. A separate version does the same thing using an interrupt on the CLK pin instead of continuously polling it, which avoids wasting Arduino cycles and prevents missed counts if other code is running.

arduino-rotary-encoder.ino - the sketch from the tutorial, unchanged.

/*
* Created by ArduinoGetStarted.com
*
* This example code is in the public domain
*
* Tutorial page: https://arduinogetstarted.com/tutorials/arduino-rotary-encoder
*/

#include <ezButton.h> // the library to use for SW pin

#define CLK_PIN 2
#define DT_PIN 3
#define SW_PIN 4

#define DIRECTION_CW 0 // clockwise direction
#define DIRECTION_CCW 1 // counter-clockwise direction

int counter = 0;
int direction = DIRECTION_CW;
int CLK_state;
int prev_CLK_state;

ezButton button(SW_PIN); // create ezButton object that attach to pin 4

void setup() {
Serial.begin(9600);

// configure encoder pins as inputs
pinMode(CLK_PIN, INPUT);
pinMode(DT_PIN, INPUT);
button.setDebounceTime(50); // set debounce time to 50 milliseconds

// read the initial state of the rotary encoder's CLK pin
prev_CLK_state = digitalRead(CLK_PIN);
}

void loop() {
button.loop(); // MUST call the loop() function first

// read the current state of the rotary encoder's CLK pin
CLK_state = digitalRead(CLK_PIN);

// If the state of CLK is changed, then pulse occurred
// React to only the rising edge (from LOW to HIGH) to avoid double count
if (CLK_state != prev_CLK_state && CLK_state == HIGH) {
// if the DT state is HIGH
// the encoder is rotating in counter-clockwise direction => decrease the counter
if (digitalRead(DT_PIN) == HIGH) {
counter--;
direction = DIRECTION_CCW;
} else {
// the encoder is rotating in clockwise direction => increase the counter
counter++;
direction = DIRECTION_CW;
}

Serial.print("DIRECTION: ");
if (direction == DIRECTION_CW)
Serial.print("Clockwise");
else
Serial.print("Counter-clockwise");

Serial.print(" | COUNTER: ");
Serial.println(counter);
}

// save last CLK state
prev_CLK_state = CLK_state;

if (button.isPressed()) {
Serial.println("The button is pressed");
}
}

Full Tutorial

The complete tutorial, wiring diagram and code explanation: https://arduinogetstarted.com/tutorials/arduino-rotary-encoder