One I missed: led driver repurposed for 16 servos
HomeHome > Blog > One I missed: led driver repurposed for 16 servos

One I missed: led driver repurposed for 16 servos

Sep 02, 2023

I was looking at the electronics behind the little Petoi dog robot (right), and noticed a chip I was not aware of before, NXP’s PCA9685.

On a deeper delve, I noticed Adafruit also uses it for creating the classic 1.0 – 2.0ms pulses that tell hobby servos where to position.

It has an I2C input, and can create up to 16 pwm channels – what a handy device.

NXP created it to control red, green, blue and amber leds in four-colour backlights for displays.

NXP’s PCA9685, showing one of its 16 PWM putput channels

Each PWM is 12bit, so 4,096 steps (0% and 100% are also possible), and all channels share a programmable base frequency between 24Hz and 1.5kHz (the internal oscillator is ~25MHz, and up to 50MHz can be applied externally).

As an aside, outputs can be set to open-drain (5.5Vmax) or totem-pole. Capability is 10mA source and 25mA sink.

Supply is needed between 2.3 and 5.5V, and the inputs are 5.5V-tolerant.

I have no idea which clever soul first decided that this would make a signal source for servos (maybe Adafruit?) – but what a nice idea – 16 servos controlled through a single I2C bus – which can work at 1MHz.

Each output gets two 12bit registers, nominally named on-time and off-time, but they actually interact with a fixed 4,096 counted time frame in a more complex way than their names suggest to give control of relative phase between all of the channels as well as on and off time – start at chapter 7.3.3 in the PCA9685 data sheet to have your mind boggled for a while.

Separate bits set each channel fully off or fully on, and there is a way to set all channels on or off together with a global command. Each output also has its own output invert bit.

Output frequency is set by an 8bit pre-scaler and produces a frequency of 25MHz/4096/prescaler, although, for reasons I would love to know, it cannot be set below divide-by-four, so settings of ÷1, ÷2 or ÷3 are automatically replaced with ÷4. ÷5 and up are all possible. It defaults to producing ~200Hz.

Luckily for the rest of us, AdaFruit has created an Arduino library to control the chip as a multi-channel servo driver – we have Limor Fried to thank for so many good Arduino libraries – and it has something similar for CircuitPython and Python too.

BTW, the if you are interested in the Peroi Bittle robot dog, find it here. It essentially has Arduino electronics – a custom Arduino-esk board with suitable peripherals.

rightNXP’s PCA9685, showing one of its 16 PWM putput channelsSteve Bush