(via ChatGPT)
Below is a step-by-step guide for wiring a KY-040 rotary encoder to an ESP32-C3-based board on a breadboard, along with a simple example sketch (Arduino-style) showing how to read both rotation and the built-in push button.
A typical KY-040 rotary encoder module has five pins:
- GND – Ground
- + or VCC – Supply voltage (often labeled 5 V on the module, but it will also work fine at 3.3 V for an ESP32-C3)
- SW – Push-button switch output
- DT – Data signal (sometimes labeled
B
) - CLK – Clock signal (sometimes labeled
A
)
When you rotate the shaft, the module toggles CLK
and DT
out of phase. By detecting which signal changes first, you can figure out rotation direction (clockwise or counterclockwise). The push-button switch is usually triggered by pressing the knob down.
Below is one example wiring that works well on the ESP32-C3. You can choose other GPIOs if you prefer, but avoid pins dedicated to flash, USB, or boot configuration (i.e. strapping pins) unless you are sure you can free them up.
KY-040 Pin | Connect to on ESP32-C3 | Notes |
---|---|---|
GND | GND | Common ground |
+ | 3.3 V | Supply with 3.3 V (do not use 5 V) |
CLK | GPIO9 | Rotary output channel A (interrupt/input) |
DT | GPIO8 | Rotary output channel B (interrupt/input) |
SW | GPIO7 | Push-button switch (digital input) |
Important:
- On many KY-040 modules, the pin labeled
+
is sometimes used at 5 V with Arduino boards. However, the ESP32-C3 is a 3.3 V device, so you should power it at 3.3 V to avoid logic-level mismatches. - The rotary encoder outputs are open-contact signals. Typically, you enable internal pull-ups on the ESP32-C3 so you don’t need extra resistors (the hardware has small pull-ups built in).
- The built-in push button (
SW
) is often pulled up inside the ESP32-C3. When pressed, it goes LOW (to GND).
A typical breadboard arrangement:
+-----------+
| KY-040 |
| |
| SW DT CLK + GND
+-----------+
| | | | |
| | | | |
GPIO7---+ | | | |
GPIO8--+ | |
GPIO9--+ |
3.3 V--------------------+
GND-------------------------+
Below is an Arduino-style sketch that uses internal pull-ups and interrupts to detect both turning and button presses. You can paste this into your PlatformIO or Arduino IDE project (making sure your board is set to an ESP32-C3 variant).
// Example code for reading KY-040 Rotary Encoder on an ESP32-C3.
// Author: (Your Name)
#define PIN_CLK 9 // GPIO9 for the rotary encoder CLK
#define PIN_DT 8 // GPIO8 for the rotary encoder DT
#define PIN_SW 7 // GPIO7 for the rotary encoder push button
volatile int16_t encoderValue = 0;
volatile bool buttonPressed = false;
// Keep track of the last state of CLK to determine direction
volatile int lastCLKState = HIGH;
void IRAM_ATTR handleEncoderCLK()
{
// Read both pins quickly in the ISR
int currentCLK = digitalRead(PIN_CLK);
int currentDT = digitalRead(PIN_DT);
// If the CLK signal has changed from high to low
if (currentCLK == LOW && lastCLKState == HIGH) {
// Check DT to figure out direction
if (currentDT == HIGH) {
// Rotating clockwise
encoderValue++;
} else {
// Rotating counterclockwise
encoderValue--;
}
}
// Save the last state so we can detect the falling edge next time
lastCLKState = currentCLK;
}
void IRAM_ATTR handleButton()
{
// If the SW pin is active-low, it goes LOW when pressed:
if (digitalRead(PIN_SW) == LOW) {
buttonPressed = true;
}
}
void setup() {
// Configure USB Serial on ESP32-C3
// For PlatformIO, ensure build flags in platformio.ini:
// -DARDUINO_USB_MODE=1
// -DARDUINO_USB_CDC_ON_BOOT=1
Serial.begin(115200);
delay(1000);
// Pins for the encoder signals
pinMode(PIN_CLK, INPUT_PULLUP);
pinMode(PIN_DT, INPUT_PULLUP);
// Store the initial state of CLK
lastCLKState = digitalRead(PIN_CLK);
// Attach interrupt on the CLK signal’s falling edge
attachInterrupt(digitalPinToInterrupt(PIN_CLK), handleEncoderCLK, FALLING);
// Pin for the push button
pinMode(PIN_SW, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(PIN_SW), handleButton, FALLING);
Serial.println("KY-040 Rotary Encoder with ESP32-C3 - Starting up.");
}
void loop() {
// Just show changes once per second, or whenever the value changes significantly
static int16_t lastValue = 0;
int16_t currentValue = encoderValue;
if (currentValue != lastValue) {
Serial.print("Encoder value: ");
Serial.println(currentValue);
lastValue = currentValue;
}
if (buttonPressed) {
Serial.println("Button pressed!");
buttonPressed = false;
}
delay(50);
}
-
Interrupts: We attach an interrupt to the
CLK
pin for the falling edge. In the handler, we read bothCLK
andDT
to figure out the direction of rotation. -
Pull-ups: The code sets the pins as
INPUT_PULLUP
, relying on the internal pull-up resistors so external resistors aren’t strictly needed (though many KY-040 modules also have onboard pull-ups). -
Bounce: Mechanical rotary encoders and push buttons often need debounce handling. Depending on quality and speed requirements, you may see occasional spurious direction changes. If your application is sensitive, you can do software debouncing or short delays in the interrupt routine. For many use cases, the above approach works well enough.
-
USB Serial on ESP32-C3:
- If you’re using Arduino or PlatformIO with an ESP32-C3 DevKit, you may need these build flags to enable serial over USB:
build_flags = -DARDUINO_USB_MODE=1 -DARDUINO_USB_CDC_ON_BOOT=1
- This will let you see
Serial.println()
outputs via the USB port directly.
- If you’re using Arduino or PlatformIO with an ESP32-C3 DevKit, you may need these build flags to enable serial over USB:
- Open the Serial Monitor at 115200 baud.
- Rotate the encoder slowly clockwise. You should see the “Encoder value” increment.
- Rotate the encoder counterclockwise. The value should decrement.
- Push the built-in button (press the rotary knob down). You should see “Button pressed!”
- If you see random increments or bouncing, consider adding a small capacitor or software debounce logic.
Once wired as shown and loaded with the example sketch, you will have basic rotation and push-button reads from the KY-040. You can adapt this code to your own application (changing how frequently it prints, adding filtering, or using the value to navigate menus, adjust volume, etc.).
Enjoy experimenting with your ESP32-C3 and the KY-040 rotary encoder! If you run into any quirks with pin selection or debugging, remember you can enable debug logs over USB by ensuring the USB CDC build flags are set, or switch to UART logs on dedicated TX/RX pins.