Zbotic Logo Zbotic Logo
  • Home
  • Shop
  • Sale
  • 3D Print Service
  • PCB Service
  • B2B
  • Blogs
  • Contact Us
0 0

View Wishlist Add all to cart

0 0
0 Shopping Cart
Shopping cart (0)
Subtotal: ₹0.00

View cartCheckout

  • Shop
  • About Us
  • Contact Us
  • Reseller
  • Blogs
020 69134444
1800 209 0998
[email protected]
Help Desk
Facebook Twitter Instagram Linkedin YouTube
Zbotic Logo Zbotic Logo
0 0

View Wishlist Add all to cart

0 0
0 Shopping Cart
Shopping cart (0)
Subtotal: ₹0.00

View cartCheckout

All departments
  • 3D Print Service
  • 3D Printer
  • Batteries & Chargers
  • Development Boards
  • Drone Parts
  • EBike parts
  • Sensor Modules
  • Electronic Components
  • Electronic Modules
  • IoT and Wireless
  • Mechanical Parts and Workbench Tools
  • Motors & Drivers & Pumps & Actuators
  • DIY and Robot Kits
  • Show more
  • Home
  • Shop
  • Sale
  • 3D Print Service
  • PCB Service
  • B2B
  • Blogs
  • Contact Us
Return to previous page
Home Sensors & Modules

Rotary Encoder Tutorial: KY-040 with Arduino Step-by-Step

Rotary Encoder Tutorial: KY-040 with Arduino Step-by-Step

March 11, 2026 /Posted byJayesh Jain / 0

Table of Contents

  • Introduction
  • What Is a Rotary Encoder?
  • KY-040 Module Specifications
  • How the KY-040 Generates Pulses
  • Wiring KY-040 to Arduino
  • Basic Code: Polling Method
  • Advanced Code: Interrupt-Based (Recommended)
  • Debouncing the Push Button
  • Clockwise vs Counter-Clockwise Detection
  • Project Ideas with KY-040
  • Troubleshooting
  • Frequently Asked Questions
  • Conclusion

Introduction

If you have ever adjusted the volume on a car stereo or navigated a menu on a 3D printer, you have used a rotary encoder. Unlike a potentiometer, a rotary encoder has no beginning or end — it can spin indefinitely and counts every click (detent). The KY-040 rotary encoder module is the most popular encoder module in the Arduino maker community, thanks to its integrated pull-up resistors, built-in push button, and low price.

This tutorial explains everything from how the encoder generates signals to writing robust, interrupt-based Arduino code that correctly detects direction and handles switch debouncing. We also cover five practical project ideas you can build with a KY-040.

What Is a Rotary Encoder?

A rotary encoder is an electromechanical device that converts rotational position or movement into digital pulses. There are two main types:

  • Absolute encoder: Reports the exact angular position at all times (even after power loss). Used in industrial servo drives. Expensive.
  • Incremental encoder: Counts steps relative to a reference point. Reports direction and number of clicks since startup. Loses count on power loss. Much cheaper — this is the KY-040.

Incremental encoders like the KY-040 are perfect for user interface applications: volume knobs, menu selectors, manual jogging of CNC axes, and speed control.

KY-040 Module Specifications

Parameter Value
Supply Voltage 3.3 V – 5 V
Output Pins CLK (A), DT (B), SW (button)
Output Type Digital (TTL)
Pulses per Revolution 20 detents / 20 pulses per 360°
Integrated Pull-ups Yes (10 kΩ on CLK, DT, SW)
Push Button Yes (momentary, NO)
Shaft Diameter 6 mm D-shaft
Dimensions 32 × 19 mm (module)
Price in India ₹30–₹80

The module has 5 pins: CLK (also called A or DT), DT (also called B), SW (push button switch), + (VCC), and GND.

How the KY-040 Generates Pulses

Inside the encoder, a rotating disc with notched contacts slides across two contact pads (A and B) that are physically offset by 90° (quarter phase). As you turn the shaft, A and B alternately connect to GND through the notches, producing a sequence of LOW/HIGH pulses.

The sequence of A (CLK) and B (DT) states determines direction:

  • Clockwise rotation: CLK goes LOW first, then DT goes LOW
  • Counter-clockwise: DT goes LOW first, then CLK goes LOW

