OVERVIEW
We have seen in prior tutorials how to connect and control Stepper Motors.
Stepper Motors are great for many projects but can get expensive when your projects needs a bunch of them.
So let’s see how to connect and control Servo Motors, which are a little cheaper.
Servo Motors are great when your project just need to make some mechanical movements that don’t need to be as precise, like those achieved by Stepper Motors.
Normally to control a Servo you need 1 pin on your Arduino, so if you have 5 of them, then you would require 5 pins.
Depending on your project, that means that you could run out of pins for other components.
In this tutorial we will be using the PCA9685 PWM module, which enable us to control up to 16 Servos and only use 2 pins on our Arduino UNO, since it uses the I2C communication protocol.
You can even link multiple PCA9685 modules together to control even more if needed.
PARTS USED
PCA9685 PWM Module
Joystick Module
Servo Motor
These are Amazon affiliate links...
They don't cost you anything and it helps me keep the lights on
if you buy something on Amazon. Thank you!
SERVO MOTORS INTRODUCTION
A Servo Motor can be either a DC, AC or other type of motor and includes a device to know it’s position (ex.: potentiometer, digital encoder…).
Inside most Servo Motors you will find:
A motor, gears, some type of limit stops that will limit the movement of the shaft, a potentiometer of some kind for position feedback and some integrated circuit to move the servo to a specific position.
A Standard Servo has around 180 degrees of motion. These can be modified to make them rotate 360 degrees or you can buy them already made this way.
The modification involves opening the Servo case, removing the limiting device and disconnect the potentiometer from the shaft.
Once done the Servo will rotate in either direction endlessly since it has no way of knowing it’s position anymore and there are no limit switches to stop it.
Most Servo Motors have three wires:
Black: Ground
Red: Voltage
White or Yellow: Control Wire.
To move a Servo you send a pulse to the control wire. This process is referred to Pulse Coded Modulation.
Standard Servos expects to see a pulse every 20ms. Depending on the length of this pulse the Servo will move to a specific angle.
For example a 1.5ms pulse will make the Servo move to the 90 degree position (which normally is the neutral or middle position).
A pulse shorter than 1.5ms will be move the Servo closer to 0 degrees and a longer one will move closer to 180 degrees.
Servos can have a lot of torque for their size and they also draw power in proportion to how hard they are working.
So if you project is not moving much weight than the Servo will not consume much energy.
CONNECTIONS
Using the PCA9685 PWM Servo module makes connections very easy as you can see.
Each of the Servo motors connectors are connected to the PCA9685 bottom connections:
*In this tutorial we are using connector 1-4-8-12.
V+ is the RED wire of the Servo motor
GND is the Black wire
PWM is the White or Yellow wire
Then to power the Servo Motors we connect an External 5V power supply to the screw terminal V+ and GND.
*Note the PCA9685 screw connector is protected in case you wire it backward.
Then we have to make the connection from the UNO
5V and GND from the UNO are connected to VCC and GND of the PCA9685 module.
*Note V+ on the side of the PCA9685 Module is used for powering the Servo Motors if you are not using the Screw Terminal connector. It is better to use the Screw Terminal connector since it is protected in case you invert GND and Voltage by mistake.
A4 (SDA) and A5 (SLC) of the UNO are connected to the corresponding pins of the PCA9685 module.
*Note If your are using VERSION 2 of the code you also need to connect the Joystick Switch to Pin 4 of the UNO.
THE CODE
We are using the HDPC9685 library to communicate with the PCA9685 PWM Module.
You can find a link to download the library at the bottom of this tutorial page.
As you can see from the codes below, using the library makes it very easy to move the Servo Motors to a position relative to the position of our Joystick.
We are reading the X axis of the Joystick to move Servo Motors number 0 and 12 and the Y axis to move the 4 and 8 Servos.
Below you will find 2 different ways (code) to move the servos:
The first one will be proportional to the movement of the joystick: Since the analog value from the Joystick varies from 0 to 1023 and the movements of the Servo Motors are from 0 to around 420, we are using the MAP function to map the values of the Joystick to reflect the Servos limits.
The second one moves the servos until the joystick is released and the servo position can be reset to the middle by clicking the joystick switch.
As always, Don’t forget to watch our Tutorial videos on the left side of this page for more information.
CODE VERSION 1
/* Arduino Multiple Servo Motors Control Using The PCA9685 PWM Module VERSION 1 PROPORTIONAL
Created by Yvan / https://Brainy-Bits.com
This code is in the public domain...
You can: copy it, use it, modify it, share it or just plain ignore it!
Thx!
*/
#include "HCPCA9685.h" // Include the HCPCA9685 library created by Andrew Davies
#define I2CAdd 0x40 // Default address of the PCA9685 Module
#define JoyX A0 // Joystick X pin connected to A0 on the UNO
#define JoyY A1 // Joystick Y pin connected to A1 on the UNO
// Used to store the mapping of the Joystick X and Y values
int ServoXforward;
int ServoXbackward;
int ServoYforward;
int ServoYbackward;
HCPCA9685 HCPCA9685(I2CAdd); // Define Library to use I2C communication
void setup()
{
HCPCA9685.Init(SERVO_MODE); // Set to Servo Mode
HCPCA9685.Sleep(false); // Wake up PCA9685 module
}
void loop()
{
int val1X = analogRead(JoyX); // Read current value of Joystick 1 X axis
int val1Y = analogRead(JoyY); // Read current value of Joystick 1 Y axis
// Map Joystick Axis values to servo Min and Max position
ServoXforward = map(val1X, 0, 1023, 420, 10); // Used to move Servo 0
ServoXbackward = map(val1X, 0, 1023, 10, 420); // Used to move Servo 12 inverted
ServoYforward = map(val1Y, 0, 1023, 10, 420); // Used to move Servo 4
ServoYbackward = map(val1Y, 0, 1023, 420, 10); // Used to move Servo 8 inverted
// Move Servos to read postion from Joystick
HCPCA9685.Servo(0, ServoXforward); // Move Servo 0
HCPCA9685.Servo(12, ServoXbackward); // Move Servo 12
HCPCA9685.Servo(4, ServoYforward); // Move Servo 4
HCPCA9685.Servo(8, ServoYbackward); // Move Servo 8
delay(1);
}
CODE VERSION 2
/* Arduino Multiple Servo Motors Control Using The PCA9685 PWM Module VERSION 2 MOVE/STOP/RESET
Created by Yvan / https://Brainy-Bits.com
This code is in the public domain...
You can: copy it, use it, modify it, share it or just plain ignore it!
Thx!
*/
#include "HCPCA9685.h" // Include the HCPCA9685 library created by Andrew Davies
#define I2CAdd 0x40 // Default address of the PCA9685 Module
#define JoyX A0 // Joystick X pin connected to A0 on the UNO
#define JoyY A1 // Joystick Y pin connected to A1 on the UNO
#define JoySwitch 4 // Joystick switch connected to Pin 4 on UNO
// Variables used to store the Position of each Servos
int Servo0Position;
int Servo4Position;
int Servo8Position;
int Servo12Position;
HCPCA9685 HCPCA9685(I2CAdd); // Define Library to use I2C communication
void setup()
{
HCPCA9685.Init(SERVO_MODE); // Set to Servo Mode
HCPCA9685.Sleep(false); // Wake up PCA9685 module
// Set Center value for the Servos
Servo0Position=250;
Servo4Position=250;
Servo8Position=250;
Servo12Position=250;
// Move all Servos at start to center position
HCPCA9685.Servo(0, Servo0Position); // Move Servo 0
HCPCA9685.Servo(4, Servo4Position); // Move Servo 4
HCPCA9685.Servo(8, Servo8Position); // Move Servo 8
HCPCA9685.Servo(12, Servo12Position); // Move Servo 12
pinMode(JoySwitch, INPUT_PULLUP);
}
void loop()
{
if (!digitalRead(JoySwitch)) { // If Joystick switch is clicked re-center all Servos
delay(500); // delay for debouncing the joystick switch
// Set all Servos position variable back to center values
Servo0Position=250;
Servo4Position=250;
Servo8Position=250;
Servo12Position=250;
// Move all Servos to center position
HCPCA9685.Servo(0, Servo0Position); // Move Servo 0
HCPCA9685.Servo(4, Servo4Position); // Move Servo 4
HCPCA9685.Servo(8, Servo8Position); // Move Servo 8
HCPCA9685.Servo(12, Servo12Position); // Move Servo 12
}
// if Joystick X axis in not in center move Servo 0 and 12 accordingly
if (analogRead(JoyX) > 800) {
if (Servo0Position < 420) { // Check if maximum movement of Servo reached
Servo0Position++; // Increase Servo 0 Position variable by 1
}
if (Servo12Position > 10) { // Check if minimum movement of Servo reached
Servo12Position--; // Decrease Servo 12 Position variable by 1
}
delay(10); // Decrease to make Servos move faster or increase for slower movement
HCPCA9685.Servo(0, Servo0Position); // Move Servo 0
HCPCA9685.Servo(12, Servo12Position); // Move Servo 12
}
if (analogRead(JoyX) < 300) { if (Servo0Position > 10) {
Servo0Position--;
}
if (Servo12Position < 420) { Servo12Position++; }
delay(10);
HCPCA9685.Servo(0, Servo0Position); // Move Servo 0
HCPCA9685.Servo(12, Servo12Position); // Move Servo 12
}
// if Joystick Y axis in not in center move Servo 4 and 8 accordingly
if (analogRead(JoyY) > 800) {
if (Servo4Position < 420) {
Servo4Position++;
}
if (Servo8Position > 10) {
Servo8Position--;
}
delay(10);
HCPCA9685.Servo(4, Servo4Position); // Move Servo 4
HCPCA9685.Servo(8, Servo8Position); // Move Servo 8
}
if (analogRead(JoyY) < 300) { if (Servo4Position > 10) {
Servo4Position--;
}
if (Servo8Position < 420) {
Servo8Position++;
}
delay(10);
HCPCA9685.Servo(4, Servo4Position); // Move Servo 4
HCPCA9685.Servo(8, Servo8Position); // Move Servo 8
}
}
TUTORIAL VIDEO PART 1
TUTORIAL VIDEO PART 2
DOWNLOAD
Copy the above Sketch code in your Arduino IDE software to program your Arduino board.
Used Libraries:
PCA9685 PWM Module Library created by Andrew Davies
Once downloaded, just extract the content of the zip files inside your “arduino/libraries” folder, and make sure to restart the Arduino IDE (Close and Reopen) software so it detect this newly installed library.