Preview build — page text is a draft awaiting human review. Code badges come from real compiles. The flasher is real but not yet hardware-tested; the Playground is still a preview.

Rotary encoder (KY-040) with Arduino Uno — interrupt pins, no missed steps

Wire a KY-040 rotary encoder to an Arduino Uno R3 on interrupt pins D2/D3, count clicks in both directions with the Encoder library and read the button.

Arduino C++Verified — core avr 1.8.8, Encoder 1.4.4, 3 Nov 2026Compile-only

Community draft — report a mistake

A rotary encoder is a knob that turns without end and reports each click and its direction. It suits menus, volume control or setting a timer on an LCD. The KY-040 module adds a push switch and the pull-up resistors.

What matters on the Uno is which pins you use. The encoder sends two square waves, CLK and DT. If you turn it fast, a sketch that only polls them in loop() misses steps. The Uno has exactly two external-interrupt pins, D2 and D3. Put CLK and DT there and Paul Stoffregen’s Encoder library counts every edge in an interrupt, however busy the rest of your code is.

The sketch prints the position and direction on every click, and resets to zero when you press the knob.

Wiring

Arduino Uno R3Only the pins used are shown · 5 V logicKY-040 rotary encoder5VGNDD2D3D4CLKDTSW+GND
Every connection
Arduino Uno R3KY-040 rotary encoderWireNotes
D2CLKyellowINT0
D3DTgreenINT1
D4SWbluePush switch to GND; the sketch uses the internal pull-up.
5V+redPowers the module’s 10 kΩ pull-ups on CLK and DT.
GNDGNDblack

3.3–5 V part, 5 V board. Power the module from your board’s logic voltage (3.3 V on ESP32/Pico) — its pull-ups go to the + pin, so CLK and DT will never exceed that voltage.

Board quirks

  • D2 and D3 are the Uno’s only external-interrupt pins. With both encoder pins there, the Encoder library catches every edge even while loop() is busy. On other pins it falls back to polling and skips steps when you turn fast.
  • The KY-040 gives 4 counts per click, so the sketch divides by 4. Some bare encoders give 2 or 1 — change the divisor if one click moves more than one step.
  • Turning the wrong way? Swap CLK and DT, or swap the 2 and 3 in Encoder knob(2, 3).
  • The library uses attachInterrupt() on D2/D3, so those pins are no longer free for a PIR or a flow sensor’s interrupt.

Code

rotary-encoder-uno.inoArduino C++Open in PlaygroundOpen in PlaygroundFlash
// KY-040 rotary encoder on an Arduino Uno R3, with Paul Stoffregen's Encoder library.
// CLK → D2, DT → D3 (both external-interrupt pins), SW → D4, + → 5V, GND → GND.
#include <Encoder.h>

const uint8_t SW_PIN = 4;
Encoder knob(2, 3);  // both pins have interrupts on the Uno = no missed steps

long lastPos = 0;
bool lastSw = HIGH;

void setup() {
  pinMode(SW_PIN, INPUT_PULLUP);
  Serial.begin(9600);
  Serial.println(F("Turn the knob or press it"));
}

void loop() {
  long pos = knob.read() / 4;  // KY-040: 4 counts per click (detent)
  if (pos != lastPos) {
    Serial.print(pos > lastPos ? F("Clockwise      ") : F("Anticlockwise  "));
    Serial.print(F("position "));
    Serial.println(pos);
    lastPos = pos;
  }
  bool sw = digitalRead(SW_PIN);
  if (sw != lastSw) {
    delay(5);  // simple debounce
    if (digitalRead(SW_PIN) == sw) {
      lastSw = sw;
      if (sw == LOW) {
        knob.write(0);
        lastPos = 0;
        Serial.println(F("Pressed - position reset to 0"));
      }
    }
  }
}

Library: Encoder (Paul Stoffregen) — compiled with Encoder 1.4.4.

Expected serial output

Serial Monitor · 9600Output
Turn the knob or press it
Clockwise      position 1
Clockwise      position 2
Anticlockwise  position 1
Pressed - position reset to 0

Common errors

Position jumps by 2 or goes back and forth

Contact bounce on cheap encoders. Interrupt pins help a lot; add 10 nF capacitors from CLK and DT to GND if it still happens.

Counts only one direction

DT or CLK not connected, or the + pin unpowered (so the pull-ups don’t work).

“Encoder.h: No such file”

Install “Encoder” by Paul Stoffregen from the Library Manager — not one of the other encoder libraries with similar names.

↑↓ to move · Enter to open