PCA9685 Servo Driver: Control up to 16 Servos with Arduino or ESP32

A PCA9685 servo driver board lets an Arduino or ESP32 run up to 16 servos from just two I2C wires. The board makes the pulses for every servo, so your code stays simple and you keep the rest of your pins free. This guide covers wiring, sizing the servo supply, the 50 Hz pulse maths, the library, chaining boards, and the problems people usually hit.

In this guide
  1. What the board does and what you need
  2. Wiring it to an Arduino Uno
  3. Sizing the servo power supply
  4. Install the library and run a first test
  5. 50 Hz and the pulse-to-tick maths
  6. Using it with an ESP32
  7. More than 16 servos: addresses and chaining
  8. What people run into
  9. Troubleshooting by symptom
  10. Frequently asked questions

What the board does and what you need

An Uno can drive servos straight from its pins, but each servo takes a pin, and the Servo library ties up a timer. The PCA9685 chip has its own clock and 16 outputs. Your board tells it the pulse length for each channel over I2C, then the chip keeps sending those pulses on its own, 50 times a second, until you change them.

You can use it for a 6-servo robot arm, a hexapod, a pan and tilt camera mount or model railway points. Each output has a 3-pin servo header, so an SG90 or MG90S plugs straight in with no extra wiring.

Part Why you need it
PCA9685 servo driver board Makes the 16 servo signals and carries servo power to every header
Arduino Uno, Nano or an ESP32 board Sends the positions over I2C
Micro servos such as the SG90, SG92R or MG90S Our micro servo comparison helps you pick
A separate 5V supply Powers the servos through the green screw terminal
Four or five jumper wires Male to female for an Uno, female to female for an ESP32 dev board

Wiring it to an Arduino Uno

The board has two separate supplies, and mixing them up causes most first-day problems.

  • VCC on the 6-pin header powers only the PCA9685 chip. It takes 3 to 5V from your Arduino or ESP32 and draws a few milliamps.
  • V+ is the servo rail. It comes in through the green screw terminal and feeds the red middle row of every servo header. The board takes 6V at most on V+.
Wiring diagram: Arduino Uno 5V to VCC, GND to GND and OE, A4 to SDA, A5 to SCL; 5V supply positive to the V+ screw and negative to the GND screw; servo plugged into channel 0 with brown on the GND row
Uno logic on the 6-pin header, servo power on the screw terminal, one servo on channel 0. Not to scale.
  1. Logic header to the Uno: VCC to 5V, GND to GND, SDA to A4 and SCL to A5. Run a second wire from OE to another GND pin so the outputs are always switched on.
  2. Leave the V+ pin on the 6-pin header unconnected. It joins straight onto the servo rail.
  3. Servo supply to the screw terminal: positive to the left screw, marked V+ and next to the POWER LED, and negative to the right screw.
  4. Servo on channel 0: channel 0 is the first column next to the 6-pin header. The brown wire goes on the GND row at the board edge, red on the middle V+ row and orange on the yellow PWM row.

You don't need a separate ground wire from the servo supply to the Uno. The terminal's negative screw and the header's GND pin are the same ground on the board, so the GND wire to the Uno joins them.

Treat the screw terminal as unprotected. The underside print says the terminal is reverse polarity protected, but don't rely on it. A supply connected backwards can destroy the 1000µF capacitor and every servo plugged in. Check that positive goes to the V+ screw before you switch on.

Sizing the servo power supply

A micro servo sitting still draws almost nothing. Our SG90 draws 100 to 250mA while moving and up to 700mA when it stalls, which happens every time it starts under load or pushes against something. Metal gear MG90S servos pull at least as much. So plan on about 1A for each servo that can move at the same moment.