In code, we detect a falling edge on CLK (interrupt) and then immediately read the state of DT. If DT is HIGH at that moment, the encoder is turning clockwise; if DT is LOW, it is counter-clockwise.

Quadrature signal table (simplified):

Step CLK DT Direction
1 HIGH HIGH —
2 LOW HIGH CLK fell first → CW
3 LOW LOW —
4 HIGH LOW —
5 HIGH HIGH Back to start

Wiring KY-040 to Arduino

KY-040 Pin Arduino Uno Pin Notes
+ (VCC) 5V Or 3.3V for ESP32
GND GND —
CLK (A) D2 Interrupt pin INT0
DT (B) D3 Or any digital pin
SW (button) D4 Active LOW

The KY-040 module has built-in 10 kΩ pull-up resistors, so you do not need to enable Arduino’s internal pull-ups for CLK and DT. For the SW button, the module also has a pull-up, so you read HIGH when not pressed and LOW when pressed.

Basic Code: Polling Method

The polling method checks CLK state in every loop iteration. Simple but can miss fast rotations if the loop has other time-consuming tasks.

#define CLK_PIN 2
#define DT_PIN  3
#define SW_PIN  4

int counter = 0;
int lastCLK = HIGH;

void setup() {
  pinMode(CLK_PIN, INPUT);
  pinMode(DT_PIN, INPUT);
  pinMode(SW_PIN, INPUT);
  Serial.begin(9600);
  Serial.println("Rotary Encoder Test");
}

void loop() {
  int currentCLK = digitalRead(CLK_PIN);
  // Detect falling edge on CLK
  if (currentCLK == LOW && lastCLK == HIGH) {
    if (digitalRead(DT_PIN) == HIGH) {
      counter++;  // Clockwise
    } else {
      counter--;  // Counter-clockwise
    }
    Serial.print("Counter: "); Serial.println(counter);
  }
  lastCLK = currentCLK;

  // Button press (active LOW)
  if (digitalRead(SW_PIN) == LOW) {
    Serial.println("Button Pressed!");
    counter = 0;  // Reset counter
    delay(300);   // Simple debounce delay
  }
}

Advanced Code: Interrupt-Based (Recommended)

The interrupt method fires immediately on a CLK edge, regardless of what the main loop is doing. This ensures no pulses are missed — even if you have display updates or serial prints in the main loop.

#define CLK_PIN 2
#define DT_PIN  3
#define SW_PIN  4

volatile int counter = 0;
volatile bool buttonPressed = false;
unsigned long lastButtonTime = 0;

void IRAM_ATTR handleEncoder() {
  // CLK has fallen — read DT to determine direction
  if (digitalRead(DT_PIN) == HIGH) {
    counter++;
  } else {
    counter--;
  }
}

void setup() {
  pinMode(CLK_PIN, INPUT);
  pinMode(DT_PIN, INPUT);
  pinMode(SW_PIN, INPUT);
  Serial.begin(9600);
  // Attach interrupt on falling edge of CLK
  attachInterrupt(digitalPinToInterrupt(CLK_PIN), handleEncoder, FALLING);
  Serial.println("Encoder Ready");
}

void loop() {
  // Print counter when changed
  static int lastCounter = 0;
  if (counter != lastCounter) {
    Serial.print("Counter: "); Serial.println(counter);
    lastCounter = counter;
  }

  // Debounced button read
  if (digitalRead(SW_PIN) == LOW) {
    unsigned long now = millis();
    if (now - lastButtonTime > 200) {
      Serial.println("Button Pressed — Counter Reset!");
      counter = 0;
      lastButtonTime = now;
    }
  }
}

Note for ESP32 users: Replace IRAM_ATTR qualifier on the ISR function. On Arduino Uno, IRAM_ATTR is not needed — simply declare as void handleEncoder().

Debouncing the Push Button

Mechanical switches bounce — on press and release, the contacts make and break contact multiple times in the space of a few milliseconds. Without debouncing, a single press can register as 3–10 presses in software.

Two debounce approaches:

  1. Time-based debounce (software): Record the timestamp of the first LOW reading. Ignore further changes until 50–200 ms have passed. This is the approach in the code above (lastButtonTime).
  2. Hardware debounce: Add a 0.1 µF capacitor between SW and GND, and a 10 kΩ resistor in series with SW. The RC filter smooths the bounce. Eliminates the need for software debouncing.

