Motors

PCA9685 PWM driver with ESP32

Sixteen servos on two wires is the point of this board, and it is the practical answer on a display board with only an I2C connector left. The PCA9685 generates all the PWM itself. After the setup, the ESP32 sends only new positions, which leaves it free for the display.

Power is the main trap. VCC is the chip's logic supply and goes to 3.3 V. V+ is a separate rail that feeds only the servos, normally 5 to 6 V from a supply that can handle them. Join the grounds and nothing else. Do not power a bank of servos from USB or the ESP32 regulator: when several start together, the voltage drops and the display board resets. Never connect the servo supply to the 3V3 pin. As a first step, add up stall currents, not running currents.

All 16 channels share one frequency, because the chip has a single prescaler. At 50 Hz for servos, you cannot also run LED dimming at another rate on the same chip. The frequency comes from 25,000,000 / (4096 × 50) − 1, which gives a prescale of 121. One step is about 4.9 µs, and pulses of about 150 to 600 counts cover a typical servo, so check yours and start in the middle to avoid forcing it against its end stop. The default address is 0x40, changed with solder jumpers, and that also clashes with an INA219 or INA226 at 0x40, so scan first. OE is pulled low on most boards. Driving it high switches all outputs off.

PCA9685 PWM driver wiring diagram for ESP32
Wiring diagram drawn by LCD Ultra Pro.

Specifications

Channels16
Resolution12-bit
Logic supply (VCC)3.3 V
Servo supply (V+)Separate 5–6 V
I2C address0x40 default, solder jumpers
FrequencyOne for all channels
Servo pulseAbout 150–600 counts at 50 Hz

Power and logic levels

3.3 V: safe to connect directly

SupplyVCC 3.3 V, V+ 5–6 V separate
Signal levelI2C at 3.3 V
On an ESP32V+ must never touch an ESP32 pin.

ESP32 pins, including those on a display board's connectors, work at 3.3 V and are not 5 V tolerant. Modules differ, so if in doubt, measure the signal before you connect it.

Wiring

PCA9685 PWM driverConnect toNote
VIN / VCC3V3
GNDGND
SDAGPIO 8Any free pin, set in Wire.begin()
SCLGPIO 9Any free pin, set in Wire.begin()
V+External 5–6 VNever the 3V3 pin
GNDJoin with servo supply

Arduino code

#include <Wire.h>

const int SDA_PIN = 8, SCL_PIN = 9;
const uint8_t ADDR = 0x40;

void writeReg(uint8_t reg, uint8_t value) {
  Wire.beginTransmission(ADDR);
  Wire.write(reg); Wire.write(value);
  Wire.endTransmission();
}

void setPulse(uint8_t channel, uint16_t off) {
  Wire.beginTransmission(ADDR);
  Wire.write(0x06 + 4 * channel);    // LEDn_ON_L
  Wire.write(0); Wire.write(0);
  Wire.write(off & 0xFF); Wire.write(off >> 8);
  Wire.endTransmission();
}

void setup() {
  Wire.begin(SDA_PIN, SCL_PIN);
  writeReg(0x00, 0x10);              // sleep, needed to set the prescaler
  writeReg(0xFE, 121);               // 50 Hz
  writeReg(0x00, 0x20);              // wake, auto-increment
  delay(1);
  writeReg(0x00, 0xA0);              // restart
}

void loop() {
  setPulse(0, 300); delay(1000);
  setPulse(0, 400); delay(1000);
}

No extra library needed. Compiled for ESP32-S3 with arduino-esp32 3.x. Not yet tested by us on a physical sensor. Change the pins to match your board.

On a display

Read the value in your sketch and pass it to a label, or send it over MQTT and show it with an MQTT value in the editor.

Design a display for PCA9685 PWM driver

Boards with a ready connector

Only boards whose connectors we have surveyed. Others may still work on free GPIOs.

