Source: https://mokxi.com/libraries/esp32encoder
Updated: 2026-11-11

Libraries / Input

Arduino library · Input

# ESP32Encoder: counting a quadrature encoder on the ESP32

ESP32Encoder by Kevin Harrington counts quadrature encoders on the ESP32, both the KY-040 knobs used for menus and the encoders on motor shafts used in robots. On a real chip it uses the pulse counter hardware, so counting takes no CPU time and keeps up with fast motors, and the count is a 64-bit number that does not overflow.

Open the example in the editor See the calls

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

## What ESP32Encoder does

You choose how many edges to count. attachFullQuad() counts every edge of both pins, four per cycle, for the most counts per turn of a motor. attachHalfQuad() counts two per cycle, and attachSingleEdge() one. A KY-040 knob has one cycle per click, so half quad gives 2 a click, which the runnable example shows: two clicks read as 4.

Pull resistors are chosen for every encoder at once with the static useInternalWeakPullResistors setting, before attaching. In Mokxi the counting is done from pin interrupts rather than the pulse counter, sharing the four slots of the Encoder library, so it counts the same edges a real ESP32 would. setFilter() is accepted and not needed, since the simulated knob does not bounce unless told to.

Library Manager name | ESP32Encoder

Author | Kevin Harrington

Include | #include <ESP32Encoder.h>

Boards | ESP32-C3, ESP32-C6, Seeed XIAO ESP32-C3, ESP32-C3 SuperMini, Seeed XIAO ESP32-C6, ESP32 DevKit, ESP32-DevKitC V4, LOLIN32 Lite, Wemos D1 R32, Cheap Yellow Display, TTGO T-Display, ESP32-S3-DevKitC-1, Seeed XIAO ESP32-S3, Arduino Nano ESP32

In the simulator | Simulated: it runs against the part the way it does on the bench.

Parts it drives | Rotary encoder, KY-040

## Install it

It builds on ESP32-C3, ESP32-C6, Seeed XIAO ESP32-C3, ESP32-C3 SuperMini, Seeed XIAO ESP32-C6, ESP32 DevKit, ESP32-DevKitC V4, LOLIN32 Lite, Wemos D1 R32, Cheap Yellow Display, TTGO T-Display, ESP32-S3-DevKitC-1, Seeed XIAO ESP32-S3, Arduino Nano ESP32.

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

On a real board, install "ESP32Encoder" by Kevin Harrington from the Arduino IDE’s Library Manager (Sketch, Include Library, Manage Libraries), or add ESP32Encoder to lib_deps in PlatformIO. Mokxi follows the calls of release 5.0.0, so a sketch written here builds there too.

What to know in the simulator: Counted from pin interrupts rather than the chip’s pulse counter, sharing Encoder.h’s four slots.

- ESP32-C3
- ESP32-C6
- Seeed XIAO ESP32-C3
- ESP32-C3 SuperMini
- Seeed XIAO ESP32-C6
- ESP32 DevKit
- ESP32-DevKitC V4
- LOLIN32 Lite
- Wemos D1 R32
- Cheap Yellow Display
- TTGO T-Display
- ESP32-S3-DevKitC-1
- Seeed XIAO ESP32-S3
- Arduino Nano ESP32

## The calls you will use

In the order a sketch meets them.

### ESP32Encoder encoder

One encoder object. Make one per encoder; pins are given when it is attached.

### ESP32Encoder::useInternalWeakPullResistors = puType::up

Turns on the internal pull-ups for the encoder pins. Set it before attaching; puType::none is for modules with their own resistors.

### encoder.attachHalfQuad(4, 5)

Starts counting on two pins, two counts per cycle. Which pin is named first decides which direction counts up.

### encoder.attachFullQuad(4, 5)

Counts four per cycle, every edge of both pins, which gives a motor encoder four times the counts of single edge.

### encoder.getCount()

The count so far as an int64_t. Cast it to int32_t or long before printing on cores whose Serial lacks a 64-bit print.

### encoder.setCount(0)

Sets the count to any value, for zeroing at a home position. clearCount() sets it to 0.

### encoder.pauseCount()

Stops counting until resumeCount(), without losing the value.

## Example: A rotary encoder on an ESP32-C3

On the ESP32-C3-DevKitM-1. It runs in the browser exactly as printed.

sketch.ino · ESP32-C3-DevKitM-1

### Wiring

- ESP32-C3-DevKitM-1 2 to Rotary encoder, KY-040 CLK
- ESP32-C3-DevKitM-1 3 to Rotary encoder, KY-040 DT
- ESP32-C3-DevKitM-1 3V3 to Rotary encoder, KY-040 VCC
- ESP32-C3-DevKitM-1 GND to Rotary encoder, KY-040 GND

Open it in the editor, wired and ready to run

## Common errors and how to fix them

### call of overloaded println(int64_t) is ambiguous

getCount() returns a 64-bit number that Serial.println() on some cores cannot print directly. Cast it first, (int32_t)encoder.getCount(), or wrap it in String().

### The count goes down when the knob is turned clockwise

The pins are named in the opposite order from your wiring. Swap the two pin numbers in attachHalfQuad() or attachFullQuad(); no wiring change is needed.

### One click changes the count by 2 or 4 instead of 1

That is the counting mode: half quad gives 2 per click and full quad 4. Divide getCount() by that number, or use attachSingleEdge() for one count per click.

## Questions and answers

### Does ESP32Encoder work on an Arduino Uno?

No, it is written for the ESP32 family. On an Uno use the Encoder library, which counts from pin interrupts in the same way.

## Keep going

### Learn

- Arduino Rotary Encoder (KY-040): Wiring and Code
- ESP32 Interrupts: attachInterrupt and Debounce

### Parts

- Rotary encoder, KY-040

### More input libraries

- XPT2046_Touchscreen
- Keypad
- OneButton
- Encoder
- RotaryEncoder
- CapacitiveSensor
- IRremote
- Adafruit MCP23017 Arduino Library

Every built-in library · Open the editor

## Try ESP32Encoder without installing anything

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

Start building free

Open the editor
