The first servo
One servo on channel 0, driven from an ESP32-S3 DevKitC or an Arduino Uno, moving between 1000 and 2000 µs every second and a half. Four wires from the microcontroller, a 5 V adapter in the board's USB-C socket, and one sketch that compiles for both boards and says on the Serial Monitor what it is doing.
What you need
- One board from the box, address pads untouched (0x40).
- An ESP32-S3 DevKitC or an Arduino Uno, and its USB cable to the computer.
- One servo: an SG90 is ideal.
- A 5 V USB-C adapter for the board, not a computer port.
- Four female-to-male jumper wires.
Wire it
| Board | ESP32-S3 DevKitC | Arduino Uno |
|---|---|---|
| GND | GND | GND |
| VCC | 3V3 | 5V |
| SDA | GPIO 8 | A4 |
| SCL | GPIO 9 | A5 |
| OE | not connected | not connected |
| V+ | not connected | not connected |
VCC goes to the microcontroller's own logic voltage: 3V3 on the ESP32-S3, 5V on the Uno. That sets the voltage on SDA and SCL (V+ and VCC), and it is the one wire in this build that can damage something if it goes to the wrong pin. Leave both pads on the underside open.
Then the servo on channel 0, at the left end of the servo field: brown or black on the bottom row, red in the middle, the signal on the top. Plug the adapter into the board's USB-C socket last. Both LEDs should now be lit: red for VCC, blue for V+.
Set up the IDE
Install Adafruit PWM Servo Driver Library from the Library Manager. Choose ESP32S3 Dev Module or Arduino Uno under Tools, Board. On the ESP32-S3, set Tools, USB CDC On Boot to Enabled, or the Serial Monitor stays empty. Open the Serial Monitor at 115200.
On another ESP32, put its own SDA and SCL pin numbers in Wire.begin().
What it prints
PCA9685 at 0x40, 50 Hz
1000 us
2000 us
1000 us
2000 usA new line every 1.5 s, and the servo swings from one end to the other on each.
If the first line is No PCA9685 at 0x40. instead, the chip did not answer:
look at VCC, SDA, SCL and GND before anything else.
The line to change later
OSC_HZ is 25 MHz, the datasheet's typical figure. If the servo's positions
look a little off, or you want them exact, measure your chip once as in
4096 counts and put the result there.
The code
The same sketch for both boards. On an ESP32 it starts I²C on GPIO 8 and 9; on an Uno, Wire.begin() uses A4 and A5. Every width is in microseconds, so the numbers are the ones from A pulse, not an angle.
// The first servo: channel 0 between 1000 and 2000 us.
//
// Wiring ESP32-S3 DevKitC Arduino Uno
// GND -> GND GND
// VCC -> 3V3 5V
// SDA -> GPIO 8 A4
// SCL -> GPIO 9 A5
// OE, V+ not connected not connected
// A 5 V USB-C adapter in the board's USB-C socket.
// Servo on channel 0, brown or black wire on the GND row.
//
// Arduino IDE: Tools > Board > ESP32S3 Dev Module,
// or Arduino Uno.
// ESP32-S3: Tools > USB CDC On Boot > Enabled.
// Serial Monitor at 115200.
// Library: Adafruit PWM Servo Driver Library.
#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>
// 25 MHz is the datasheet's typical figure, not a
// promise. Adafruit's servo example assumes 27 MHz.
// Measure yours: osc = Hz x 4096 x (prescale + 1).
const uint32_t OSC_HZ = 25000000;
const uint8_t CHANNEL = 0;
const uint16_t END_A = 1000; // us
const uint16_t END_B = 2000; // us
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(0x40);
void moveTo(uint16_t us) {
pwm.writeMicroseconds(CHANNEL, us);
Serial.print(us);
Serial.println(" us");
}
void setup() {
Serial.begin(115200);
delay(1000);
#if defined(ESP32)
Wire.begin(8, 9); // SDA, SCL
#else
Wire.begin(); // A4, A5 on an Uno
#endif
if (!pwm.begin()) {
Serial.println("No PCA9685 at 0x40.");
Serial.println("Check GND, VCC, SDA and SCL.");
while (true) delay(1000);
}
pwm.setOscillatorFrequency(OSC_HZ);
pwm.setPWMFreq(50); // one pulse every 20 ms
Serial.println("PCA9685 at 0x40, 50 Hz");
}
void loop() {
moveTo(END_A);
delay(1500);
moveTo(END_B);
delay(1500);
}begin() returns false when nothing answers at 0x40, and the sketch stops there with a message rather than moving a servo that is not connected. OSC_HZ is the one line to change after you measure your chip.
When it does not work
The chip did not answer. Check the red VCC LED is on, then SDA to GPIO 8 or A4 and SCL to GPIO 9 or A5, not swapped. Check GND is wired. If the address pads underneath are bridged, the board is not at 0x40.
The chip is fine and the servo has no power or no pulse. Check the blue V+ LED: no light means no adapter. Then check the servo plug is the right way round, on channel 0, and that OE is not wired to anything.
USB CDC On Boot must be Enabled for Serial to reach the USB port on the S3, and the Monitor must be at 115200. Set it in the Tools menu, upload again, and press the board's reset button.
That servo's travel ends before 1000 or 2000 µs. Bring END_A up or END_B down by 50 at a time until the buzz stops.
Install the Adafruit PWM Servo Driver Library from the Library Manager (Sketch, Include Library, Manage Libraries), and accept its dependency, Adafruit BusIO, if asked.
Every channel sweeping, started a few at a time so the supply keeps up.
Sixteen at once →Edit this page — content/books/pca9685/first-servo.mdx
Questions about this product
See what other owners have asked, and read their solutions.
PCA9685 16-Channel Servo Driver Board, USB-C Powered
Loading discussions…
Discuss this article
Ask about this page. The answer stays here, on the page it belongs to, for whoever hits the same wall next.