Elecrow CrowPanel ESP32 HMI 2.4"I2C port: SDA 22, SCL 21Not shared with the touch controller (it is on SPI) — free for sensors
Elecrow CrowPanel ESP32 HMI 2.8"I2C port: SDA 22, SCL 21Not shared with the touch controller (it is on SPI) — free for sensors
Elecrow CrowPanel ESP32 HMI 3.5"I2C port: SDA 22, SCL 21Not shared with the touch controller (it is on SPI) — free for sensors
Elecrow CrowPanel ESP32-S3 HMI 5.0"I2C port: SDA 19, SCL 20Same I2C bus as the GT911 touch (0x14 / 0x5D) and, on V3.0 boards, the PCA9557 touch-reset expander (0x18)
Elecrow CrowPanel ESP32-S3 HMI 7.0"I2C port: SDA 19, SCL 20Same I2C bus as the GT911 touch (0x14 / 0x5D) and, on V3.0 boards, the PCA9557 touch-reset expander (0x18)
LilyGO T-Display-S3-Pro 2.33"QWIIC RIGHT: SDA 5, SCL 6I2C only — same bus as the touch, the PMU (SY6970) and the light sensor
M5Stack AtomS3 0.85"Bottom I2C pins: SDA 38, SCL 39Same I2C bus as the built-in IMU (MPU6886, 0x68)
Makerfabs MaTouch ESP32-S3 Rotary IPS 2.1 RoundMabee I2C (J1): SDA 17, SCL 18Same I2C bus as the touch controller (CST826)
Makerfabs MaTouch ESP32-S3 Parallel TFT 4.3"Mabee I2C: SDA 17, SCL 18Same I2C bus as the touch controller (GT911)
Makerfabs MaTouch ESP32-S3 Parallel TFT with Touch 5.0"Mabee I2C: SDA 17, SCL 18Same I2C bus as the touch controller (GT911)
Makerfabs MaTouch ESP32-S3 Parallel TFT with Touch 7.0"Mabee I2C: SDA 17, SCL 18Same I2C bus as the touch controller (GT911)
Sunton ESP32-4827S043R/C 4.3"I2C header (P3): SDA 19, SCL 20Same I2C bus as the GT911 touch controller. P3 also carries GPIO 17 / 18.
Sunton ESP32-8048S043C 4.3"I2C header (P3): SDA 19, SCL 20Same I2C bus as the GT911 touch controller. P3 also carries GPIO 17 / 18.
Sunton ESP32-8048S050C 5.0"I2C header (P3): SDA 19, SCL 20Same I2C bus as the GT911 touch controller. P3 also carries GPIO 17 / 18.
Sunton ESP32-8048S070C 7.0"I2C header (P3): SDA 19, SCL 20Same I2C bus as the GT911 touch controller. P3 also carries GPIO 17 / 18.
Waveshare ESP32-S3 Touch LCD 2.1" roundI2C connector: SDA 15, SCL 7Same I2C bus as the touch controller, the IO expander, the RTC and the IMU (addresses 0x15/0x5D, 0x20, 0x51, 0x6B, 0x7E taken)
Waveshare ESP32-S3 Touch LCD 2.8"I2C connector: SDA 11, SCL 10Same I2C bus as the RTC and the IMU (0x51, 0x6B, 0x7E taken) — the touch has its own bus
Waveshare ESP32-S3 Touch LCD 2.8" Type BI2C connector: SDA 15, SCL 7Same I2C bus as the touch controller, the IO expander, the RTC and the IMU (addresses 0x15/0x5D, 0x20, 0x51, 0x6B, 0x7E taken)
Waveshare ESP32-S3-Touch-LCD-2.8CI2C connector: SDA 15, SCL 7Same I2C bus as the touch controller, the IO expander, the RTC and the IMU (addresses 0x15/0x5D, 0x20, 0x51, 0x6B, 0x7E taken)
Waveshare ESP32-S3-LCD-7BI2C connector (H1): SDA 8, SCL 9Same I2C bus as the touch controller (GT911) and the IO expander (CH422G)

Good to know

  • Use a separate supply for the servos.
  • All channels share one frequency.
  • Check 0x40 for clashes with INA sensors.
  • Find each servo's end stops carefully.

What it is good for

  • Robot arms and hexapods
  • Boards with no free PWM pins
  • Banks of LEDs at one frequency

FAQ

Can I power servos from the ESP32?

No. Use a separate 5–6 V supply on V+ and join the grounds.

Can I run servos and LEDs at different frequencies?

Not on one chip. All channels share a frequency.

Why does the board reset when servos move?

The supply is dropping. Use a stronger, separate one.

Sources

Related parts

Use this information at your own risk. It is for general guidance only: the example code compiles, but it has not been tested on every part, and modules differ between sellers. Check the manufacturer's data before you build. Product names belong to their owners, and LCD Ultra Pro is not affiliated with them. See our Terms.