DeterministicESPAsyncWebServer v6.27.1
Zero-allocation, bounded-execution async HTTP server for ESP32
Loading...
Searching...
No Matches
pca9685.h File Reference

NXP PCA9685 16-channel 12-bit PWM / servo driver codec (DETWS_ENABLE_PCA9685). More...

#include <stddef.h>
#include <stdint.h>

Go to the source code of this file.

Macros

#define PCA9685_CHANNELS   16
 PWM output channels.
 
#define PCA9685_COUNT_MAX   4095
 a PWM count is 12-bit (0..4095)
 
#define PCA9685_FULL_ON   0x1000
 pass as on for a channel fully on (bit 12 flag)
 
#define PCA9685_FULL_OFF   0x1000
 pass as off for a channel fully off (bit 12 flag)
 
#define PCA9685_REG_MODE1   0x00
 
#define PCA9685_REG_MODE2   0x01
 
#define PCA9685_REG_LED0_ON_L   0x06
 channel 0 base; channel n is this + 4*n
 
#define PCA9685_REG_PRESCALE   0xFE
 

Functions

uint8_t pca9685_prescale (uint32_t freq_hz)
 Compute the PRESCALE register value for a PWM output frequency (25 MHz oscillator): round(25e6 / (4096 * freq)) - 1, clamped to the chip's valid 3..255 range.
 
uint8_t pca9685_channel_reg (uint8_t channel)
 The register base (LED_ON_L) for channel (0..15); 0 for an out-of-range channel.
 
uint16_t pca9685_us_to_count (uint32_t microseconds, uint32_t freq_hz)
 Convert a servo pulse width (microseconds) at freq_hz to a 12-bit OFF count (rounded), clamped to 0..4095. ON is taken as 0, so the pulse starts at the period's edge.
 
size_t pca9685_set_pwm_bytes (uint8_t *buf, size_t cap, uint8_t channel, uint16_t on, uint16_t off)
 Emit the 5-byte channel PWM write: [LED_ON_L(channel), ON_L, ON_H, OFF_L, OFF_H] (each count 12-bit little-endian; bit 12 / PCA9685_FULL_ON is the full-on/off flag).
 
bool pca9685_begin (uint8_t addr, uint32_t freq_hz)
 Reset the PCA9685 at addr and set the PWM frequency freq_hz.
 
bool pca9685_set_pwm (uint8_t channel, uint16_t on, uint16_t off)
 Set channel's raw 12-bit ON / OFF counts.
 
bool pca9685_set_servo_us (uint8_t channel, uint32_t microseconds)
 Drive a servo on channel to a microseconds pulse (uses the configured frequency).
 

Detailed Description

NXP PCA9685 16-channel 12-bit PWM / servo driver codec (DETWS_ENABLE_PCA9685).

The PCA9685 generates sixteen independent 12-bit PWM outputs from a 25 MHz oscillator. The output frequency is set by a PRESCALE register value; each channel is four registers (a 12-bit ON count and a 12-bit OFF count) at 0x06 + 4 * channel. Driving a hobby servo is a matter of turning a pulse width (in microseconds) into an OFF count at the configured frequency.

This codec is pure and host-tested: pca9685_prescale computes the prescale for a frequency, pca9685_us_to_count converts a servo pulse width to a 12-bit count, pca9685_channel_reg gives a channel's register base, and pca9685_set_pwm_bytes emits the 5-byte channel write. On an ESP32 the binding replays those writes over I2C (Wire); only that touches hardware.

A cheap solder-and-bench-test breakout for driving up to 16 servos or LEDs: wire it up, sweep a servo.

Author
Douglas Quigg (dstroy0)
Date
2026

Definition in file pca9685.h.

Macro Definition Documentation

◆ PCA9685_CHANNELS

#define PCA9685_CHANNELS   16

PWM output channels.

Definition at line 31 of file pca9685.h.

◆ PCA9685_COUNT_MAX

#define PCA9685_COUNT_MAX   4095

a PWM count is 12-bit (0..4095)

Definition at line 32 of file pca9685.h.

◆ PCA9685_FULL_ON

#define PCA9685_FULL_ON   0x1000

pass as on for a channel fully on (bit 12 flag)

Definition at line 33 of file pca9685.h.

◆ PCA9685_FULL_OFF

#define PCA9685_FULL_OFF   0x1000

pass as off for a channel fully off (bit 12 flag)

Definition at line 34 of file pca9685.h.

◆ PCA9685_REG_MODE1

#define PCA9685_REG_MODE1   0x00

Definition at line 37 of file pca9685.h.

◆ PCA9685_REG_MODE2

#define PCA9685_REG_MODE2   0x01

Definition at line 38 of file pca9685.h.

◆ PCA9685_REG_LED0_ON_L

#define PCA9685_REG_LED0_ON_L   0x06

channel 0 base; channel n is this + 4*n

Definition at line 39 of file pca9685.h.

◆ PCA9685_REG_PRESCALE

#define PCA9685_REG_PRESCALE   0xFE

Definition at line 40 of file pca9685.h.

Function Documentation

◆ pca9685_prescale()

uint8_t pca9685_prescale ( uint32_t  freq_hz)

Compute the PRESCALE register value for a PWM output frequency (25 MHz oscillator): round(25e6 / (4096 * freq)) - 1, clamped to the chip's valid 3..255 range.

◆ pca9685_channel_reg()

uint8_t pca9685_channel_reg ( uint8_t  channel)

The register base (LED_ON_L) for channel (0..15); 0 for an out-of-range channel.

◆ pca9685_us_to_count()

uint16_t pca9685_us_to_count ( uint32_t  microseconds,
uint32_t  freq_hz 
)

Convert a servo pulse width (microseconds) at freq_hz to a 12-bit OFF count (rounded), clamped to 0..4095. ON is taken as 0, so the pulse starts at the period's edge.

◆ pca9685_set_pwm_bytes()

size_t pca9685_set_pwm_bytes ( uint8_t *  buf,
size_t  cap,
uint8_t  channel,
uint16_t  on,
uint16_t  off 
)

Emit the 5-byte channel PWM write: [LED_ON_L(channel), ON_L, ON_H, OFF_L, OFF_H] (each count 12-bit little-endian; bit 12 / PCA9685_FULL_ON is the full-on/off flag).

Returns
5, or 0 if cap < 5 or channel is out of range.

◆ pca9685_begin()

bool pca9685_begin ( uint8_t  addr,
uint32_t  freq_hz 
)

Reset the PCA9685 at addr and set the PWM frequency freq_hz.

Returns
true on ack.

◆ pca9685_set_pwm()

bool pca9685_set_pwm ( uint8_t  channel,
uint16_t  on,
uint16_t  off 
)

Set channel's raw 12-bit ON / OFF counts.

Returns
false on I2C error / bad channel.

◆ pca9685_set_servo_us()

bool pca9685_set_servo_us ( uint8_t  channel,
uint32_t  microseconds 
)

Drive a servo on channel to a microseconds pulse (uses the configured frequency).