Arduino Nano - Rotary Encoder

by DIYables in Circuits > Arduino

33 Views, 0 Favorites, 0 Comments

Arduino Nano - Rotary Encoder

arduino-nano-rotary-encoder-cover.jpg

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://newbiely.com/tutorials/arduino-nano/arduino-nano-rotary-encoder

This build reads a rotary encoder with an Arduino Nano: turning the knob increases or decreases a counter depending on direction, and pressing the knob's built-in button is detected separately. The encoder outputs two offset pulse signals (CLK and DT) instead of an analog voltage, which makes it useful for counting turns, menu navigation, or controlling things like LED brightness, servo position, or stepper speed.

Supplies

Wiring

arduino-nano-rotary-encoder-wiring-diagram.jpg

Connect the encoder's CLK pin to Nano pin 2, DT pin to pin 3, and SW pin to pin 4. Connect VCC to the Nano's 3.3V or 5V and GND to GND. The SW pin is normally open and relies on a pull-up so it reads HIGH when the knob is not pressed and LOW when pressed.

How It Works

Inside the encoder a disc connects pins A and B to a common ground pin as you turn the knob, and A and B touch ground in a different order depending on direction - this is quadrature encoding, with the two signals 90 degrees out of phase. The code watches the CLK pin: when it changes from LOW to HIGH, it checks DT. If DT is HIGH the knob turned anticlockwise and the counter decreases; if DT is LOW it turned clockwise and the counter increases.

Code

The sketch configures CLK and DT as inputs and uses the ezButton library to debounce the SW pin with a 50ms debounce time. In the main loop it reads CLK, compares it to its previous state, and on a LOW-to-HIGH edge reads DT to decide direction, updating and printing the counter over serial. It also checks button.isPressed() to report presses. A second version of the sketch does the same detection using interrupts instead of constantly polling the CLK pin, which avoids missing a turn while other code is running and frees up the Nano.

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

/*
* This Arduino Nano code was developed by newbiely.com
*
* This Arduino Nano code is made available for public use without any restriction
*
* For comprehensive instructions and wiring diagrams, please visit:
* https://newbiely.com/tutorials/arduino-nano/arduino-nano-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 // anticlockwise direction

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

ezButton button(SW_PIN);

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 anticlockwise 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("Twisted direction: ");
if (direction == DIRECTION_CW)
Serial.print("CLOCKWISE");
else
Serial.print("ANTICLOCKWISE");

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://newbiely.com/tutorials/arduino-nano/arduino-nano-rotary-encoder