Source: https://mokxi.com/learn/arduino-rotary-encoder
Updated: 2026-10-05

Learn

# Read a KY-040 rotary encoder with an Arduino

Beginner

Written by the Mokxi team, updated October 5, 2026

Start building free Open the editor

Or see every lesson.

- 261 parts on the bench
- 31 boards running now
- 1.00x real time, on every board

Drag around the knob to turn it, and click it to swap methods

The Rotary encoder example on a simulated ATmega328P. Turn the knob; press it to swap the state table for the falling-edge method.

A rotary encoder is a knob that turns forever, with a click at each step. Unlike a potentiometer, it has no start or end. Your sketch counts the clicks and decides what they mean: volume, a menu choice, or a number on a display. The KY-040 module is the one in most kits, and it has a push button under the knob too.

The circuit above is an Arduino Uno with a KY-040 on pins 2, 3 and 4, and a lamp on pin 9. Turn the knob and the count goes up or down, and the lamp gets brighter or dimmer. Press the knob to switch to a second way of reading it, the one most tutorials print, and watch it get the count wrong. It runs in your browser on the sketch below.

## What you need

- An Arduino Uno
- A KY-040 rotary encoder module
- An LED and a 220 ohm resistor
- A half-size breadboard and jumper wires

## Wiring

Part and pin | Goes to | Note

KY-040 CLK | Pin 2 | One half of the quadrature pair

KY-040 DT | Pin 3 | The other half

KY-040 SW | Pin 4 | The push button; read with INPUT_PULLUP

KY-040 + | 5 V | Powers the module’s pull-up resistors

KY-040 GND | GND | Shared ground

LED | Pin 9 | Through a 220 ohm resistor to GND

## Two switches, a quarter of a click apart

Inside the encoder are two switches, CLK and DT. As you turn the knob, they open and close a quarter of a step apart. So the pair of readings walks through four states. Turning clockwise goes 11, 01, 00, 10 and back to 11. Turning the other way walks the same states in reverse. The knob rests at 11 between clicks.

Which way the pair walks tells you which way the knob turned. That is the whole idea. The only hard part is doing it reliably.

## Method 1: the state table

Every time the pair changes, the sketch looks up the move in a table. The table holds all sixteen moves from an old state to a new one. A real quarter step scores +1 or -1. A jump of two states at once scores 0 and is ignored, because that is what a bouncing contact looks like. When the knob gets back to 11 with four quarter steps one way, that is one click.

In the circuit above, three clockwise clicks print "count 1", "count 2", "count 3". One click back prints "count 2". Every time.

The state table method, from the Rotary encoder example

## Method 2: the falling edge, and why it miscounts

Most tutorials use a shorter method: when CLK goes from HIGH to LOW, read DT. If DT is different from CLK, count up; otherwise, count down. On a perfectly clean encoder, that works.

Real encoder contacts bounce. For a split second after they close, they open and close again. Each bounce on CLK is another falling edge, and the short method counts it. Press the knob in the circuit above to switch to this method, then turn it three clicks clockwise. In our run it printed 1, 0, 1, 0, 1, 0 and ended at 0 instead of 3.

Mokxi’s KY-040 bounces on purpose, because that is the lesson. Click the encoder’s properties and turn bounce off, and the short method counts 1, 2, 3 correctly. The state table gets it right either way.

## The push button

SW is a plain button to ground. The module has no pull-up for it, so the sketch uses INPUT_PULLUP. The pin reads LOW when pressed. Here a press switches methods and resets the count. In your own project it might select a menu item.

## Common mistakes

Counting every edge. Use the state table, or a library that does, so a bounce cannot add a count.

A slow loop. The sketch must check the pins often, every millisecond or two. A long delay() in loop() misses steps. Interrupts on pins 2 and 3 are another way to catch every change.

Counting at the wrong spot. Some encoders give two or four state changes per click. Count a click only when the knob is back at rest, as the state table does.

Forgetting INPUT_PULLUP on SW. Without it, the button pin floats and reads random presses.

## Questions

How do I connect a KY-040 to an Arduino Uno?

CLK to pin 2, DT to pin 3, SW to pin 4, + to 5 V and GND to GND. Pins 2 and 3 are also the Uno’s interrupt pins, which is handy if you want to use interrupts later.

Why does my rotary encoder skip or count twice?

The contacts bounce, and a sketch that counts every falling edge on CLK counts the bounces too. Use a state table, as on this page, which ignores a bounce.

Rotary encoder or potentiometer?

A potentiometer gives a position between two ends. An encoder gives steps that never run out. Use an encoder for menus and anything that should keep turning.

What does Mokxi not model on the KY-040?

The feel of the clicks, and speed. Each click arrives at a fixed rate however fast you turn. The bounce is one short extra edge per quarter step, the same every time, where a real contact is less regular.

Related

## Keep going

Arduino Button Debounce: See the Bounce, Then Fix It Debouncing a Button: Why It Fires More Than Once Interrupts vs Polling on Arduino, Side by Side Arduino Potentiometer: analogRead and a Dimmer How the KY-040 is modeled Ring Simon: the same encoder in a game on an ESP32-C3 Advanced The Arduino Uno simulator The project page, with the full sketch Beginner

## Build this for real

Open the editor, change a value and watch the number move with it. Nothing to install, and no account needed.

Start building free Open the editor