For the encoder’s CLK and DT signals, bouncing is less of an issue because the encoder mechanism is different from a simple switch — the sliding contacts produce cleaner signals. However, if you see double-counting at certain positions, add a small 10 nF capacitor from CLK to GND.

Clockwise vs Counter-Clockwise Detection

If your project is not detecting direction correctly (or reversing CW and CCW), try these fixes:

  • Swap CLK and DT pins — CW/CCW depends on physical orientation of the encoder. Swapping CLK and DT in your wiring (or in your code) reverses the direction logic.
  • Check interrupt edge — This code triggers on FALLING (CLK goes LOW). Some encoders work better with RISING. Try changing FALLING to RISING in the attachInterrupt call.
  • Four-step per detent encoders: Some encoders produce 4 quadrature transitions per detent. If your counter increments by 4 per click, divide by 4 in software, or use a state-machine decoder that only counts on complete quadrature cycles.

Project Ideas with KY-040

1. Digital Volume Control

Pair the KY-040 with a digital potentiometer IC (MCP4131) over SPI. Each encoder step sends an SPI command to the digital pot, incrementing or decrementing a DAC output that controls audio amplifier gain. Display current volume on a 7-segment display.

2. 3D Printer Manual Jog Control

Replace repetitive menu navigation on a 3D printer or CNC machine with a KY-040. Rotate to jog X/Y/Z axis by 0.1 mm per detent. Press the button to switch between axes. Faster rotation speed maps to 1 mm steps (detect RPM from pulse timing).

3. OLED Menu Navigator

Drive an SSD1306 OLED display with a scrollable settings menu. The encoder scrolls through menu options; pressing the button selects. This is a common pattern in any device with configurable parameters — weather stations, data loggers, audio synthesizers.

4. Stepper Motor Position Controller

Each encoder step advances a stepper motor by one step via an A4988 driver. Perfect for manual focusing of a camera lens, positioning a laser cutter’s mirror, or adjusting a spectrometer’s diffraction grating.

5. Frequency-Controlled LED Blinker

A beginner project: rotate the encoder to change the blink frequency of an LED from 0.5 Hz to 20 Hz. Great for understanding how encoder counts translate to real-world parameters using the map() function.

ACS712 Current Sensor

20A Range Current Sensor Module ACS712

Pair a rotary encoder with the ACS712 current sensor for a manual current-setpoint controller in a bench power supply or motor drive project.

View on Zbotic

BMP280 Sensor

BMP280 Barometric Pressure & Altitude Sensor

Build a rotary-controlled weather station dashboard — use the KY-040 to scroll between sensor readings on an OLED while BMP280 measures pressure and altitude.

View on Zbotic

Troubleshooting

Counter jumps by 2 or 4 per click

You are triggering on both RISING and FALLING edges, or the encoder generates multiple quadrature pulses per detent. Confirm you are using only FALLING edge trigger. If still jumping by 4, add a divider: counter = rawCount / 4;

Rotation direction is reversed

Swap the CLK and DT pin definitions in your code (or physically swap the wires). Alternatively, negate the counter increment logic.

Button registers multiple presses on one click

Your debounce delay is too short. Increase from 200 ms to 300 ms. Or add a 100 nF capacitor hardware debounce between SW and GND.

Encoder works but misses steps at high rotation speed

Switch from polling to interrupt-based code. If already using interrupts, check that your ISR is short (no Serial.print inside the ISR — use flags instead).

No signal on CLK or DT

Check that VCC is connected (modules without power have no pull-ups). Verify with a multimeter: CLK and DT should read ~5 V when at rest.

Frequently Asked Questions

Q1: Can I use KY-040 with ESP32 or ESP8266?

Yes. Both work at 3.3 V. Connect VCC to 3.3 V. Use any GPIO pins — on ESP32, all GPIO pins support interrupts (unlike Arduino Uno which only has 2 interrupt pins).

Q2: How many KY-040 encoders can I use on one Arduino?

Arduino Uno has only 2 external interrupt pins (D2, D3). For multiple encoders on Uno, use pin change interrupts (PCINT) via the EnableInterrupt library, which enables interrupts on any digital pin. On Arduino Mega, you have 6 external interrupt pins. On ESP32, you have dozens.

