PCA9685 LED controller and ESP8266 example

In this example we connect a PCA9685 LED controller to an ESP8266

The PCA9685 is an I²C-bus controlled 16-channel LED controller optimized for Red/Green/Blue/Amber (RGBA) color backlighting applications. Each LED output has its own 12-bit resolution (4096 steps) fixed frequency individual PWM controller that operates at a programmable frequency from a typical of 24 Hz to 1526 Hz with a duty cycle that is adjustable from 0 % to 100 % to allow the LED to be set to a specific brightness value. All outputs are set to the same PWM frequency.

Each LED output can be off or on (no PWM control), or set at its individual PWM controller value. The LED output driver is programmed to be either open-drain with a 25 mA current sink capability at 5 V or totem pole with a 25 mA sink, 10 mA source capability at 5 V. The PCA9685 operates with a supply voltage range of 2.3 V to 5.5 V and the inputs and outputs are 5.5 V tolerant. LEDs can be directly connected to the LED output (up to 25 mA, 5.5 V) or controlled with external drivers and a minimum amount of discrete components for larger current or higher voltage LEDs.


  • 16 LED drivers. Each output programmable at:
    • Off
    • On
    • Programmable LED brightness
    • Programmable LED turn-on time to help reduce EMI
  • 1 MHz Fast-mode Plus compatible I2C-bus interface with 30 mA high drive capability on SDA output for driving high capacitive buses
  • 4096-step (12-bit) linear programmable brightness per LED output varying from fully off (default) to maximum brightness
  • LED output frequency (all LEDs) typically varies from 24 Hz to 1526 Hz (Default of 1Eh in PRE_SCALE register results in a 200 Hz refresh rate with oscillator clock of 25 MHz)
  • Sixteen totem pole outputs (sink 25 mA and source 10 mA at 5 V) with software programmable open-drain LED outputs selection (default at totem pole). No input function
  • Output state change programmable on the Acknowledge or the STOP Command to update outputs byte-by-byte or all at the same time (default to ‘Change on STOP’)
  • Active LOW Output Enable (OE) input pin. LEDs outputs programmable to logic 1, logic 0 (default at power-up) or ‘high-impedance’ when OE is HIGH
  • 6 hardware address pins allow 62 PCA9685 devices to be connected to the same I2C-bus
  • Toggling OE allows for hardware LED blinking
  • 4 software programmable I2C-bus addresses (one LED All Call address and three LED Sub Call addresses) allow groups of devices to be addressed at the same time in any combination (for example, one register used for ‘All Call’ so that all the PCA9685s on the I2C-bus can be addressed at the same time and the second register used for three different addresses so that 1⁄3 of all devices on the bus can be addressed at the same time in a group). Software enables and disables for these I2C-bus address
  • Software Reset feature (SWRST General Call) allows the device to be reset through the I2C-bus
  • 25 MHz typical internal oscillator requires no external components
  • External 50 MHz (max.) clock input
  • Internal power-on reset
  • Noise filter on SDA/SCL inputs
  • Edge rate control on outputs
  • No output glitches on power-up
  • Supports hot insertion
  • Low standby current
  • Operating power supply voltage range of 2.3 V to 5.5 V
  • 5.5 V tolerant inputs

Parts List

Here are the parts I used


Name Links
Wemos Mini
Connecting cables



This example only shows one led connected, my test board had all 16 connected – ideally the PCA9685 board should be externally powered

esp8266 and PCA9685
esp8266 and PCA9685



You will need to add the Adafruit PWM Servo driver library – https://github.com/adafruit/Adafruit-PWM-Servo-Driver-Library/archive/master.zip

This is the default code, I commented out a couple of lines so this would compile for the ESP32


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

// called this way, it uses the default address 0x40
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();

void setup() {
  Serial.println("16 channel PWM test!");
  pwm.setPWMFreq(1600);  // This is the maximum PWM frequency
  // save I2C bitrate
  //uint8_t twbrbackup = TWBR;
  // must be changed after calling Wire.begin() (inside pwm.begin())
  //TWBR = 12; // upgrade to 400KHz!

void loop() {
  // Drive each PWM in a 'wave'
  for (uint16_t i=0; i<4096; i += 8) 
    for (uint8_t pwmnum=0; pwmnum < 16; pwmnum++) 
      pwm.setPWM(pwmnum, 0, (i + (4096/16)*pwmnum) % 4096 );






Please enter your comment!
Please enter your name here