Skip to main content
ESPBoards

ESP32 PCA9685 16-Channel 12-bit PWM/Servo Driver

The PCA9685 is a 16-channel, 12-bit PWM controller designed for LED and servo motor control applications. It operates over an I²C interface, allowing for easy integration with microcontrollers like the ESP32. Each of its 16 output channels can deliver PWM signals with 12-bit resolution, enabling precise control over connected devices.

Jump to Code Examples

Arduino Core Image
ESP-IDF Image
ESPHome Image
PlatformIO Image
MicroPython Image

Quick Links

PCA9685 16-Channel 12-bit PWM/Servo Driver Datasheet ButtonPCA9685 16-Channel 12-bit PWM/Servo Driver Specs ButtonPCA9685 16-Channel 12-bit PWM/Servo Driver Specs ButtonPCA9685 16-Channel 12-bit PWM/Servo Driver Specs Button

PCA9685 Price

Normally, the PCA9685 16-Channel 12-bit PWM/Servo Driver costs around $7 per Psc.
The prices are subject to change. Check current price:

Amazon com

Amazon de logo

Aliexpress logo

About PCA9685 16-Channel 12-bit PWM/Servo Driver

The PCA9685 is a 16-channel, 12-bit PWM driver widely used for controlling servos, LEDs, and other PWM-controlled devices. It operates via an I²C interface, allowing seamless integration with microcontrollers like the ESP32, Arduino, or Raspberry Pi. The module supports an adjustable PWM frequency range of 24 Hz to 1526 Hz, with a 12-bit resolution providing 4096 steps for fine-grained control of connected devices. Each of its 16 output channels can be individually controlled, enabling simultaneous management of multiple servos or LEDs. The PCA9685 features a voltage range of 2.3V to 5.5V for its logic circuit and has a separate V+ pin to power external devices like servos (typically 5V–6V). It also includes addressable I²C pins, allowing up to 62 PCA9685 modules on the same I²C bus for large-scale projects. Its versatility and ease of use make the PCA9685 ideal for robotics, automation, and complex lighting systems requiring precision and scalability.

PCA9685 Sensor Technical Specifications

Below you can see the PCA9685 16-Channel 12-bit PWM/Servo Driver Technical Specifications. The sensor is compatible with the ESP32, operating within a voltage range suitable for microcontrollers. For precise details about its features, specifications, and usage, refer to the sensor’s datasheet.

  • Protocol: I2C
  • Interface: I2C
  • PWM Channels: 16
  • PWM Resolution: 12-bit (4096 steps)
  • PWM Frequency: 24 Hz to 1526 Hz
  • Voltage (Logic Circuit): 2.3V to 5.5V
  • Voltage (External Power): Up to 6V (typically 5V for servos)
  • Output Current: Sink: 25 mA, Source: 10 mA per channel
  • Addressable Modules: Up to 62 on a single I2C bus
  • External Clock: Supports external clock input for synchronization
  • Operating Temperature: -40°C to 85°C

PCA9685 Sensor Pinout

Below you can see the pinout for the PCA9685 16-Channel 12-bit PWM/Servo Driver. The VCC pin is used to supply power to the sensor, and it typically requires 3.3V or 5V (refer to the datasheet for specific voltage requirements). The GND pin is the ground connection and must be connected to the ground of your ESP32!

The PCA9685 module has the following pins, each with specific functions: VCC: Supplies power to the PCA9685 module. It can be connected to 3.3V or 5V, making it compatible with most microcontrollers, including the ESP32. GND: Ground pin for the module. Connect this to the ground of your microcontroller and power source to ensure proper operation. SDA: Serial Data pin for I2C communication. Connect this to the SDA pin of your microcontroller (e.g., GPIO21 on ESP32). SCL: Serial Clock pin for I2C communication. Connect this to the SCL pin of your microcontroller (e.g., GPIO22 on ESP32). V+: External power pin for the servo motors or LEDs connected to the PCA9685. Typically, a 5V–6V external power supply is connected here for high-current devices. Outputs 0-15: These are the 16 PWM output pins used to control servo motors, LEDs, or other PWM devices. Each pin can generate independent PWM signals. OE: Output Enable pin. This is an optional pin that can be used to disable all PWM outputs when pulled low. It is usually left unconnected in most setups. ADR: Address selection pins (A0–A5). These are used to set the I2C address of the module, allowing multiple PCA9685 modules to be used on the same I2C bus.

