PCA9685 board/Builds/11. The first servo
Builds · 11 of 13

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

The first servo, four wires and a plug
ESP32-S3: VCC to 3V3
Microcontroller
VCC to
3V3
SDA / SCL
GPIO 8 / GPIO 9
Servo on
channel 0
VCC goes to 3V3. The pull-ups on SDA and SCL go to VCC, so VCC at 3.3 V keeps the bus at the ESP32-S3's own logic level. Its SDA is GPIO 8 and SCL is GPIO 9. Leave both underside pads open, and let the adapter power the servo.
BoardESP32-S3 DevKitCArduino Uno
GNDGNDGND
VCC3V35V
SDAGPIO 8A4
SCLGPIO 9A5
OEnot connectednot connected
V+not connectednot 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 us

A 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

first_servo.ino

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 Serial Monitor says No PCA9685 at 0x40.

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.

It prints every line and the servo does not move.

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.

Nothing at all appears in the Serial Monitor on the ESP32-S3.

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.

The servo moves, but buzzes at one end.

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.

It will not compile: Adafruit_PWMServoDriver.h not found.

Install the Adafruit PWM Servo Driver Library from the Library Manager (Sketch, Include Library, Manage Libraries), and accept its dependency, Adafruit BusIO, if asked.

Where this goes next

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

Community

Questions about this product

See what other owners have asked, and read their solutions.

Ask a question ↗

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.

Browse Modules and blocks on the forum →