Arduino Projects

PCA9685 Servo Driver Arduino circuit diagram and Code

PCA9685 Servo Driver Arduino: 

PCA9685 Servo Driver with Arduino- We often need to use Servos in our projects, without a servo driver we can control just a few servos because we have less number of pwm pins in Arduino Uno and Arduino Nano. There are times when we need to control more Servos then in a situation like this we will need more pwm pins. Thanks to the PWM PCA9685 Servo Driver which can control multiple Servos using only two wires, because it uses the I2C bus. In this article we will look at how you can control up to 16 servos with your Arduino board using a PCA9685 Servo Driver module. PCA9685 is a 16-Channel and 12-Bit PWM Servo Driver can help a lot when there are insufficient PWM output pins for the MCU in your project. The only condition is that the main control chip supports I2C communication, which means enabling the communication between the chip and PCA9685 Servo Driver, so as to control multiple servos simultaneously.



Amazon Links:

12v Adaptor:

Arduino Uno

Arduino Nano

PCA9685 Servo Driver

Other Tools and Components:

Top Arduino Sensors:

Super Starter kit for Beginners

Digital Oscilloscopes

Variable Supply

Digital Multimeter

Soldering iron kits

PCB small portable drill machines

*Please Note: These are affiliate links. I may make a commission if you buy the components through these links. I would appreciate your support in this way!

PCA9685 Servo Driver:

PCA9685

The Arduino UNO has only 6 PWM pins that you can use for controlling servos but by adding one of these modules you can control up to 16 servos. You can add multiple PCA9685 modules to control even more servos but for this tutorial we will stick with just one also this module uses I2C communication. So it only takes up two of your Arduino pins A4 and A5. OE – Output enable. Can be used to quickly disable all outputs. When this pin is low all pins are enabled. When the pin is high the outputs are disabled. Pulled low by default so it’s an optional pin! There are two sets of control input pins on either side. Both sides of the pins are identical! Use whichever side you like, you can also easily chain by connecting up two side-by-sides. There are 16 output ports. Each port has 3 pins: V+, GND and the PWM output. Each PWM runs completely independently but they must all have the same PWM frequency. That is, for LEDs you probably want 1.0 KHz but servos need 60 Hz – so you cannot use half for LEDs @ 1.0 KHz and half @ 60 Hz.

The first thing we need to do is connect our PCA9685 Servo Driver module to our Arduino board.




Interfacing PCA9685 with Arduino:

Let’s get started for this tutorial I will be using an Arduino Nano and I will be using two servos but when we get to the Arduino sketch I will show you how to add more.

PCA9685

  • First connect VCC of the PCA9685 Servo Driver module to the 5V of the Arduino
  • Next connect SDA to A4 if you are using Arduino Mega connect to pin 20 instead
  • Connect the SCL pin to A5 of the arduino if you are using an Arduino mega once again connect this to pin 21 instead
  • Connect the grounds of the PCA9685 Servo Driver to the ground of the Arduino
  • Next we will connect the two servos 1 to position 3 and the other to position 15 of the PCA9685 Servo Driver
  • To power the Arduino I will be using a 9volt battery, so I will connect the positive from the battery to the Vin pin on the Arduino board and the ground of the battery to the ground of the Arduino.
  • If you are using a regulated five volt power supply you can go ahead and connect it to the five volt pin on the Arduino
  • Next we need to power the servos the output from your Arduino board will not drive that many servos. So an external power supply will be necessary it needs to be between five and six volts more than six volts will damage the servos. Please use a voltmeter to check the power supply you are going to use, it may say five or six volts on it but more than likely it will put out more than that and would then damage your servos
  • For this tutorial I am only using two servos and only for a short amount of time therefore I can avoid using the external power source and go ahead and instead connect the VCC from the PCA9685 Servo Driver to the 5volt pin of my Arduino.
  • If you go ahead and try this please remember not to run it for very long or you may overheat and damage the Arduino board. Once you have everything connected it should look something as you can see in the schematic:



Adding the library to the Arduino IDE:

Now let’s move on to the sketch the first thing we will need to do is get the library that we will be using. I tried out the Adafruit library that most people use but found that the HCPA9685 library is much easier to use and just as powerful.

After you download it open up your Arduino IDE click on sketch and under the include library tab select add zip library navigate to where you downloaded the library to and select it.

PCA9685

Now that the library is installed click on file under the examples tab scroll down until you find hcpca9685 and select the servo example:

PCA9685


PCA9685 Servo Driver Arduino Code:

/* Include the HCPCA9685 library */
#include "HCPCA9685.h"

/* I2C slave address for the device/module. For the HCMODU0097 the default I2C address
   is 0x40 */
#define  I2CAdd 0x40


/* Create an instance of the library */
HCPCA9685 HCPCA9685(I2CAdd);


void setup() 
{
  /* Initialise the library and set it to 'servo mode' */ 
  HCPCA9685.Init(SERVO_MODE);

  /* Wake the device up */
  HCPCA9685.Sleep(false);
}


void loop() 
{
  unsigned int Pos;

  /* Sweep the servo back and forth from its minimum to maximum position.
     If your servo is hitting its end stops then you  should adjust the 
     values so that the servo can sweep though its full range without hitting
     the end stops. You can adjust the min & max positions by altering 
     the trim values in the libraries HCPCA9685.h file*/
  for(Pos = 10; Pos < 450; Pos++)
  {
    /* This function sets the servos position. It takes two parameters, 
     * the first is the servo to control, and the second is the servo 
     * position. */
    HCPCA9685.Servo(3, Pos);
    HCPCA9685.Servo(8, Pos);
    delay(10);
  }
  
  for(Pos = 450; Pos >= 10; Pos--)
  {
    HCPCA9685.Servo(3, Pos);
     HCPCA9685.Servo(8, Pos);
    delay(10);
  }
}