PCA9685 Wiring with ESP32

Below you can see the wiring for the PCA9685 16-Channel 12-bit PWM/Servo Driver with the ESP32. Connect the VCC pin of the sensor to the 3.3V pin on the ESP32 or external power supply for power and the GND pin of the sensor to the GND pin of the ESP32. Depending on the communication protocol of the sensor (e.g., I2C, SPI, UART, or analog), connect the appropriate data and clock or signal pins to compatible GPIO pins on the ESP32, as shown below in the wiring diagram.

To wire the PCA9685 module with the ESP32, follow these steps: VCC: Connect the VCC pin of the PCA9685 to the 3.3V pin on the ESP32. This powers the logic circuitry of the PCA9685. GND: Connect the GND pin of the PCA9685 to the GND pin on the ESP32. This establishes a common ground for proper communication. SDA: Connect the SDA pin of the PCA9685 to GPIO21 on the ESP32, which is the default I2C data pin. SCL: Connect the SCL pin of the PCA9685 to GPIO22 on the ESP32, which is the default I2C clock pin. V+: Connect the V+ pin of the PCA9685 to an external 5V–6V power supply to provide power for the connected servos or LEDs. Ensure the power supply can handle the current requirements of all devices. Outputs 0-15: Connect the signal wire of each servo or LED to one of the PWM output pins (0-15) on the PCA9685. GND for Servos: Ensure the ground of the external power supply is connected to the GND of both the PCA9685 and the ESP32 to maintain a common reference. This wiring ensures proper communication and power distribution for the PCA9685 and connected devices.

Code Examples

Below you can find code examples of PCA9685 16-Channel 12-bit PWM/Servo Driver with ESP32 in several frameworks:

Arduino Core Image

ESP32 PCA9685 Arduino IDE Code Example

Example in Arduino IDE

Fill in your main Arduino IDE sketch file with the following code to use the PCA9685 16-Channel 12-bit PWM/Servo Driver:

#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>

// Create a PCA9685 object
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();

// Define the servo parameters
#define SERVOMIN 150 // Minimum pulse length count
#define SERVOMAX 600 // Maximum pulse length count
#define SERVO_FREQ 50 // Analog servos run at ~50 Hz

void setup() {
Serial.begin(115200);
pwm.begin();
pwm.setPWMFreq(SERVO_FREQ); // Set PWM frequency to 50 Hz
}

void loop() {
// Sweep the servo back and forth
for (int pulselen = SERVOMIN; pulselen <= SERVOMAX; pulselen++) {
pwm.setPWM(0, 0, pulselen); // Channel 0 controls the servo
delay(10);
}
for (int pulselen = SERVOMAX; pulselen >= SERVOMIN; pulselen--) {
pwm.setPWM(0, 0, pulselen);
delay(10);
}
}

This code uses the Adafruit_PWMServoDriver library to control a servo motor with the PCA9685 PWM driver module and ESP32. The Adafruit_PWMServoDriver simplifies communication with the PCA9685 over I2C, enabling precise control of servo motors. The PCA9685 generates PWM signals, where SERVOMIN and SERVOMAX define the pulse width range for the servo's movement. The code sweeps the servo motor back and forth on channel 0 by varying the pulse length between these limits.

Connect your ESP32 to your computer via a USB cable, Ensure the correct Board and Port are selected under Tools, Click the "Upload" button in the Arduino IDE to compile and upload the code to your ESP32.

ESP-IDF Image

ESP32 PCA9685 ESP-IDF Code Example
Example in Espressif IoT Framework (ESP-IDF)

If you're using ESP-IDF to work with the PCA9685 16-Channel 12-bit PWM/Servo Driver, here's how you can set it up and read data from the sensor. Fill in this code in the main ESP-IDF file:

#include <stdio.h>
#include "driver/i2c.h"
#include "esp_log.h"

// PCA9685 I2C address and parameters
#define I2C_MASTER_NUM I2C_NUM_0
#define I2C_MASTER_SDA_IO 21
#define I2C_MASTER_SCL_IO 22
#define I2C_MASTER_FREQ_HZ 100000
#define PCA9685_ADDR 0x40
#define PCA9685_MODE1 0x00
#define PCA9685_PRESCALE 0xFE
#define SERVO_MIN 150
#define SERVO_MAX 600
#define CHANNEL_0 0

static const char *TAG = "PCA9685_SERVO";

