PCA9685: A 16-Channel, 12-Bit, I2C-Controlled LED Controller


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 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 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 controller applications involve running servo motors, but you can also use them to control RGB LEDs.  

A servo motor

A servo motor

Source: Wikimedia Commons  

PCA9685 Pinouts

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.  

Power Pins

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.


Control Pins

  • 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.


Output Pins

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


PCA9685 Features

  • 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

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, the potentiometer is spun 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

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

Arduino UNO servo connectors

Source: Wikimedia Commons  

The connection between Arduino and the servo controller should be as follows:  

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 screen output showing 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

Hooking up 62 boards maximum in serial to control more standard servo motors (992 max) is possible. 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 different sets of unused control pins of the primary controller to the corresponding pins in the secondary board using six jumper wires.  

Address the Boards

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. After connecting them, you must give each board in the cascade a unique identifier.

The pads are six and include:

  • A0+RW
  • A1
  • A2
  • A3
  • A4
  • A5+1

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.  


Afterward, you can program each board using its object name to control the servo motor or LED connected anywhere along the cascade.  

Typical Applications



Source: Wikimedia Commons

  • Servos driver



In conclusion, the PCA9685, 12-bit, 16-channel driver is crucial for precise 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.    

Need custom LED services?