Moving at once Supply
1 or 2 A 5V 2A plug pack into a DC barrel socket screw terminal adapter, then two wires to the board's terminal. We suggest up to 2A through that adapter. Our DC barrel jack guide covers plug sizes and which screw is +.
Up to 3, from 12V or 24V The IP67 buck converter, 5V 3A. Its 5V output leads go straight into the terminal, so it suits caravans, boats and anything on a 12V battery. Our 12V power guide shows how to wire it in with a fuse.
4 or 5 The IP67 buck converter, 5V 5A, or a 5V 5A supply
6 to 10 A 5V 10A switch-mode supply, on short, thick leads
11 to 16, such as a hexapod A 5V 15 to 20A supply, on short, thick leads. Check the V+ voltage at the board while everything moves.

Count only the servos that really move together. A display that moves one servo at a time runs happily on 5V 3A even with all 16 plugged in. A walking robot moves most of its legs at once, so it needs the bigger supply.

  • Batteries: four NiMH AA cells give 4.8V, which suits a small portable build. Four fresh alkaline AA cells can sit above 6V, which is over the board's V+ limit.
  • The capacitor: the fitted 1000µF capacitor catches the current spikes when several servos start together. A common rule is about 100µF per servo, so it covers roughly 10. For a full board of 16, add another 470 to 1000µF across the terminal, rated 10V or more, with its stripe to negative. Our electrolytic capacitor kit includes 470µF 16V and 1000µF.
  • Never take servo power from the Arduino's 5V pin. Two servos starting together can pull the Uno's 5V down far enough to reset it.

Install the library and run a first test

  1. In the Arduino IDE, open Tools > Manage Libraries, search PCA9685 and install Adafruit PWM Servo Driver Library. Accept the extra library it asks for (Adafruit BusIO).
  2. Wire the board as above with one servo on channel 0, and without a horn or linkage fitted.
  3. Upload this sketch, then switch on the servo supply.
#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(0x40);
const uint8_t SERVO_CH = 0;    // first column next to the 6-pin header
void setup() {
  pwm.begin();
  pwm.setOscillatorFrequency(25000000);  // see "calibration" below
  pwm.setPWMFreq(50);                    // hobby servos expect 50 Hz
  delay(10);
  pwm.writeMicroseconds(SERVO_CH, 1500); // start at centre
  delay(1000);
}
void loop() {
  pwm.writeMicroseconds(SERVO_CH, 1000);
  delay(1000);
  pwm.writeMicroseconds(SERVO_CH, 2000);
  delay(1000);
}

What you should see: the servo moves to its centre, then swings back and forth through roughly a quarter turn, once a second. A 360° servo turns one way for a second, then the other way. Once that works, widen the range in small steps. Our SG90 180° version reaches its full sweep at about 500 to 2500µs. Stop widening as soon as it buzzes at an end, because that is the servo pushing against its internal stop.

Call setOscillatorFrequency() before setPWMFreq(). The library works out the chip's divider from the oscillator value, so setting it afterwards changes nothing.

50 Hz and the pulse-to-tick maths

A servo reads the length of a pulse, sent about 50 times a second. Around 1500µs means centre, shorter turns one way and longer turns the other. At 50 Hz each cycle lasts 20,000µs, and the PCA9685 splits every cycle into 4096 steps, called ticks. So one tick is about 4.88µs.

Ticks = pulse in µs x 4096 / 20,000

Pulse Ticks 180° 360°
500µs about 102 One end, on servos that reach it Full speed one way
1000µs about 205 About 45° from centre Fast one way
1500µs about 307 Centre Stop
2000µs about 410 About 45° the other way Fast the other way
2500µs about 512 Other end, on servos that reach it Full speed the other way

There are two ways to send a position. pwm.writeMicroseconds(ch, 1500) takes the pulse in microseconds and does the maths for you, which is easiest to read. pwm.setPWM(ch, 0, 307) takes ticks directly: the pulse starts at tick 0 and ends at tick 307. Many online examples use ticks with limits such as 150 and 600, which are tuned for one particular board and servo, so check them against your own servo before using them.

