Skip to content

adafruit_pca9685

Works with

Any board with I2C. The PCA9685 chip is found on the Motor Shield V2, Servo FeatherWing, and standalone breakout boards.

What it does

adafruit_pca9685 is the low-level driver for the PCA9685 16-channel 12-bit PWM controller chip. It lets you set the frequency and duty cycle of up to 16 PWM channels independently over a single I2C connection. Most users will interact with this chip through higher-level libraries like adafruit_servokit or adafruit_motorkit — but you need direct access when driving LEDs, ESCs (electronic speed controllers), custom actuators, or anything that requires raw PWM values rather than servo angles or motor throttle abstractions.

Multiple PCA9685 boards can be stacked on the same I2C bus by configuring address jumpers (0x40 through 0x7F), giving up to 992 PWM channels from a single microcontroller.

Installing the library

Copy all of the following to CIRCUITPY/lib/:

  • adafruit_pca9685.mpy
  • adafruit_bus_device/ (folder)

Quick start

import board
import busio
from adafruit_pca9685 import PCA9685

i2c = busio.I2C(board.SCL, board.SDA)
pca = PCA9685(i2c)          # default address 0x40
pca.frequency = 50          # 50 Hz for servos; up to 1600 Hz for LEDs

# Set channel 0 to 50% duty cycle
# duty_cycle is 16-bit: 0 = off, 0xFFFF = fully on
pca.channels[0].duty_cycle = 0x7FFF  # ~50%

# Set a servo pulse manually (50 Hz = 20 ms period)
# 1.5 ms pulse = 90 degrees center position
# 1.5 ms / 20 ms * 65535 ≈ 4915
pca.channels[1].duty_cycle = 4915

# Turn a channel fully on or off
pca.channels[2].duty_cycle = 0xFFFF  # fully on
pca.channels[3].duty_cycle = 0       # off

# Second board on the same I2C bus
pca2 = PCA9685(i2c, address=0x41)
pca2.frequency = 1000  # 1 kHz for LEDs

Key things you can do

What you want How to do it
Set PWM frequency pca.frequency = 50 (1–1600 Hz)
Set channel duty cycle pca.channels[n].duty_cycle = value (0–65535)
Turn a channel fully on pca.channels[n].duty_cycle = 0xFFFF
Turn a channel off pca.channels[n].duty_cycle = 0
Use a non-default I2C address PCA9685(i2c, address=0x41)
Stack multiple boards Create separate PCA9685 instances with different addresses
Reset all channels pca.reset()
Drive LEDs at high frequency Set frequency = 1000 or higher to eliminate visible flicker
Control an ESC Set frequency = 50, then set pulse widths matching your ESC's calibration range

Reading the official docs

Full API reference: https://docs.circuitpython.org/projects/pca9685/en/latest/

Projects using this library