You might want to connect an encoder to your Arduino board when you want to have a physical control over you electronics. The encoder might also be a great alternative to physical pushbuttons as a rotating knob might be a more intuitive solution for some applications.
Table of contents
Encoder
If you look to an encoder – it will look similar to a potentiometer, but its function is totally different. Instead of changing resistance it can generate pulses when you rotate the knob. So, it is a great little device when you want, for example, to control some internal firmware parameters (like audio volume) by rotating its knob. When the encoder has internal button (you press directly on its shaft), it can also be used as a control for an LCD menu.
From the outside, the encoder usually has three pins plus two for the shaft button and when it is sold as a module, its pinout is shown below:

The center pin is usually a ground pin, while two other pins which, when the encoder’s shaft is turned, outputs specific signals.
The encoder’s internals can be seen as two pushbuttons plus the additional shaft button:

When you turn the shaft, the encoder generates two impulse signals which are shifted a bit in time:

So, from Arduino’s point of view, we can wait for one of the pins falling edge and when we detect it, read the second pin. Depending on the second pin’s level (high or low) we can define in which position the encoder was rotated.
Used hardware in this example
- Arduino Nano or equivalent board (Affiliate Aliexpress)
- USB A to Mini USB cable (usually comes with Arduino or can be bought from Aliexpress)
- Encoder module (Affiliate Aliexpress) or encoder without PCB, if you want to solder it in (Aliexpress)
- Some wires
- Breadboard (optional, if you don’t want to solder parts) (Affiliate Aliexpress)
Arduino and encoder connection
If you have encoder with a PCB, it will probably have these pins: GND, +, SW, DT, CLK. The naming might be different, but the idea should be the same: GND connects one switch pin and center encoder’s pin to ground. The + pin is used to pull up encoder output signal to positive power rail through soldered resistors. SW is the second pin of the shaft switch and DT and CLK are two encoder’s pins which generates impulses when the shaft is rotated.
In the end, the encoder to your Arduino board might be connected as shown below:

And this is how everything looks in real life:

Writing some code
Now, we need to read the encoder’s output and detect when the shaft is rotated and in which direction.
I am going to use PlatformIO IDE for writing firmware code. I have already written how to use it for your projects here.
For this tutorial I will use only the encoder pins, without the integrated switch – reading a button state is quite straight forward.
Firstly, let’s define some encoder pins which are going to be using throughout this example:
#define pinA 3
#define pinB 4
volatile int rotation = 0;
Variable rotation is used to define in which direction the shaft turns. In this case, possible values are -1 (one direction), 0 (stationary) and 1 (another direction).
Interrupt function
To detect a falling encoder output edge, I suggest using the interrupt. For it we should write a function which will run when the interrupt triggers:
void rotary(){
if (!digitalRead(pinA)){
if(!digitalRead(pinB)){
delay(100);
rotation = -1;
}
else {
delay(100);
rotation = 1;
}
}
}
Arduino Nano (and other ATmega328p based) boards can use only 2 and 3 pins as external interrupt source.
The first line of the rotary() function checks if the status of pinA is low and because this function runs when there is CHANGE interrupt on that pin, it means that there was a falling edge. The line if(!digitalRead(pinB)) checks the status of the seconds encoder’s pin. If it is LOW, we have knob turning in one direction (sets rotation = -1) and if its is HIGH (and the rotation is set to 1), then it was turned in another direction. To know in which exact direction the knob was turned it is best to find out via trial and error – just try to turn it and see what direction it reports.
Setup function
Now let’s fill in the setup() function with some code:
void setup() {
Serial.begin(9600);
pinMode(pinA, INPUT);
pinMode(pinB, INPUT);
attachInterrupt(digitalPinToInterrupt(pinA), rotary, CHANGE);
}
First line initializes Serial interface. Then we set up pins connected to the encoder as inputs. Finally, we set up the interrupt, which is assigned to pinA, and when there is a changing edge on that pin, the interrupt runs function called rotary.
Loop function
Then, the loop function could be written as it is shown below:
void loop() {
if(rotation != 0){
if (rotation == 1){
Serial.println("LEFT");
}
else if (rotation == -1){
Serial.println("RIGHT");
}
rotation = 0;
delay(300);
}
}
In this function we use some code to check if there was change in rotation variable. If rotation is nonzero, then we check what the actual value of the rotation variable is. Then, it checks if it is 1, then the code prints out to the serial interface a string “LEFT”. If the variable is -1, then the code prints out “RIGHT”. Finally it resets rotation to 0.
For convenience the full code is shown below.
#include <Arduino.h>
#define pinA 3
#define pinB 4
volatile int rotation = 0;
void rotary(){
if (!digitalRead(pinA)){
if(!digitalRead(pinB)){
delay(100);
rotation = -1;
}
else {
delay(100);
rotation = 1;
}
}
}
void setup() {
Serial.begin(9600);
pinMode(pinA, INPUT);
pinMode(pinB, INPUT);
attachInterrupt(digitalPinToInterrupt(pinA), rotary, CHANGE);
}
void loop() {
if(rotation != 0){
if (rotation == 1){
Serial.println("LEFT");
}
else if (rotation == -1){
Serial.println("RIGHT");
}
rotation = 0;
delay(300);
}
}
Now, press that upload button and turn the knob to see what it prints out in the serial monitor
.
You should see a similar printout to this one:

Summary
So, here you have a simple example how you can connect and read an encoder with your Arduino board. Although, it might not be a bullet proof code – there might be times when the direction of the rotation is not recognized or recognized incorrectly, but it is good enough example to get you started with encoders and even use it in you final projects.