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

PCA9685 16-Channel 12-bit PWM/Servo Driver
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

Aliexpress logo

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

The PCA9685 is a powerful 16-channel PWM driver, ideal for controlling servos, LEDs, and other PWM-based devices. It communicates via IΒ²C, making it easy to integrate with ESP32, Arduino, and Raspberry Pi.

⚑ Key Features #

  • 16 Independent PWM Channels – Control multiple servos or LEDs simultaneously.
  • High-Resolution PWM – 12-bit resolution (4096 steps) for precise control.
  • Adjustable PWM Frequency – Ranges from 24 Hz to 1526 Hz.
  • Wide Voltage Compatibility – Logic voltage: 2.3V – 5.5V; separate V+ pin for 5V–6V external power.
  • Expandable IΒ²C Addressing – Connect up to 62 PCA9685 modules on the same IΒ²C bus.

Thanks to its scalability and precision, the PCA9685 is perfect for robotics, automation, and advanced lighting systems requiring synchronized motion or lighting effects. πŸš€

βš™οΈ 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.

  • Type: servo
  • 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.

πŸ› οΈ PCA9685 16-Channel 12-bit PWM/Servo Driver Troubleshooting

This guide outlines a systematic approach to troubleshoot and resolve common problems with the . Start by confirming that the hardware connections are correct, as wiring mistakes are the most frequent cause of issues. If you are sure the connections are correct, follow the below steps to debug common issues.

πŸ›‘ Servos Not Responding or Moving Erratically

Issue: Servos connected to the PCA9685 do not move as expected or exhibit erratic behavior.

Possible causes include insufficient power supply, incorrect wiring, or improper PWM signal configuration.

Solution: Ensure that the servos receive adequate power, as they can draw significant current, especially during startup. Use a separate, stable power supply for the servos, and connect the grounds of the PCA9685, microcontroller, and power supply together to establish a common reference. Verify that the PWM frequency is set appropriately for servo operation, typically around 50 Hz.

πŸ” PCA9685 Not Detected on I2C Bus

Issue: The PCA9685 module is not recognized on the I2C bus, leading to communication failures.

Possible causes include incorrect I2C address configuration, faulty wiring, or issues with the microcontroller's I2C interface.

Solution: Use an I2C scanner sketch to detect the PCA9685's address, which defaults to 0x40 but can be changed by adjusting the address pins. Ensure that the SDA and SCL lines are correctly connected and that pull-up resistors are present if required by your setup. Confirm that no other devices on the I2C bus share the same address, as this can cause conflicts.

πŸ’‘ LEDs Connected to PCA9685 Not Responding

Issue: LEDs connected to the PCA9685 do not light up or respond to PWM signals.

Possible causes include incorrect wiring, improper LED configuration (common anode vs. common cathode), or incorrect PWM settings.

Solution: Verify that LEDs are connected with the correct polarity and that the PCA9685's output mode matches the LED configuration. For common anode LEDs, ensure that the outputs are sinking current, and for common cathode LEDs, that they are sourcing current. Adjust the PWM duty cycle settings in your code to control the LED brightness appropriately.

🌑️ PCA9685 Module Overheating

Issue: The PCA9685 module becomes excessively hot during operation.

Possible causes include excessive current draw from connected devices, inadequate power supply, or short circuits.

Solution: Ensure that the total current draw of all connected devices does not exceed the PCA9685's specifications. Use appropriate current-limiting resistors for LEDs and verify that servos or motors are within the current limits. Check for any wiring mistakes that could cause short circuits, and provide adequate ventilation to dissipate heat.

πŸ’» Code Examples

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

If you encounter issues while using the PCA9685 16-Channel 12-bit PWM/Servo Driver, check the Common Issues Troubleshooting Guide.

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 Arduino sketch interfaces with the PCA9685 PWM Servo Driver over I2C using the Adafruit PWM Servo Driver library.

Required Library #

To use this code, ensure you have installed the Adafruit PWM Servo Driver library. You can install it via the Arduino Library Manager:

  1. Open Arduino IDE.
  2. Navigate to Sketch β†’ Include Library β†’ Manage Libraries.
  3. Search for 'Adafruit PWM Servo Driver' and install it.

Alternatively, you can download it from the official Adafruit GitHub repository:
πŸ”— Adafruit PWM Servo Driver Library

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