void i2c_master_init() {
i2c_config_t conf = {
.mode = I2C_MODE_MASTER,
.sda_io_num = I2C_MASTER_SDA_IO,
.sda_pullup_en = GPIO_PULLUP_ENABLE,
.scl_io_num = I2C_MASTER_SCL_IO,
.scl_pullup_en = GPIO_PULLUP_ENABLE,
.master.clk_speed = I2C_MASTER_FREQ_HZ,
};
i2c_param_config(I2C_MASTER_NUM, &conf);
i2c_driver_install(I2C_MASTER_NUM, conf.mode, 0, 0, 0);
}

void pca9685_write_byte(uint8_t reg, uint8_t data) {
uint8_t write_buf[2] = {reg, data};
i2c_master_write_to_device(I2C_MASTER_NUM, PCA9685_ADDR, write_buf, 2, 1000 / portTICK_RATE_MS);
}

void pca9685_set_pwm(uint8_t channel, uint16_t on, uint16_t off) {
uint8_t write_buf[5] = {
0x06 + 4 * channel, // LEDn_ON_L register address
on & 0xFF, // Low byte of ON value
on >> 8, // High byte of ON value
off & 0xFF, // Low byte of OFF value
off >> 8 // High byte of OFF value
};
i2c_master_write_to_device(I2C_MASTER_NUM, PCA9685_ADDR, write_buf, 5, 1000 / portTICK_RATE_MS);
}

void pca9685_init() {
pca9685_write_byte(PCA9685_MODE1, 0x10); // Put PCA9685 into sleep mode
uint8_t prescale = (uint8_t)(25000000 / (4096 * 50) - 1); // Set PWM frequency to 50 Hz
pca9685_write_byte(PCA9685_PRESCALE, prescale);
pca9685_write_byte(PCA9685_MODE1, 0xA0); // Restart and set to normal mode
}

void app_main() {
ESP_LOGI(TAG, "Initializing I2C...");
i2c_master_init();

ESP_LOGI(TAG, "Initializing PCA9685...");
pca9685_init();

while (1) {
// Sweep the servo from minimum to maximum
for (int pulse = SERVO_MIN; pulse <= SERVO_MAX; pulse++) {
pca9685_set_pwm(CHANNEL_0, 0, pulse);
vTaskDelay(10 / portTICK_RATE_MS);
}

// Sweep the servo back from maximum to minimum
for (int pulse = SERVO_MAX; pulse >= SERVO_MIN; pulse--) {
pca9685_set_pwm(CHANNEL_0, 0, pulse);
vTaskDelay(10 / portTICK_RATE_MS);
}
}
}

This ESP-IDF code demonstrates how to control a servo motor using the PCA9685 PWM driver module. The i2c_master_init function initializes the ESP32's I2C interface for communication with the PCA9685. The pca9685_init function sets up the PWM frequency to 50 Hz, ideal for controlling servos. The pca9685_set_pwm function sends PWM signals to a specific channel, determining the servo position based on pulse width. In the app_main function, the servo is swept back and forth by incrementally adjusting the pulse length between SERVO_MIN and SERVO_MAX on channel 0.

Update the I2C pins (I2C_MASTER_SDA_IO and I2C_MASTER_SCL_IO) to match your ESP32 hardware setup, Use idf.py build to compile the project, Use idf.py flash to upload the code to your ESP32.

ESPHome Image

ESP32 PCA9685 ESPHome Code Example

Example in ESPHome (Home Assistant)

Fill in this configuration in your ESPHome YAML configuration file (example.yml) to integrate the PCA9685 16-Channel 12-bit PWM/Servo Driver

pca9685:
- id: pca9685_hub1
frequency: 500

output:
- platform: pca9685
pca9685_id: 'pca9685_hub1'
channel: 0

This configuration sets up a PCA9685 PWM driver in ESPHome. The pca9685 section defines a hub with an ID pca9685_hub1 and a frequency of 500 Hz. The output section specifies a single output channel (channel 0) controlled by the PCA9685 hub. This is useful for controlling devices like servos or LEDs. For more details, visit ESPHome PCA9685 Output Documentation.

Upload this code to your ESP32 using the ESPHome dashboard or the esphome run command.

PlatformIO Image

ESP32 PCA9685 PlatformIO Code Example

Example in PlatformIO Framework

For PlatformIO, make sure to configure the platformio.ini file with the appropriate environment and libraries, and then proceed with the code.

