One of the critical components for an automated-manufacturing system, robotics, or CNC machinery project is a servo motor due to its precise control. This device requires a sophisticated circuit board controller to run the operations and give it its desirable high-precision property.
The dedicated module for controlling the motors is usually the PCA9685 16-channel PWM driver module. We will look at the controller in detail and how to program it using Arduino to control its outputs.
What is PCA9685?
The PCA9685 is a 12-bit, 16-channel, I2C bus controller that delivers its output independently at 4096 steps (12-bit resolution), but all with the same frequency. This frequency is programmable from 24Hz to 1526Hz, and the duty cycle is adjustable from 0-100%.
Adafruit 16-Channel 12-bit PWM/Servo Driver - I2C
Each driver can control 16 servos using only two pins, minimizing the occupant I/Os. Used as the master chip, the controller can connect to 61 driver boards max in a cascading design (62 total), allowing the control of 992 servos simultaneously.
Most of the controller's applications involve running servo motors, but you can also use it to control RGB LEDs.
A servo motor
Source: Wikimedia Commons
The PCA9685 16-channel PWM driver module has two sets of identical control input pins on either side of the board, which form the power and control inputs.
There are three power pins:
- GND: The signal and power ground pin
- VCC: The logic power pin (module power supply). Its power supply voltage range should be 3-5V and match the microcontroller's logic level.
- V+: This pin is an optional power pin for supplying the servos. It should be 5-6V DC but can go up to 12V DC. Leave it disconnected if not using servos but never use it with the chip.
- SCL: The I2C clock pin uses a 3V or 5V power supply voltage range and connects to the microcontroller's I2C clock line.
- SDA: Like the SCL, the I2C data pin runs on 3V or 5V logic and connects to the microcontroller's I2C data line.
- OE (Output Enable): The pin disables all outputs if enabled (high). It remains low by default to keep all output pins enabled.
The last set of pins forms the output ports, which are 16 to accommodate 16 servos simultaneously. They are in groups of three containing the following ports:
- PWM: PWM outputs run independently but at the same frequency
- GND: Ground
- V+: Power supply for the output
- 5V compliant (controllable using a 3.3V microcontroller)
- 1MHz fast mode with a compatible I2C bus
- I2C-controlled PWM driver with a built-in clock
- Supports two pins for controlling the 16 free-running PWM outputs
- Three-pin connectors in four groups (can accommodate 16 servos simultaneously)
- Low standby current
- 12-bit resolution for all outputs (4096 steps)
- Noise filter on SCL/SDA inputs
- Dimensions: 62 x 26 mm
PCA9685 Working Principle
Using the PCA 9685 chip, the board can control the 16-channel output values. It allows you to program the controller to adjust the output PWM frequency and duty cycle for effective and precise control over the servos.
PCA9685PW chip pinouts
Using LED control as an example, you can program the turn-on time for all output drivers independently using the LEDn_ON and LEDn_OFF registers. For instance, if you set the on-time to 500 and the off-time to 1300, the PWM channel duty cycle will be:
((1300-500)/4096) x 100 = 19.53%
The signal captured by the receiving channel goes to the demodulation circuit, generating a DC offset voltage. This voltage gets compared to the voltage across the potentiometer, and the drop between them forms the servo input. The input then turns the LEDs on and off.
For motors, it will turn them clockwise and counterclockwise. Once the rotating speed gets to a specific optimal value, it makes the potentiometer spin by the cascaded reducer gear.
The PWM signal (channel duty cycle) controls the servos determining their rotational direction. This motor keeps on spinning until the voltage drop lowers to zero.
How to Program a Servo Using Arduino
You need the following components:
- Arduino UNO R3
- A PCA9685 16-channel 12-bit PWM servo driver
- A servo
- Two 18650 batteries
- A 18650 battery holder
A 18650 battery holder
- Male to female breadboard jumper wires
Servos use a lot of power, so it is advisable to supply the module with an independent power supply. In this case, you should connect the VCC and GND of the independent power source (battery) to the servo driver's V+ and GND, respectively.
Arduino UNO servo connectors
Source: Wikimedia Commons
The connection between Arduino and the servo controller should be as follows:
Install the Library
Connect the Arduino microcontroller to your computer, then launch the IDE. Go to the library manager (Sketch > Include Library > Manage Libraries) and search for the Arduino Library file labeled Adafruit-PWM-Servo-Driver-Library. Click the install button to install it.
The next step is to run the code, and we will program Arduino to spin the servo motor from 0°-180°.
Save and upload the code to Arduino, and you should see the motor spinning from 0°-180° and back continuously. Try modifying the angle value to adjust the rotating positions. If linking multiple servos, go to the "Servo.ino" file (File > Examples > Adafruit PWM Servo Driver Library).
Alternatively, you can run the following code.
This code powers channel 1-4, so you can expect any motor connected to these pins to spin 180° clockwise and back. Also, it will give some output on the screen to show when each motor is rotating.
If you use more or less than four servo channels, adjust the number on the last line of the code accordingly.
Connect Multiple Control Boards in Serial
It is possible to hook up 62 boards maximum in serial to control more standard servo motors (992 max). The previous setup had the battery pack, Arduino UNO R3, 16-channel PWM servo driver, and servo connected into one circuit.
Remember that the PCA9685 has two sets of control input pins, one on either side of the board. If you have extra boards, connect the extra set of unused control pins of the primary controller to the corresponding pins in the secondary board using six jumper wires.
Address the Boards
After connecting them, you must give each board in the cascade a unique identifier. Each controller features address soldering pads on the upper-right edge, and the base I2C address for each is 0X40. The binary address programmed using the soldering pads adds to the base I2C address. A solder bridge between corresponding address jumpers can program the offset for every binary one in the address.
The pads are six and include:
A0 to A5+1 are slave addresses, while A0 to A5 are hardware selectable. If you want to connect four boards to the primary one, follow these steps to give them unique identifiers.
- Board 0: No jumpers required. Offset binary (00000), Address = 0x40
- Board 1: Bridge A0 and RW. Offset binary (00001), Address = 0x41
- Board 2: Bridge A1. Offset binary (00010), Address = 0x42
- Board 3: Bridge A0 and A1. Offset binary (00011), Address = 0x43
- Board 4: Bridge A2. Offset binary (00100), Address = 0x44
State the Objects
After configuring the hardware to assign the addresses, the next step is to create an independent object for each controller in the Arduino code for initialization.
Next, set the maximum output frequency for each board using the objects.
After that, you can program each board using its object name to control the servo motor or LED connected anywhere along the cascade.
- RGBA or RGB LED driver
An RGB LED
Source: Wikimedia Commons
- Servos driver
In conclusion, the PCA9685, 12-bit, 16-channel driver is a crucial device required for precision control over servos. As you can see above, it is not a difficult task to integrate the device with Arduino for programming, even when cascaded. Reach out to us if you have any difficulties setting up the controller for your project, and we'll get back to you in no time.