Across a 180° sweep of 2000µs, one tick moves an SG90 by less than half a degree. That is finer than the servo's own gears can hold, so 12-bit resolution is never the limit.

Using it with an ESP32

The board works the same on an ESP32 with two changes.

  • Power VCC from the ESP32's 3V3 pin, not 5V. The board's I2C pull-up resistors connect to VCC. With VCC on 5V, the SDA and SCL lines sit at 5V, which is more than the ESP32's pins are made for. At 3.3V the servo signal also swings to 3.3V, which the SG90, SG92R and MG90S all accept.
  • Use the right I2C pins. On our ESP32-WROOM-32 dev board, SDA is GPIO21 and SCL is GPIO22, which are the defaults, so the Uno sketch runs unchanged. On boards without fixed I2C pins, start the bus on your chosen pins before pwm.begin().
void setup() {
  Wire.begin(4, 5);   // ESP32-C3 SuperMini: SDA on GPIO4, SCL on GPIO5
  pwm.begin();        // uses the bus already started on those pins
  pwm.setOscillatorFrequency(25000000);
  pwm.setPWMFreq(50);
}

The servo supply still goes to the screw terminal, and the ESP32's GND still joins the board's GND. Our ESP32-C3 SuperMini setup guide covers that board's pins. If you use ESPHome instead of Arduino code, its pca9685 output component drives the same board.

More than 16 servos: addresses and chaining

Every board answers on I2C address 0x40 until you change it. The six pad pairs above the "I2C Address" label set the address in binary: bridge a pair with a blob of solder and that bit becomes 1. One board can stay on 0x40, and each extra board needs its own address.

  1. Bridge one pad pair on the second board. The pads aren't labelled A0 to A5, so run an I2C scanner sketch to read the new address. 0x41 means you bridged A0, 0x42 is A1, 0x44 is A2, 0x48 is A3, 0x50 is A4 and 0x60 is A5.
  2. Avoid 0x70. Every PCA9685 also listens on 0x70 as a group address, so a board set to 0x70 clashes with all of them.
  3. Chain the logic. The 6 holes at the far end carry the same GND, OE, SCL, SDA, VCC and V+ as the header. Solder a header or six wires into them and link them to the next board's 6-pin header.
  4. Feed each board's screw terminal from the supply with its own pair of leads. The chain link also joins the V+ rails, so either use one supply for every board, or leave the V+ wire out of the link if each board has its own supply.
Adafruit_PWMServoDriver arm  = Adafruit_PWMServoDriver(0x40);
Adafruit_PWMServoDriver legs = Adafruit_PWMServoDriver(0x41);
void setup() {
  arm.begin();  arm.setOscillatorFrequency(25000000);  arm.setPWMFreq(50);
  legs.begin(); legs.setOscillatorFrequency(25000000); legs.setPWMFreq(50);
}

The chip allows up to 62 boards on one bus, which is 992 servos. In practice the supply runs out long before the addresses do.

What people run into

Jitter when other servos move

If one servo twitches whenever another one starts, the servo supply voltage is dipping. Measure V+ at the screw terminal with a multimeter while the servos move. It should stay above 4.8V, the bottom of a micro servo's rated range. If it drops, use a bigger supply, shorter and thicker leads, or the extra capacitor from the power section. Check that the GND wire to your Arduino or ESP32 is firmly in, because a missing ground also causes jitter.

Servos jump at power-up or after each upload

pwm.begin() restarts the chip, so every reset stops the pulses for a moment. Uploading a sketch, pressing RESET or opening the Serial Monitor on an Uno all cause a reset. The servos go limp, then snap to the first position your sketch sends. Two habits keep this tame:

  • Send each servo its resting position first thing in setup(), and park the mechanism in that same position before you switch off.
  • Switch the servo supply on after the Arduino is running, for example with a switch in the supply's positive lead. Servos often give one twitch when power arrives before any pulse does.

