This guide will get you up and running with the PCA9685 driver in just a few steps.
Prerequisites
Minimal Example
Here's a complete working example:
#include "pca9685.hpp"
class MyI2c : public pca9685::I2cInterface<MyI2c> {
public:
bool EnsureInitialized() noexcept { return true; }
bool Write(uint8_t addr, uint8_t reg, const uint8_t *data, size_t len) noexcept {
return true;
}
bool Read(uint8_t addr, uint8_t reg, uint8_t *data, size_t len) noexcept {
return true;
}
};
MyI2c i2c;
pca9685::PCA9685<MyI2c> pwm(&i2c, 0x40);
if (!pwm.Reset()) {
return;
}
pwm.SetPwmFreq(50.0f);
pwm.SetDuty(0, 0.5f);
Step-by-Step Explanation
Step 1: Include the Header
Step 2: Implement the I2C Interface
You need to implement the I2cInterface for your platform. See Platform Integration for detailed examples for ESP32, STM32, and Arduino.
The interface requires two methods:
Write(uint8_t addr, uint8_t reg, const uint8_t *data, size_t len) - Write data to a register
Read(uint8_t addr, uint8_t reg, uint8_t *data, size_t len) - Read data from a register
Step 3: Create Driver Instance
MyI2c i2c;
pca9685::PCA9685<MyI2c> pwm(&i2c, 0x40);
The constructor takes:
- Pointer to your I2C interface implementation
- I2C address (0x40 is the default, can be changed via A0-A5 pins)
Step 4: Initialize
if (!pwm.Reset()) {
uint16_t flags = pwm.GetErrorFlags();
auto error = pwm.GetLastError();
}
Reset() puts the device in a known state and must be called before other operations.
Step 5: Set PWM Frequency
Important: You must set the frequency before setting channel outputs. Valid range is 24-1526 Hz.
Step 6: Control Channels
pwm.SetDuty(0, 0.5f);
pwm.SetPwm(1, 0, 2048);
Expected Output
When running this example with a servo on channel 0:
- The servo should move to its center position (1.5ms pulse at 50 Hz)
- No error messages should appear
Troubleshooting
If you encounter issues:
- Compilation errors: Check that you've implemented all required I2C interface methods
- Initialization fails: Verify hardware connections and I2C address
- No output: Ensure
SetPwmFreq() was called before setting channels
- See: Troubleshooting for common issues
Next Steps