Difficulty Level: Intermediate
A rotary encoder is an input device that allows the user to rotate a knob and capture both the direction of rotation and how much the knob has been turned. It’s used in a wide variety of projects, such as volume control, navigation menus, or even motor control.
Rotary encoders have two outputs, typically called "A" (or CLK) and "B" (or DT). As the encoder turns, these two outputs toggle between HIGH and LOW in a specific sequence. The direction of rotation can be determined by the order in which these signals change.
Encoders also often include a push button (SW pin), allowing for additional control when pressed down, making them versatile input devices.
The following Arduino code reads the rotary encoder and detects the direction of rotation. Additionally, it tracks when the button on the encoder is pressed.
attachInterrupt()
: Sets up an interrupt on the clock pin to trigger when the encoder moves.digitalRead()
: Reads the current state of the encoder pins to determine the rotation direction.encoderValue
: Keeps track of the current position of the encoder.Here is the code to set up a rotary encoder and track its rotation and button press:
// Rotary Encoder Pins
#define CLK 2 // Clock pin
#define DT 3 // Data pin
#define SW 4 // Button pin
volatile int encoderValue = 0; // Track encoder position
int lastClkState; // Store the last state of the CLK pin
void setup() {
pinMode(CLK, INPUT);
pinMode(DT, INPUT);
pinMode(SW, INPUT_PULLUP); // Internal pull-up for button
// Initialize serial communication
Serial.begin(9600);
// Attach interrupt to the CLK pin to trigger on change
attachInterrupt(digitalPinToInterrupt(CLK), updateEncoder, CHANGE);
lastClkState = digitalRead(CLK); // Get initial state of CLK pin
}
void loop() {
// Check for button press (low when pressed)
if (digitalRead(SW) == LOW) {
Serial.println("Button Pressed!");
delay(200); // Debounce delay
}
// Print encoder value to serial monitor
Serial.print("Encoder Value: ");
Serial.println(encoderValue);
delay(100); // Slow down the output
}
// Interrupt service routine for encoder
void updateEncoder() {
int currentClkState = digitalRead(CLK);
int currentDtState = digitalRead(DT);
// Determine rotation direction
if (currentClkState != lastClkState) {
if (currentDtState != currentClkState) {
encoderValue++;
} else {
encoderValue--;
}
}
lastClkState = currentClkState; // Update the last CLK state
}
The interrupt attached to the clock pin (CLK) triggers every time the encoder rotates. Inside the interrupt service routine, the current state of the data pin (DT) is read. By comparing the states of the CLK and DT pins, the direction of rotation is determined, and the encoder value is incremented or decremented accordingly.
Additionally, the button press is checked in the main loop using digitalRead()
, and a message is printed to the serial monitor when the button is pressed.
This experiment demonstrated how to interface a rotary encoder with Arduino. By reading the signals from the CLK and DT pins, you can accurately detect the direction and amount of rotation. Additionally, the built-in button provides extra control, making rotary encoders a versatile input device for projects like navigation, motor control, and volume adjustment.