If you wire OE to a spare pin instead of GND, setting that pin HIGH stops all 16 outputs at once. That makes a handy "relax all servos" or stop control.

Centre is off, or a 360° servo won't stop

The PCA9685's internal clock is rated at 25MHz, but real chips run a few percent fast or slow. The library can't know your chip's exact speed, so a 1500µs command can come out at 1440 or 1560µs. On a 180° servo that shifts the centre by several degrees. On a 360° servo it means it creeps at "stop". Two boards can also disagree with each other.

To calibrate with a multimeter that has a Hz setting:

  1. Run your sketch with setOscillatorFrequency(25000000) and setPWMFreq(50), and add pwm.setPWM(15, 0, 2048); to send a square wave on channel 15. Leave channel 15 empty.
  2. Measure the frequency between channel 15's PWM pin and GND. A perfect chip reads 50.0 Hz.
  3. Multiply the reading by 499,712 and use the result as your oscillator value. For example, 51.8 Hz x 499,712 = 25,885,082, so call setOscillatorFrequency(25885082).

Re-measure after the change: it should now read close to 50 Hz. The 499,712 factor only applies when the sketch sets 25000000 and 50 Hz, as in step 1. The library also includes an oscillator example that measures the clock with an ESP32 pin instead of a meter.

5V on an ESP32's I2C pins

With VCC wired to 5V, an ESP32 often still works at first, which makes the mistake easy to miss. Its pins are being held above their rating the whole time. Move VCC to the 3V3 pin.

Servo power from the side headers

The V+ pins on both 6-pin ends connect straight to the servo rail without passing the terminal. Feed servo power only through the screw terminal, and keep the V+ header pin unconnected unless you are joining two boards.

Troubleshooting by symptom

Symptom Likely cause and fix
Nothing moves at all Measure the voltage across the two terminal screws first. If it reads 4.8 to 6V, run an I2C scanner. No 0x40 means SDA and SCL are swapped, VCC is missing or an address jumper is bridged. Also check OE goes to GND.
Servo moves but the wrong one Channel 0 is the column next to the 6-pin header. Count from there.
Arduino resets when servos move Servos are drawing from the Arduino's 5V. Move servo power to the screw terminal and leave the header V+ pin empty.
Servos twitch when others move The supply sags. Measure V+ while moving, then fit a bigger supply or thicker leads.
Buzzes and warms at one end The pulse goes past the servo's end stop. Narrow the range in code.
Barely moves, or moves the wrong amount setPWMFreq(50) is missing, or the oscillator value is far out. Calibrate it.
360° servo creeps at 1500µs Adjust the stop value in 5µs steps, or calibrate the oscillator.
All servos jump on upload Normal reset behaviour. Send rest positions first in setup().
Works on Uno, not on ESP32 VCC must be 3V3, and check the SDA and SCL GPIO numbers for your board.

Frequently asked questions

Can I use the Arduino Servo library with this board?

No. The Servo library makes pulses on the Arduino's own pins. The PCA9685 needs its own library, such as Adafruit PWM Servo Driver, which sends the pulse lengths over I2C instead.

Can I mix 180° and 360° servos on one board?

Yes. Every channel runs at the same 50 Hz, and each one gets its own pulse length. Send a position to the 180° servos and a speed to the 360° servos, using the table in the pulse maths section.

Can the board run larger standard-size servos?

Yes, if they run on 6V or less. They plug into the same 3-pin headers. They draw more current than micro servos, often over 1A each under load, so size the supply from their stall current.

Sixteen servos from two wires

The PCA9685 board drives 16 servos from two I2C wires on an Uno or ESP32. Give the servos their own 5V supply and it handles the rest.

View the PCA9685 board

Practical help from New Zealand

Still stuck? Send us a photo.

Tell us what you’re building and what the circuit is doing. Our small NZ team knows these parts and can help you spot a wiring problem or choose what you need next.

Ask NZN for help Browse more guides