Skip to main content

Raw PWM control

What this example shows​

Setting a channel's raw on/off tick counts and ramping them over time. This is the board's basic building block: every higher-level call, including the servo angle helper on the next page, ends up calling setPWM().

The example code​

from pca9685 import PCA9685
from utime import sleep_ms

pwm = PCA9685()
pwm.setPWMFreq(1000) # fast PWM for LEDs/general outputs, not servos

while True:
for duty in range(0, 4096, 32):
pwm.setPWM(0, 0, duty)
sleep_ms(20)

Expected result:

No serial output. Channel 0's duty cycle ramps from 0 to 4064 in steps of 32, taking a little over 2.5 seconds per ramp, then repeats.

Functions used​

PCA9685(i2c=None, address=PCA9685_DEFAULT_ADDRESS)returns None

Constructor. If i2c is not supplied, it auto-detects the I2C pins (SCL 22, SDA 21) on ESP32, ESP8266 and Soldered Dasduino CONNECTPLUS boards, and raises an exception on any other board. Pass your own initialized machine.I2C object to use a different pin pair or board.

ReturnsConstructor; no return value.

Parameters

TypeNameDescription
I2Ci2cInitialized machine.I2C object. Optional; auto-detected on known boards.
intaddressI2C address of the board. Defaults to PCA9685_DEFAULT_ADDRESS (0x40).
setPWMFreq(freq)returns bool

Sets the PWM frequency shared by all 16 channels. Clamped to the chip's 24-1526 Hz range.

ReturnsTrue on success.

Parameters

TypeNameDescription
floatfreqDesired frequency in Hz, clamped to 24-1526 Hz.
setPWM(channel, on, off)returns bool

Sets the raw tick counts at which a channel's output turns on and off within one PWM period (4096 ticks). Used directly for LEDs and general PWM; setServoAngle() on the next page is a convenience wrapper around this same call.

ReturnsTrue on success, False if channel is out of range.

Parameters

TypeNameDescription
intchannelChannel number, 0 to 15.
intonTick count (0-4095) at which the output turns on.
intoffTick count (0-4095) at which the output turns off.

Putting it together​

The constructor sets a 50 Hz default, but this example immediately raises it to 1000 Hz with setPWMFreq(), which suits an LED or general PWM load better than the 50 Hz hobby servos expect. setPWM() then places both edges of the pulse: with on fixed at 0, off alone controls the duty cycle, so ramping off from 0 to 4064 ramps the output from fully off to nearly fully on.

To hold a channel steady instead of ramping it, call setPWM() once with the tick values you want and stop calling it again; the PCA9685 keeps generating that signal on its own until you change it.