Introduction
In this interesting Arduino Project learn to control a servo motor with a rotary encoder using Arduino microcontroller and display the angle rotated on the LCD display. You will learn the process of interfacing a servo motor, rotary encoder with an Arduino to achieve accurate control over a servo motor. We will also explain about servo motors and rotary encoders, and their working principles.
The project of controlling a servo motor using a rotary encoder with Arduino can be used in various practical applications like Robotic Arm Control, Camera Pan-Tilt Mechanism, Surveillance camera systems, Manual Solar Trackers, CNC Machine Control, Industrial Automation, and more. With the help of this project, it is easy to rotate the objects at specified angles with good accuracy.
Table of Contents
What is a Servo Motor
A servo motor is a special type of motor commonly used in robotics and automation projects. It is designed to provide precise control over angular rotation, making it ideal for applications requiring specific movements or positions. Servo motors consist of a DC motor, gears, and a control circuit. The control circuit receives a control signal, usually in the form of a pulse width modulation (PWM) signal, to determine the desired position of the motor shaft.
What is a Rotary Encoder
A rotary encoder is an electromechanical device used to convert angular position or rotation into digital or analog signals. It provides feedback on the rotational movement, enabling accurate measurement and control. Rotary encoders typically consist of a rotating disk, sensors (optical or magnetic), and output circuitry. As the encoder rotates, the sensors detect the changes in position, generating corresponding electrical signals.
For more details refer: What is Rotary Encoder? Types, Principle, working in detail
Working Principle of Servo Motors and Rotary Encoders
Servo motors work on a closed-loop control system. The control signal sent to the servo motor determines the desired position. The internal control circuit compares the current position with the desired position and adjusts the motor’s rotation accordingly. This feedback loop ensures accurate positioning.
Rotary encoders, on the other hand, provide feedback on the rotational movement. The encoder generates electrical signals, such as pulses or digital codes, representing the direction and magnitude of rotation. By monitoring these signals, we can track the position, speed, and direction of the rotary encoder.
Related Project: DIY Measuring Wheel using Arduino and Rotary Encoder
Interfacing Servo motor and rotary encoder with Arduino to display angle on LCD
Required components:
Product Name | Quantity | ||
---|---|---|---|
Arduino Microcontroller | 1 | https://amzn.to/3H4cKxZ | https://amzn.to/3638aTS |
Servo motor sg90 | 1 | https://amzn.to/42TlD9yhttps://amzn.to/3hA5jVi | https://amzn.to/41VeJ2jhttps://amzn.to/368WjUE |
Rotary encoder module | 1 | https://amzn.to/45qSLqF | https://amzn.to/3MNOOoT |
16X2 LCD display with I2C adapter | 1 | https://amzn.to/3WnDDXh | https://amzn.to/3Ou14ME |
5V power supply (USB or External). | 1 | https://amzn.to/3s1a8g3 | https://amzn.to/364yInH |
Few Connecting Wires | https://amzn.to/3H2BV4e | https://amzn.to/3J0WVu2 |
Circuit Diagram:
Now connect all the required components on by one as shown in the below schematic diagram.
As you can see from the above circuit diagram Servo motor RED and BROWN wires which are positive and negative are connected to 5V and GND pins of Arduino respectively. The ORANGE wire which is for control is connected to Arduino digital pin 9.
And next Rotary encoder power pins + and GND are connected to 5V and GND pins of Arduino respectively. And next CLK, DT and SW pins of Encoder are connected to digital pins 2,3 and 4 of Arduino respectively.
And finally we are connecting an LCD display module with I2C adapter which has only 4 pins. LCD display power pins VCC and GND are connected to 5V and GND of Arduino respectively and I2C pins SDA and SCL are connected to A4 and A5 respectively. Thats it for connection, next we need to write a program and upload it to Arduino.
Control Servo with rotary encoder using Arduino source code
After connecting all the required components we need to upload the program. Connect Arduino to PC where Arduino IDE is installed, and copy the below code and paste it in the Arduino IDE workspace, install required libraries listed below, choose correct port and upload the code.
Required Libraries:
- Encoder library – Encoder.h by PaulStoffregen – link
- Servo library – Installed by default
- Liquid Crystal I2c library – link
/* Control Servo motor with Rotary encoder and display angle on LCD display // for Best performace connect this both pins to interupt capable pins of Arduino */ #include <Encoder.h> #include <Servo.h> #include <Wire.h> #include <LiquidCrystal_I2C.h> //define a pin for rotary encode switch const int SW_PIN = 4; const int PIN_A =2; const int PIN_B =3; // for Best performace connect this both pins to interupt capable pins of Arduino Encoder myEnc(PIN_A, PIN_B); //avoid using pins with LEDs attached //Define Servo motors const int homePosition = 90; //initial position const int stepValue = 3;//how fast the servo should rotate when turning the knob const int servoPin = 9;//~must be a pin that that is labeled with ~ Servo myservo; // create servo object to control a servo int servoAngle =homePosition; // Set the LCD address to 0x27 or 0x3F for a 16 chars and 2 line display LiquidCrystal_I2C lcd(0x27, 16, 2); void setup() { Serial.begin(9600); pinMode(SW_PIN, INPUT); Serial.println("Control Servo with Rotary encoder:CircuitSchools"); myservo.attach(servoPin); // attaches the servo on pin myservo.write(servoAngle);//move servo to initial position lcd.init(); // Turn on the blacklight and print a message. lcd.backlight(); lcd.print("Encoder Servo"); lcd.setCursor (0,1); // go to start of 2nd line lcd.print("Servo Test"); delay(2000); lcd.clear();// clear previous values from screen lcd.print("Encoder Servo"); lcd.setCursor (0,1); // go to start of 2nd line lcd.print("Angle: "); } long oldPosition = -999; void loop() { long newPosition = myEnc.read(); if (newPosition != oldPosition) { if(newPosition > oldPosition) { int newStep = abs(newPosition - oldPosition); Serial.print("Angle "); Serial.println(servoAngle); servoAngle -= stepValue; if(servoAngle <0) servoAngle =0; myservo.write(servoAngle); //move servo to new angel lcdAngle(servoAngle);//print on LCD } if(newPosition < oldPosition ) { int newStep = abs(newPosition - oldPosition); Serial.print("Angle "); Serial.println(servoAngle); servoAngle += stepValue; if(servoAngle >180) servoAngle =180; myservo.write(servoAngle); //move servo to new angel lcdAngle(servoAngle);//print on LCD } oldPosition = newPosition;//remember the new position } if( digitalRead(SW_PIN) == LOW) { Serial.print("Home: "); Serial.println(homePosition); servoAngle =homePosition; myservo.write(servoAngle); //move servo to new angel lcdAngle(servoAngle);//print on LCD } //delay(200); } void lcdAngle(int angle) { int startChar =7; for(int i=startChar; i<16; i++) { lcd.setCursor (i,1); lcd.print(" "); } lcd.setCursor (startChar,1); // line 1 lcd.print(angle); lcd.print((char)223); }
Code explaination
- The code includes several libraries:
Encoder
for handling the rotary encoder,Servo
for controlling the servo motor,Wire
for I2C communication, andLiquidCrystal_I2C
for interfacing with the LCD display. - Pin assignments and constants are defined:
SW_PIN
represents the pin connected to the rotary encoder switch.PIN_A
andPIN_B
are the pins connected to the rotary encoder’s A and B channels.homePosition
is the initial position of the servo motor.stepValue
determines how fast the servo rotates when turning the knob.servoPin
is the pin to which the servo motor is connected.
- An instance of the
Encoder
class is created, passing the A and B pins as arguments. - The servo motor is initialized by creating an instance of the
Servo
class and attaching it to the servoPin. The servoAngle variable is set to the homePosition, and the servo is moved to that initial position. - The LCD display is initialized, and a welcome message is printed on it. After a short delay, the screen is cleared, and the “Encoder Servo” and “Angle: ” texts are displayed.
- The loop function is where the main logic resides. It reads the current position of the rotary encoder using the
myEnc.read()
function. - If the position has changed (newPosition != oldPosition), the code checks if the new position is greater or smaller than the old position to determine the direction of rotation.
- If the new position is greater, the servoAngle is decreased by stepValue. The code ensures that the angle does not go below 0 and then moves the servo to the new angle. The lcdAngle function is called to update the angle on the LCD display.
- If the new position is smaller, the servoAngle is increased by stepValue. The code ensures that the angle does not exceed 180 and then moves the servo to the new angle. The lcdAngle function is called to update the angle on the LCD display.
- The oldPosition is updated to store the current position for comparison in the next iteration.
- If the rotary encoder switch is pressed (SW_PIN is LOW), the servo is moved back to the homePosition, and the lcdAngle function is called to update the LCD display.
- The loop function then repeats, continuously monitoring the rotary encoder and reacting to changes.
- The lcdAngle function updates the angle value on the LCD display by clearing the previous characters and printing the new angle.