Arduino library 路 Input

Encoder: counting a rotary encoder with interrupts

Paul Stoffregen鈥檚 Encoder library (from PJRC, the Teensy makers) keeps an exact count of a quadrature encoder: the KY-040 knob, a motor鈥檚 encoder disk, or anything else with two outputs that switch a quarter cycle apart. Each change on either pin moves the count up or down by one, depending on which pin changed first.

Built in on Mokxi: #include <Encoder.h> and it builds, with nothing to install. Free, and no account needed.

What Encoder does

Its strength is that it counts from interrupts. If both pins can raise an interrupt, every edge is caught however busy loop() is, which matters for a motor shaft spinning fast. On an Uno or Nano only pins 2 and 3 have interrupts, so put the encoder there for the best result; with one interrupt pin it is still good, and with none it falls back to reading the pins whenever you call read().

Because it counts every edge, a typical KY-040 knob moves the count by four for each click you feel. Divide by four for clicks, and swap the two pins in the constructor if clockwise counts down.

Library Manager nameEncoder
AuthorPaul Stoffregen
Include#include <Encoder.h>
Boardsevery board Mokxi compiles for
In the simulatorSimulated: it runs against the part the way it does on the bench.
Parts it drivesRotary encoder, KY-040

Install it

It builds on every board Mokxi compiles for.

In Mokxi it is built in: #include <Encoder.h> and the sketch compiles, with no download, no zip and no Library Manager.

On a real board, install "Encoder" by Paul Stoffregen from the Arduino IDE鈥檚 Library Manager (Sketch, Include Library, Manage Libraries), or add Encoder to lib_deps in PlatformIO. Mokxi follows the calls of release 1.4.4, so a sketch written here builds there too.

ESP32-C3 路 Arduino Uno 路 Arduino Nano 路 Arduino Mega 2560 路 Arduino Leonardo 路 SparkFun Pro Micro 路 Arduino Micro 路 ESP32-C6 路 ATtiny85 路 Raspberry Pi Pico 路 Raspberry Pi Pico W 路 Seeed XIAO SAMD21 路 STM32 路 STM32 Nucleo-F411RE 路 STM32 Blue Pill 路 micro:bit V2 路 Arduino Uno R4 路 ESP32 DevKit 路 ESP32-S3-DevKitC-1 路 ESP8266 NodeMCU 路 Arduino Pro Mini 3.3 V 路 Seeed XIAO ESP32-C3 路 ESP32-C3 SuperMini 路 Seeed XIAO ESP32-C6 路 ESP32-DevKitC V4 路 LOLIN32 Lite 路 Wemos D1 R32 路 Cheap Yellow Display 路 TTGO T-Display 路 Seeed XIAO ESP32-S3 路 Arduino Nano ESP32 路 Arduino Nano RP2040 Connect 路 Seeed XIAO RP2040 路 Waveshare RP2040-Zero 路 Arduino Uno R4 WiFi

The calls you will use

In the order a sketch meets them.

Encoder knob(2, 3)

An encoder with its two outputs (CLK and DT on a KY-040) on pins 2 and 3, the interrupt pins of an Uno.

long pos = knob.read()

The current count since start or the last write(). It can go negative.

long pos = knob.read() / 4;
if (pos != last) {
  last = pos;
  Serial.println(pos);
}

knob.write(0)

Sets the count, for example back to zero when a button is pressed.

knob.readAndReset()

Returns the count and sets it to zero in one step, handy for measuring how far it moved since the last check.

Example: Count a rotary encoder

On the Arduino Uno R3. It runs in the browser exactly as printed.

sketch.ino 路 Arduino Uno R3
#include <Encoder.h>

// Pins 2 and 3 are the Uno's interrupt pins, so no step is missed.
Encoder myEnc(2, 3);
long oldPosition = -999;

void setup() {
  Serial.begin(9600);
  Serial.println("Basic Encoder Test:");
}

void loop() {
  long newPosition = myEnc.read();
  if (newPosition != oldPosition) {
    oldPosition = newPosition;
    Serial.println(newPosition);
  }
}

Wiring

  • Arduino Uno R3 2 to Rotary encoder, KY-040 CLK
  • Arduino Uno R3 3 to Rotary encoder, KY-040 DT
  • Arduino Uno R3 5V to Rotary encoder, KY-040 VCC
  • Arduino Uno R3 GND to Rotary encoder, KY-040 GND

Open it in the editor, wired and ready to run

Common errors and how to fix them

The count goes up by four for every click

That is correct: the library counts every edge, and a KY-040 has four per detent. Divide read() by four, rounding the way you prefer, to get clicks.

Fast turns skip counts or count backward

The pins have no interrupts, so edges are missed between read() calls. On an Uno or Nano use pins 2 and 3, and avoid long delays in loop() if only one pin can interrupt.

Turning clockwise makes the number go down

The direction depends on which pin is named first. Swap the two numbers in the constructor, or swap the CLK and DT wires.

Try Encoder without installing anything

Open the example, change the sketch, and keep your version in a free account.