Arduino Experiment: Set Up Rotary Encoder

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.

Required Components

Wiring Instructions

Understanding the Rotary Encoder

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.

Code Explanation

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.

Key Functions

Arduino Code

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
}
            

How It Works

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.

Upload and Test

  1. Connect your Arduino to your computer via the USB cable.
  2. Open the Arduino IDE and paste the code above into the editor.
  3. Select your board and port from the IDE menu.
  4. Click the upload button to load the code onto your Arduino.
  5. Open the serial monitor and rotate the encoder. You should see the encoder value change as you rotate it.
  6. Press the button on the encoder and observe the message printed in the serial monitor.

Conclusion

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.