Rotary Encoder Module: Difference between revisions
| Line 47: | Line 47: | ||
|} | |} | ||
[[File:Rotory-encoder-module-arduino.jpg|thumb|center| | [[File:Rotory-encoder-module-arduino.jpg|thumb|center|700px|Arduino motor speed measurement setup using an L293D driver and LM393 encoder]] | ||
== Rotary Encoder == | == Rotary Encoder == | ||
Latest revision as of 16:23, 3 September 2026
Arduino Rotary Encoder Position and Angle Measurement Using M274 / KY-040
Arduino Rotary Encoder Position and Angle Measurement is a rotary encoder interfacing setup using an Arduino UNO and an M274 / KY-040 rotary encoder.
The encoder provides two digital signals, CLK and DT, which are used by the Arduino to determine the direction and position of rotation.
The encoder also includes a push button SW. Pressing the button resets the encoder position to zero.
The program uses a typical encoder resolution of 20 pulses per revolution to calculate the approximate shaft angle.
Rotary Encoder → Arduino UNO → Position + Angle + Direction
Connections
| Device | Pin | Arduino UNO | Function |
|---|---|---|---|
| M274 / KY-040 | + / VCC | 5V | Power |
| M274 / KY-040 | GND | GND | Ground |
| M274 / KY-040 | CLK | D2 | Encoder clock signal |
| M274 / KY-040 | DT | D3 | Encoder direction signal |
| M274 / KY-040 | SW | D4 | Push button / reset |

Rotary Encoder
The M274 / KY-040 rotary encoder provides two output signals:
- CLK – Clock signal
- DT – Direction signal
The Arduino reads the relationship between the CLK and DT signals to determine whether the encoder is rotating clockwise or counter-clockwise.
The encoder also provides a push button through the SW pin.
The program assumes:
20 pulses = 1 revolution
Encoder Resolution
The program defines the encoder resolution as:
PULSES_PER_REV = 20
Therefore, one complete revolution corresponds to approximately 20 encoder pulses.
The angle corresponding to the encoder position is calculated using:
Angle = (Pulses in One Revolution × 360) / 20
Therefore:
1 pulse ≈ 18°
Encoder Direction
The Arduino detects a falling edge of the CLK signal.
At the falling edge, the Arduino checks the state of the DT signal.
If DT is HIGH:
Clockwise → Position increases
If DT is LOW:
Counter-clockwise → Position decreases
The encoder position is stored in:
volatile long encoderPosition = 0;
Clockwise rotation increments the position, while counter-clockwise rotation decrements it.
Push Button Reset
The SW pin is connected to Arduino D4.
The input uses the Arduino's internal pull-up resistor:
pinMode(SW_PIN, INPUT_PULLUP);
When the button is pressed, the SW pin becomes LOW.
The program then resets:
Position = 0
Angle = 0°
A debounce time of 200 ms is used to prevent multiple resets caused by button bouncing.
Working
The Arduino continuously performs the following operations:
- Reads the CLK and DT signals from the rotary encoder.
- Detects changes in the CLK signal using an interrupt.
- Determines the direction of rotation using the DT signal.
- Increments or decrements the encoder position.
- Calculates the angle corresponding to the current position.
- Displays the position, angle and direction on the Serial Monitor.
- Checks the push button on D4.
- Resets the encoder position to zero when the button is pressed.
The overall operation is:
CLK + DT → Direction → Position → Angle
Interrupt Operation
The CLK signal is connected to Arduino D2.
On the Arduino UNO, D2 supports an external interrupt.
The program attaches the interrupt using:
attachInterrupt( digitalPinToInterrupt(CLK_PIN), encoderISR, CHANGE );
The encoder interrupt function reads both CLK and DT signals and determines the direction of rotation.
The interrupt is triggered whenever the CLK signal changes.
Angle Calculation
The program calculates the position within one complete revolution using the modulo operation:
long pulsesInOneRev = position % PULSES_PER_REV;
For negative positions, the program adjusts the value so that the angle remains within the range of 0° to 360°.
The angle is then calculated as:
Angle = (pulsesInOneRev × 360.0) / PULSES_PER_REV
With 20 pulses per revolution:
20 pulses → 360°
10 pulses → 180°
5 pulses → 90°
1 pulse → 18°
Serial Monitor
The Serial Monitor is set to 115200 baud.
At startup, the program displays:
M274 Rotary Encoder Test ------------------------ Rotate the encoder...
During rotation, the program displays the encoder position, angle and direction.
Example:
Position: 1 | Angle: 18.0 deg | Direction: CLOCKWISE Position: 2 | Angle: 36.0 deg | Direction: CLOCKWISE Position: 3 | Angle: 54.0 deg | Direction: CLOCKWISE Position: 2 | Angle: 36.0 deg | Direction: COUNTER-CLOCKWISE
When the push button is pressed:
RESET -> Position = 0, Angle = 0 deg
Arduino Code
/*
M274 / KY-040 Rotary Encoder
Arduino UNO
Connections:
----------------------------
M274 Arduino UNO
----------------------------
+ / VCC -> 5V
GND -> GND
CLK -> D2
DT -> D3
SW -> D4
Typical encoder resolution:
20 cycles/pulses per revolution
Features:
- Detects clockwise rotation
- Detects counter-clockwise rotation
- Counts encoder position
- Calculates approximate angle
- Push button resets position to zero
*/
#define CLK_PIN 2
#define DT_PIN 3
#define SW_PIN 4
// Typical M274/KY-040 specification
const int PULSES_PER_REV = 20;
// Encoder position
volatile long encoderPosition = 0;
// Previous CLK state
volatile bool lastCLKState = HIGH;
// Button debounce
unsigned long lastButtonTime = 0;
const unsigned long debounceTime = 200;
// Encoder interrupt function
void encoderISR()
{
bool currentCLK = digitalRead(CLK_PIN);
bool currentDT = digitalRead(DT_PIN);
// Detect falling edge of CLK
if (lastCLKState == HIGH && currentCLK == LOW)
{
if (currentDT == HIGH)
{
// Clockwise
encoderPosition++;
}
else
{
// Counter-clockwise
encoderPosition--;
}
}
lastCLKState = currentCLK;
}
void setup()
{
Serial.begin(115200);
// Internal pull-up resistors
pinMode(CLK_PIN, INPUT_PULLUP);
pinMode(DT_PIN, INPUT_PULLUP);
pinMode(SW_PIN, INPUT_PULLUP);
// Read initial CLK state
lastCLKState = digitalRead(CLK_PIN);
// Interrupt on CLK
attachInterrupt(
digitalPinToInterrupt(CLK_PIN),
encoderISR,
CHANGE
);
Serial.println("M274 Rotary Encoder Test");
Serial.println("------------------------");
Serial.println("Rotate the encoder...");
}
void loop()
{
// Read encoder position safely
noInterrupts();
long position = encoderPosition;
interrupts();
// Calculate angle
long pulsesInOneRev = position % PULSES_PER_REV;
if (pulsesInOneRev < 0)
{
pulsesInOneRev += PULSES_PER_REV;
}
float angle =
(pulsesInOneRev * 360.0) / PULSES_PER_REV;
// Display data
static long previousPosition = 999999;
if (position != previousPosition)
{
Serial.print("Position: ");
Serial.print(position);
Serial.print(" | Angle: ");
Serial.print(angle, 1);
Serial.print(" deg | Direction: ");
if (position > previousPosition)
{
Serial.println("CLOCKWISE");
}
else
{
Serial.println("COUNTER-CLOCKWISE");
}
previousPosition = position;
}
if (digitalRead(SW_PIN) == LOW)
{
if (millis() - lastButtonTime > debounceTime)
{
noInterrupts();
encoderPosition = 0;
interrupts();
Serial.println("RESET -> Position = 0, Angle = 0 deg");
lastButtonTime = millis();
}
}
}
Observation
The Serial Monitor is set to 115200 baud.
When the encoder is rotated clockwise, the encoder position increases and the Serial Monitor displays: CLOCKWISE
When the encoder is rotated counter-clockwise, the encoder position decreases and the Serial Monitor displays: COUNTER-CLOCKWISE
The angle is calculated based on the encoder position and the specified 20 pulses per revolution.
Pressing the encoder push button resets the position and angle to zero.
Result
The Arduino UNO successfully interfaces with the M274 / KY-040 rotary encoder and detects clockwise and counter-clockwise rotation.
The program counts the encoder position, calculates the approximate angular position based on 20 pulses per revolution, displays the direction and angle on the Serial Monitor, and resets the position to zero when the push button is pressed.