/*
* Title: Basic Example of Encoder Library
* Description: A basic example using the rotary encoder library
* Date: Current Date
*
* A rotary encoder is a rotational input device that can detect rotation direction and amount.
* This example uses the Encoder library for Arduino to read the values from a rotary encoder
* and output them to the serial monitor.
*
* Important: The Encoder library internally handles debouncing for rotation signals only.
* Debouncing for the encoder's switch (button) must be implemented separately.
*
* Note: Most rotary encoders generate 4 steps per detent (quadrature signals).
* In this example, we divide by 4 so the value changes by 1 per detent for more intuitive usage.
*
* Required Library: Encoder (by Paul Stoffregen)
* Library Installation: Sketch > Include Library > Manage Libraries... > Search for "Encoder" > Install
* Library GitHub: https://github.com/PaulStoffregen/Encoder
*
english Ver wokwi https://wokwi.com/projects/425622139517030401
*/
#include <Encoder.h>
// Rotary Encoder Pin Definitions
const int ENCODER_PIN_A = 2; // Rotary Encoder A pin (use pin with interrupt support)
const int ENCODER_PIN_B = 3; // Rotary Encoder B pin (use pin with interrupt support)
const int ENCODER_SW_PIN = 4; // Rotary Encoder switch pin (optional)
// Create Encoder Object
// Debouncing for rotation is handled internally by the library
Encoder myEncoder(ENCODER_PIN_A, ENCODER_PIN_B);
// Variables
long oldPosition = -999; // Previous encoder position (raw library value)
int oldNormalizedPos = -999; // Previous normalized value (divided by 4)
// Switch (button) debouncing variables - not handled by the library
int switchState = HIGH; // Current switch state
int lastSwitchState = HIGH; // Previous switch state
unsigned long lastDebounceTime = 0; // Timestamp for debouncing
unsigned long debounceDelay = 50; // Debounce time in milliseconds
void setup()
{
// Initialize serial communication
Serial.begin(9600);
Serial.println("Rotary Encoder Basic Example");
Serial.println("Value changes by 1 per detent (normalized)");
// Set switch pin mode (using internal pull-up resistor)
pinMode(ENCODER_SW_PIN, INPUT_PULLUP);
}
void loop()
{
// Split functionality into two separate functions for better readability
handleEncoder();
handleSwitch();
}
/**
* Function to handle rotary encoder rotation
* Detects rotation and outputs normalized values
*/
void handleEncoder()
{
// Read encoder rotation (debouncing is handled by the library)
long newPosition = myEncoder.read();
// Normalize raw encoder value by dividing by 4 to get 1 change per detent
int normalizedPos = newPosition / 4;
// Output new value if position has changed
if (normalizedPos != oldNormalizedPos)
{
Serial.print("Encoder position: ");
Serial.print(normalizedPos);
Serial.print(" (raw value: ");
Serial.print(newPosition);
Serial.println(")");
oldPosition = newPosition;
oldNormalizedPos = normalizedPos;
}
}
/**
* Function to handle rotary encoder switch (button)
* Implements debouncing and resets encoder value when pressed
*/
void handleSwitch()
{
// Read encoder switch state and apply debouncing
int reading = digitalRead(ENCODER_SW_PIN);
// Reset debounce timer when button state changes
if (reading != lastSwitchState)
{
lastDebounceTime = millis();
}
// Check if button state has stabilized after debounce delay
if ((millis() - lastDebounceTime) > debounceDelay)
{
// Check if button state has actually changed
if (reading != switchState)
{
switchState = reading;
// LOW means button is pressed (due to pull-up resistor configuration)
if (switchState == LOW)
{
Serial.println("Encoder button pressed - Counter reset");
myEncoder.write(0); // Reset encoder value to 0
oldPosition = 0;
oldNormalizedPos = 0;
}
}
}
// Save button state for next iteration
lastSwitchState = reading;
}