Lesson 97-1: Detecting Rotary Encoder Rotation and Pushing the Switch
This guide demonstrates how to build a precise and durable control interface for your Arduino projects using a rotary encoder. Unlike a potentiometer, which has a fixed range of motion, a rotary encoder can spin continuously in either direction, making it an excellent choice for applications requiring incremental adjustments or infinite rotation. This project focuses on the fundamental task of detecting the encoder's rotation direction and position, as well as registering when its integrated push-button switch is pressed. This forms the core logic for many advanced projects, such as creating a menu navigation system, adjusting a digital volume control, or precisely tuning a frequency. The rotary encoder's mechanical contacts are also significantly more durable than a potentiometer's carbon track, ensuring a longer lifespan for your projects.
Here are a few practical ideas for what you can build with this foundational setup:
- Menu Navigation System: Rotate the encoder to scroll through options on an LCD and press the switch to select an item.
- Precision Adjustment Tool: Use it to fine-tune a parameter, like setting a timer or adjusting a motor's speed in small, defined increments.
- Robotic Arm Controller: Replace a joystick with an encoder for precise, step-by-step control of a servo motor's position.
Hardware Required
To follow along with this lesson, you will need the following components:
- Arduino Uno (or a similar compatible board)
- Rotary Encoder Module (with PCB) or a bare rotary encoder with three 10kΩ resistors
- Breadboard and jumper wires
- USB cable for programming the Arduino
Wiring Guide
The rotary encoder simplifies the process of tracking rotation. It has two output pins (often labeled A and B) that generate a specific sequence of signals as the knob is turned. By reading these signals, the Arduino can determine the direction and amount of rotation. The encoder also includes a built-in push-button switch, which is activated by pressing down on the knob, providing an additional input for user interaction.
The wiring for this project is straightforward. The provided diagram shows how to connect the encoder module to the Arduino. The CLK (or A) pin is connected to digital pin 2, the DT (or B) pin is connected to digital pin 3, and the SW (Switch) pin is connected to digital pin 4. The encoder's + (VCC) pin is connected to the 3.3V supply, and its GND pin is connected to the common ground.
If you are using a bare rotary encoder without a PCB, you will need to add three pull-up resistors (between 1kΩ and 100kΩ) to its output pins to ensure a clean signal for the Arduino.
Code Explanation
This project's code is designed to be simple and educational. It focuses on the user-configurable parts at the top of the sketch, allowing you to easily adapt it for different pins or projects.
The first section defines the pins to which the encoder is connected. These are the primary values you will need to change if your hardware is wired differently.
const int SW_PIN = 4;
const int PIN_A =2;
const int PIN_B =3;
SW_PIN: This constant defines the Arduino pin connected to the encoder's push-button switch.PIN_AandPIN_B: These constants define the Arduino pins connected to the encoder's two output channels, A and B. These pins are used by theEncoderlibrary to track the knob's rotation.
Next, the code includes the necessary library and creates an instance of the encoder object, associating it with the pins we just defined.
#include <Encoder.h>
Encoder myEnc(PIN_A, PIN_B);
In the setup() function, the serial monitor is initialized for communication, and the switch pin is configured as an input.
void setup() {
Serial.begin(9600);
pinMode(SW_PIN, INPUT);
Serial.println("Basic Encoder Test:");
}
The main logic in the loop() function performs two key tasks. First, it continuously reads the current position of the encoder. If this position has changed from the last recorded value, it means the knob has been turned, and the new position is printed to the serial monitor. Second, it checks the state of the switch. When the switch is pressed, its pin is pulled low, and the code prints a message to indicate the press.
long oldPosition = -999;
void loop() {
long newPosition = myEnc.read();
if (newPosition != oldPosition) {
oldPosition = newPosition;
Serial.println(newPosition);
}
if( digitalRead(SW_PIN) == LOW)
{
Serial.println("Switch Pressed");
}
delay(200);
}
The myEnc.read() function is a custom function from the Encoder library. It returns the current count of the encoder's position. By comparing the current and previous readings, you can detect movement. The digitalRead(SW_PIN) function is a standard Arduino function that reads the state of the switch pin.
Live Project Demonstration
Once you have uploaded the code to your Arduino, you can open the Serial Monitor (set to 9600 baud) to see the results. When you rotate the encoder knob clockwise, you will see the numbers increment. Rotating it counter-clockwise will cause the numbers to decrement. If you press down on the knob, the message "Switch Pressed" will be displayed. This confirms that both the rotation and the button press are being correctly detected by the system.
Related projects from this video
- Lesson 97-2: Controlling a Servo Motor Using a Rotary Encoder
- Lesson 97-3: Controlling a Servo Motor Using a Rotary Encoder and Display Angle on LCD
Chapters
- [00:01] Introduction to controlling a servo with a rotary encoder
- [01:41] Why use a rotary encoder instead of a potentiometer
- [04:18] Overview of the rotary encoder module and wiring
- [13:28] Installing the required libraries
- [14:54] Explaining the basic encoder example code
- [16:43] Demonstrating the basic encoder code
- [17:52] Modified code with the push-button switch
- [20:20] Full code explanation for servo and LCD control
- [23:47] Finding the LCD I2C address
- [30:01] Demonstration of the complete project
/*
* Lesson 97-1: Rotary Encoder with switch
* This code detects rotation of the encoder knob
* and also detects when it is pushed
* Download and resource page https://robojax.com/RJT453
* Watch full details video: https://youtu.be/6xVLbNlmK-g
This video is part of the Arduino Step by Step Course, which starts here: https://youtu.be/-6qSrDUA5a8
If you found this tutorial helpful, please support me so I can continue creating
content like this. Make a donation using PayPal by credit card: https://bit.ly/donate-robojax
* This code is "AS IS" without warranty or liability. Free to be used as long as you keep this note intact. *
* This code has been downloaded from Robojax.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
* Updated by Ahmad Shamshiri on Jan 23, 2022
* Encoder Library - Basic Example
* http://www.pjrc.com/teensy/td_libs_Encoder.html
*
* This example code is in the public domain.
*/
const int SW_PIN = 4;
const int PIN_A =2;
const int PIN_B =3;
#include <Encoder.h>
// Change these two numbers to the pins connected to your encoder.
// Best Performance: both pins have interrupt capability
// Good Performance: only the first pin has interrupt capability
// Low Performance: neither pin has interrupt capability
Encoder myEnc(PIN_A, PIN_B);
// avoid using pins with LEDs attached
void setup() {
Serial.begin(9600);
pinMode(SW_PIN, INPUT);
Serial.println("Basic Encoder Test:");
}
long oldPosition = -999;
void loop() {
long newPosition = myEnc.read();
if (newPosition != oldPosition) {
oldPosition = newPosition;
Serial.println(newPosition);
}
if( digitalRead(SW_PIN) == LOW)
{
Serial.println("Switch Pressed");
}
delay(200);
//Watch video details: https://youtu.be/6xVLbNlmK-g
}
Things you might need
-
Amazon
-
Amazon
-
Amazon
-
eBay
-
eBay
-
AliExpressPurchase an LCD1602 from AliExpresss.click.aliexpress.com
Resources & references
-
ExternalPAC9685 Library (from GitHub)github.com
-
ExternalPurchase an LCD1602 from AliExpresss.click.aliexpress.com
-
External
-
External
-
ExternalPurchase ZK-5DA from Amazon UKamzn.to
-
ExternalSG90 Servo on Amazon USAamzn.to
-
ExternalSG90 Servosamzn.to
Files📁
No files available.