Configure platformio.ini

First, your platformio.ini should look like below. You might need to include some libraries as shown. Make sure to change the board to your ESP32:

[env:esp32dev]
platform = espressif32
board = esp32dev
framework = arduino
lib_deps =
adafruit/Adafruit PWM Servo Driver Library @ ^2.4.0
wire
build_flags =
-D CONFIG_I2C_MASTER_SDA=21
-D CONFIG_I2C_MASTER_SCL=22
monitor_speed = 115200

ESP32 PCA9685 PlatformIO Example Code

Write this code in your PlatformIO project under the src/main.cpp file to use the PCA9685 16-Channel 12-bit PWM/Servo Driver:

#include <Wire.h>
#include "Adafruit_PWMServoDriver.h"

// Create PCA9685 object
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();

// Define servo parameters
#define SERVOMIN 150 // Minimum pulse length count
#define SERVOMAX 600 // Maximum pulse length count
#define SERVO_FREQ 50 // Servo frequency (50 Hz)

void setup() {
Serial.begin(115200); // Initialize serial communication
Serial.println("Initializing PCA9685...");

pwm.begin(); // Initialize PCA9685
pwm.setPWMFreq(SERVO_FREQ); // Set PWM frequency to 50 Hz
}

void loop() {
// Sweep the servo from minimum to maximum
for (int pulselen = SERVOMIN; pulselen <= SERVOMAX; pulselen++) {
pwm.setPWM(0, 0, pulselen); // Channel 0
delay(10);
}

// Sweep the servo back from maximum to minimum
for (int pulselen = SERVOMAX; pulselen >= SERVOMIN; pulselen--) {
pwm.setPWM(0, 0, pulselen); // Channel 0
delay(10);
}
}

This code controls a servo motor using the PCA9685 module with an ESP32. The Adafruit_PWMServoDriver library is used to communicate with the PCA9685 over I2C. The setup function initializes the PCA9685 and sets the PWM frequency to 50 Hz, suitable for most servos. In the loop, the servo motor connected to channel 0 is swept back and forth by varying the pulse length between SERVOMIN (150) and SERVOMAX (600), which define the servo's angular range. The pwm.setPWM function sends these pulse values to the PCA9685 to control the servo position.

Upload the code to your ESP32 using the PlatformIO "Upload" button in your IDE or the pio run --target upload command.

MicroPython Image

ESP32 PCA9685 MicroPython Code Example

Example in Micro Python Framework

Fill in this script in your MicroPython main.py file (main.py) to integrate the PCA9685 16-Channel 12-bit PWM/Servo Driver with your ESP32.

from machine import Pin, I2C
from time import sleep
from pca9685 import PCA9685

# Initialize I2C
i2c = I2C(0, scl=Pin(22), sda=Pin(21), freq=100000)

# Initialize PCA9685
pwm = PCA9685(i2c)
pwm.freq(50) # Set frequency to 50 Hz for servos

# Servo pulse range
SERVOMIN = 150 # Minimum pulse length
SERVOMAX = 600 # Maximum pulse length

def set_servo_angle(channel, angle):
"""Convert angle (0-180) to pulse length and set PWM."""
pulse = SERVOMIN + int((SERVOMAX - SERVOMIN) * angle / 180)
pwm.channels[channel].duty_u16(pulse)

try:
while True:
# Sweep servo from 0 to 180 degrees
for angle in range(0, 181, 1):
set_servo

This MicroPython code demonstrates how to control a servo motor using the PCA9685 module. The PCA9685 library is used to communicate with the module over I2C, where pins 22 (SCL) and 21 (SDA) are configured. The pwm.freq(50) sets the PWM frequency to 50 Hz, which is required for controlling servo motors. The set_servo_angle function calculates the appropriate pulse length for a given angle (0-180 degrees) and sends it to a specified channel. In the loop, the servo sweeps back and forth by incrementing and decrementing the angle, controlling the servo's position. The try block allows stopping the program gracefully using a keyboard interrupt.

Upload this code to your ESP32 using a MicroPython-compatible IDE, such as Thonny, uPyCraft, or tools like ampy.

Conclusion

We went through technical specifications of PCA9685 16-Channel 12-bit PWM/Servo Driver, its pinout, connection with ESP32 and PCA9685 16-Channel 12-bit PWM/Servo Driver code examples with Arduino IDE, ESP-IDF, ESPHome and PlatformIO.