Before we go over how the sketch works let’s try it out and make sure everything’s working scroll down the sketch until you find these two lines of code in the void loop:

HCPCA9685.Servo(0, Pos);

HCPCA9685.Servo(0, Pos);

Now change both of the zeros to threes

HCPCA9685.Servo(3, Pos);

HCPCA9685.Servo(3, Pos);

Then go ahead and upload the sketch to your Arduino if everything is connected correctly your servo all connected to position 3 on the PCA9685 should be sweeping back and forth.



PCA9685 Arduino Code Explanation:

Now that we have it working let’s go over call the sketch works and how to add more servos to it to start with we are including the HCPCA9685 library

#include "HCPCA9685.h"

Then we are defining the i2c address of the PCA9685 Servo Driver module the default address of the module is 0x40

#define  I2CAdd 0x40

Next we are creating an instance of the library naming it and setting the address.

HCPCA9685 HCPCA9685(I2CAdd)

Moving on to the void setup we are first initializing library and setting it to servo mode

HCPCA9685.Init(SERVO_MODE)

Then we are waking up the PCA9685 by setting the sleep mode to false

HCPCA9685.Sleep(false)

Moving along to the void loop we start by setting up an integer to store the servos position then we have two for loops to sweep the servos position up and down unlike the servo library that is included with your Arduino IDE this library uses positions for the servo instead of the angle of the servo.

You may need to increase or decrease these numbers a little bit for your particular circle for the 9 gram servo I am using the default 10 minimum and 450 maximum works fine. The first for loop sweeps the servo up from position 10 to position 450 with a 10 millisecond delay between positions.

for(Pos = 10; Pos< 450; Pos++)

  {

    /* This function sets the servos position. It takes two parameters,

     * the first is the servo to control, and the second is the servo

     * position. */

HCPCA9685.Servo(3, Pos);

delay(10);

  }

The second for loop does the opposite sweeping the servo down from position 450 to position 10 with a 10 millisecond delay between each position.

for(Pos = 450; Pos>= 10; Pos--)

  {

HCPCA9685.Servo(3, Pos);

delay(10);

  }

If you would like the servos to sweep faster or slower just change the delay time in both of the loops. Now that we have went over the example sketch.



Adding more servo motors:

Let’s look at how we can add more servos in the void loops in first for loop you will find this line of code

HCPCA9685.Servo(3, Pos);

This is the code that defines which servo you want to write to and what value you want to write to it.This number defines the position on the PCA9685 you want to write now it is set to position 3. Next we declare the value we want to write to the servo POS is writing the value currently stored in the POS integer to the servo.Now we want to add another servo just copy this line of code and paste it right below

HCPCA9685.Servo(3, Pos);

Then simply change the three that was defining position 3 on the PCA9685 to 8 this will now write to the servo on position 15.

HCPCA9685.Servo(15, Pos);

Next do the same thing in the second for loop now instead of just one servo sweeping back and forth both servos will sweep.

Complete code:

/* Include the HCPCA9685 library */

#include "HCPCA9685.h"

/* I2C slave address for the device/module. For the HCMODU0097 the default I2C address

is 0x40 */

#define  I2CAdd 0x40

/* Create an instance of the library */

HCPCA9685 HCPCA9685(I2CAdd);

void setup()

{

  /* Initialise the library and set it to 'servo mode' */

HCPCA9685.Init(SERVO_MODE);

  /* Wake the device up */

HCPCA9685.Sleep(false);

}

void loop()

{

Unsigned int Pos;

  /* Sweep the servo back and forth from its minimum to maximum position. If your servo is hitting its end stops then you should adjust the values so that the servo can sweep though its full range without hitting the end stops. You can adjust the min & max positions by altering the trim values in the libraries HCPCA9685.h file*/

for(Pos = 10; Pos< 450; Pos++)

  {

    /* This function sets the servos position. It takes two parameters,

     * the first is the servo to control, and the second is the servo

     * position. */

HCPCA9685.Servo(3, Pos);

HCPCA9685.Servo(8, Pos);

delay(10);

  }

for(Pos = 450; Pos>= 10; Pos--)

  {

HCPCA9685.Servo(3, Pos);

HCPCA9685.Servo(8, Pos);

delay(10);

  }

}


Applications:

  • RGB or RGBA LED drivers
  • LED status information
  • LED displays
  • LCD backlights
  • Keypad backlights for cellular phones or handheld devices
  • Servo Motors control

Engr Fahad

My name is Shahzada Fahad and I am an Electrical Engineer. I have been doing Job in UAE as a site engineer in an Electrical Construction Company. Currently, I am running my own YouTube channel "Electronic Clinic", and managing this Website. My Hobbies are * Watching Movies * Music * Martial Arts * Photography * Travelling * Make Sketches and so on...

2 Comments

  1. Think you Shahzada Fahad for this nice presentation and explinations of a complex piece of code.

    I have tried the code for my Otto arduino uno replacing the shield with the pca9685 and it works perfectly well.
    That is to say when using one servo or two legs servos.
    When driving feet and legs , 4 servos, it work as well but i need to control the feet in much limited degrees say 45°.
    Glade to hear from you any help

  2. With slide correction of syntax of 2nd code ..found it worked fine, but some Servo motor not moves 180 degree with 450,
    but it is ok ..and concept is understood.
    Can you tell me how two or more servo can be rotated different angle at the same instance of time ..not sequentially,
    thanks in advance.

Leave a Reply

Your email address will not be published. Required fields are marked *

Back to top button