How Rotary Encoders Work and Interface With Arduino
by Lisleapex Blog in Circuits > Arduino
134 Views, 0 Favorites, 0 Comments
How Rotary Encoders Work and Interface With Arduino
We are surrounded by rotary encoders without even realizing it, as they are used in many everyday items, from printers and cameras to CNC machines and robots. The most common application for a rotary encoder is the volume knob on a car radio.
Supplies
- Rotary encoder
- Arduino
- servo motor
Rotary Encoders and Potentiometers
The rotary encoder is the modern digital equivalent of the potentiometer and is more versatile.
A rotary encoder can rotate a full 360° without stopping, while a potentiometer can only rotate 3/4 of a turn.
A potentiometer is used in situations where the exact position of the knob needs to be known. On the other hand, a rotary encoder is used in situations where the change in position needs to be known, rather than the exact position.
How Rotary Encoders Work
The encoder has a slotted disk inside that is connected to a common ground pin C. It also has two contact pins A and B.
When you turn the knob, A and B make contact with the common ground pin C in a specific order, depending on the direction you turn the knob.
When they make contact with the common ground, two signals are generated. These signals are 90° out of phase because one pin touches the common ground before the other. It is called quadrature encoding.
When the knob is turned clockwise, the A pin is connected to ground before the B pin. When the knob is turned counterclockwise, the B pin is connected to ground before the A pin.
By monitoring when each pin is connected or disconnected from ground, we can determine the direction the knob is turned. This can be done by simply observing the state of B when the state of A changes.
When A changes state:
If B != A, turn the knob clockwise.
If B = A, turn the knob counterclockwise.
Rotary Encoder Pinout
GND is the ground connection.
vcc is the positive supply voltage, usually between 3.3 and 5 volts.
SW is the output of the push button switch (active low). When the knob is pressed, the voltage goes low.
DT (output B) is similar to the CLK output, but lags CLK by 90° phase shift. This output is used to determine the direction of rotation.
CLK (output A) is the main output pulse used to determine the amount of rotation. Each time the knob is turned in either direction with only one detent (click), the "CLK" output goes through a high then low cycle.
Connecting the Rotary Encoder to the Arduino
Now that we understand how the rotary encoder works, it's time to use it!
Let's connect the rotary encoder to the Arduino. The connections are pretty simple. Start by connecting the +V pin of the module to the 5V output of the Arduino and the GND pin to ground.
Now connect the CLK and DT pins to digital pins #2 and #3 respectively. Finally, connect the SW pin to digital pin #4.
The image below shows the wiring.
Controlling Servo Motors Using Rotary Encoders
In the following example, we will use a rotary encoder to control the position of a servo motor.
This project can be very useful in a variety of situations. For example, if you want to operate a robotic arm, it can help you accurately position the arm and its grip. If you are not familiar with servo motors, read the following tutorial.
Wiring
Let's include a servo motor in our project. Connect the red wire of the servo motor to an external 5V power supply, the black/brown wire to ground, and the orange/yellow wire to digital pin 9, which is PWM enabled.
Of course, you can use the 5V output of the Arduino, but keep in mind that the servo may induce electrical noise on the 5V power line, which may damage your Arduino. Therefore, it is recommended that you use an external power supply.
Arduino Code
This is the code for precisely controlling a servo motor using a rotary encoder. Each time the knob is turned one notch (click), the position of the servo arm changes by one degree.
Here are the following codes,
// Include the Servo Library
#include <Servo.h>
// Rotary Encoder Inputs
#define CLK 2
#define DT 3
Servo servo;
int counter = 0;
int currentStateCLK;
int lastStateCLK;
void setup() {
// Set encoder pins as inputs
pinMode(CLK,INPUT);
pinMode(DT,INPUT);
// Setup Serial Monitor
Serial.begin(9600);
// Attach servo on pin 9 to the servo object
servo.attach(9);
servo.write(counter);
// Read the initial state of CLK
lastStateCLK = digitalRead(CLK);
}
void loop() {
// Read the current state of CLK
currentStateCLK = digitalRead(CLK);
// If last and current state of CLK are different, then pulse occurred
// React to only 1 state change to avoid double count
if (currentStateCLK != lastStateCLK && currentStateCLK == 1){
// If the DT state is different than the CLK state then
// the encoder is rotating CCW so decrement
if (digitalRead(DT) != currentStateCLK) {
counter --;
if (counter<0)
counter=0;
} else {
// Encoder is rotating CW so increment
counter ++;
if (counter>179)
counter=179;
}
// Move the servo
servo.write(counter);
Serial.print("Position: ");
Serial.println(counter);
}
// Remember last CLK state
lastStateCLK = currentStateCLK;
}