Q3: What is the difference between KY-040 and a bare EC11 encoder?

EC11 is the bare encoder mechanism (the rotating shaft component). KY-040 is a PCB module with an EC11 encoder soldered to it, plus pull-up resistors for CLK, DT, and SW. The KY-040 is easier to use because you plug it directly into a breadboard without needing external resistors.

Q4: Can a rotary encoder replace a potentiometer?

For user interface applications (volume, menu navigation, parameter adjustment), a rotary encoder is usually better — it has no end stops, gives positive click feedback, and the value is defined in software (unlimited range). For analog circuits that need a physical voltage divider, a potentiometer is still the right tool.

Q5: Why does my encoder lose count when I reset the Arduino?

Incremental encoders have no memory — they lose position on power loss. If you need to preserve the position across resets, save the counter value to EEPROM periodically and restore it on startup.

Conclusion

The KY-040 rotary encoder is a small, inexpensive module that adds a powerful user input mechanism to any Arduino project. The key to using it well is understanding the quadrature signal, using interrupts rather than polling, and implementing proper debouncing for the push button. Once you have the interrupt-based code running reliably, you can build everything from simple volume knobs to sophisticated multi-axis CNC control panels.

Available from Zbotic for under ₹80, the KY-040 delivers excellent value for makers and students across India. Pair it with sensors, displays, and actuators from our sensor collection to build interactive, responsive projects.

Shop Sensors & Modules at Zbotic

Tags: Arduino, encoder tutorial, interrupt, KY-040, rotary encoder
Share Post
  • Facebook
  • Linkedin
  • Whatsapp
Best Logic Analyzers for Ardui...
blog best logic analyzers for arduino debugging india 2026 596474
blog 2 4ghz interference wifi bluetooth nrf24l01 coexistence 596477
2.4GHz Interference: WiFi, Blu...

Related posts

Svg%3E
Read more

Encoder Module: Position and Speed Measurement with Arduino

April 1, 2026 0
A rotary encoder converts the angular position and rotation speed of a shaft into electrical signals that Arduino can count... Continue reading
Svg%3E
Read more

Infrared Obstacle Sensor: Line Follower and Object Detection

April 1, 2026 0
Infrared obstacle sensors are the building blocks of line-following robots, edge detection systems, and proximity triggers. These tiny modules emit... Continue reading
Svg%3E
Read more

Rain Sensor and Raindrop Detection Module: Arduino Guide

April 1, 2026 0
A rain sensor module detects the presence of water droplets on its surface, giving Arduino a simple signal to trigger... Continue reading
Svg%3E
Read more

LiDAR Sensor TFmini: Distance Measurement Beyond Ultrasonic

April 1, 2026 0
When ultrasonic sensors hit their limits — range too short, accuracy too coarse, outdoor sunlight causing interference — LiDAR sensors... Continue reading
Svg%3E
Read more

Pressure Sensor BMP280: Weather Station and Altitude Meter

April 1, 2026 0
The BMP280 barometric pressure sensor by Bosch measures atmospheric pressure with ±1 hPa accuracy and temperature with ±1°C precision. These... Continue reading

Add comment Cancel reply

Your email address will not be published. Required fields are marked

Facebook Twitter Instagram Pinterest Linkedin Youtube

Get the latest deals and more.

Download on Google Play Download on the App Store

Call us: 020 69134444 / 1800 209 0998

Monday - Saturday 09:30 AM - 06:00 PM
For Technical Supports Email: [email protected]
For Sales / Enquiries Email: [email protected]

  • My Account

    • Cart

    • Wishlist

    • Checkout

    • My Orders

    • Track Order

    • My Account

  • Information

    • FAQs

    • Blogs

    • Career

    • About Us

    • Contact Us

    • Payment Options

  • Policies

    • Privacy Policy

    • Terms & Conditions

    • GST Input Tax Credit

    • Shipping Return Policy

    • E-Waste Collection Points

    • Our Sitemap

© Zbotic.in is registered trademark of Moxie Supply Pvt Ltd – All Rights Reserved
Login
Use Phone Number
Use Email Address
Not a member yet? Register Now
Reset Password
Use Phone Number
Use Email Address
Register
Already a member? Login Now