To reliably control a servo with a Raspberry Pi, you must use an external I2C PWM driver like the NXP PCA9685 and a dedicated 5V/6V power supply. Relying on the Pi’s native GPIO pins for software PWM introduces severe jitter due to Linux kernel scheduling, while the single hardware PWM pin (GPIO 18) limits you to one motor. This guide covers the exact hardware stack, motor selection criteria, torque sizing math, and wiring topology required to run high-load servos without corrupting your Pi's SD card.
Why the Pi Demands a Dedicated PWM Controller
The Raspberry Pi runs a general-purpose Linux operating system, not a real-time operating system (RTOS). When you attempt to generate a PWM signal via software on standard GPIO pins, the Linux kernel periodically pauses your Python or C++ script to handle background tasks like network polling, USB interrupts, or memory management. For a hobby servo, which expects a precisely timed 1ms to 2ms pulse every 20ms (50Hz), a kernel delay of just 2 milliseconds causes the servo to twitch, hum, or drift to the wrong position.
While the Pi does have hardware PWM capabilities, they are largely restricted to GPIO 18 (and partially GPIO 19), limiting you to a single servo. To control multiple servos or free up GPIO 18 for other uses, the industry standard solution is the NXP PCA9685 16-channel PWM driver.
Motor Selection: Servo vs. Stepper vs. DC for Pi Projects
Before wiring anything, you must confirm a servo is actually the right actuator for your load profile. Makers frequently confuse servos and steppers, treating them as interchangeable position-control motors. They are not. A servo is a closed-loop DC motor with an internal gearbox and potentiometer, optimized for high holding torque over a limited angular range (usually 180° or 270°). A stepper is an open-loop motor optimized for precise, continuous rotational steps, but its torque drops sharply as RPM increases.
| Motor Type | Torque Curve Profile | Control Needs (Driver) | Typical Cost (USD) | Best Pi Use Case |
|---|---|---|---|---|
| Hobby Servo (e.g., MG996R) | High holding torque at zero speed; limited angular travel (180°/270°). | 50Hz PWM signal (PCA9685); 5V-6V DC power. | $8 - $18 | Robotic arms, camera pan/tilt, RC steering, throttles. |
| NEMA 17 Stepper | High torque at low RPM; torque drops linearly as speed increases. | Step/Dir pulses via driver (A4988, TMC2209); 12V-24V DC. | $12 - $25 (plus driver) | CNC plotters, 3D printer extruders, linear actuators, continuous rotation. |
| Brushed DC Gearmotor | Peak torque at stall; drops as speed increases; continuous rotation. | H-Bridge (L298N, DRV8871) for speed/direction; 6V-12V DC. | $10 - $20 | Drive wheels, conveyors, winches (requires external encoder for position). |
| Brushless DC (BLDC) | Extremely high power-to-weight; requires complex commutation. | 3-phase ESC (Electronic Speed Controller); 12V-48V DC. | $30 - $60+ | Drones, high-speed spindles, heavy-load continuous rotation. |
Which motor fits this load profile? If your project requires moving a specific payload to an exact angular position under 360 degrees and holding it there against gravity (like a robotic arm joint or a heavy camera rig), the closed-loop servo is the correct choice. If you need continuous rotation with precise distance tracking (like a rover wheel), use a DC gearmotor with a quadrature encoder or a stepper motor.
Sizing Your Servo: Torque, Load, and Failure Signatures
Servo torque is rated in kg-cm or oz-in. This number represents the stall torque—the maximum weight the motor can hold at a specific distance from the output shaft before it stalls. A common beginner mistake is sizing the servo exactly to the calculated static load. In reality, dynamic movement, inertia, and mechanical friction require a significant safety margin.
The Sizing Rule of Thumb: Calculate your maximum static load torque, then multiply by a 2.5x safety factor for dynamic robotic applications.
Worked Load Example
Suppose you are building a robotic arm that needs to lift a 500g (0.5 kg) payload. The distance from the servo's output shaft to the center of mass of the payload is 15 cm.
- Static Torque: 0.5 kg × 15 cm = 7.5 kg-cm.
- Dynamic Safety Factor: 7.5 kg-cm × 2.5 = 18.75 kg-cm.
- Selection: You need a servo rated for at least 19 kg-cm. A standard MG996R (rated ~13 kg-cm) will fail here. You must step up to a 20 kg-cm servo like the DS3218 or a 25 kg-cm serial bus servo like the LewanSoul LX-224.
Reading Failure Signatures
When a servo system fails, it rarely dies silently. The physical symptoms tell you exactly what is wrong electrically or mechanically:
- Humming and Jittering: This is almost always a power delivery issue. The 5V rail is sagging under load, or the signal ground is not shared with the power ground. The internal potentiometer is reading voltage fluctuations as position errors, causing the motor to rapidly correct back and forth.
- Overheating (Too hot to touch): The servo is stalled against a physical hard stop or an oversized load. At stall, a large servo like the MG996R will draw its maximum stall current (up to 2.5A) continuously. Without a thermal cutoff, the internal H-bridge MOSFETs and motor windings will cook the plastic casing within minutes.
- Clicking or Grinding: Mechanical failure. The nylon or brass internal gears have stripped teeth, or the wiper on the internal feedback potentiometer has worn through the carbon track, causing the control board to lose track of the shaft position.
Wiring the PCA9685 and Powering the Bus
Wiring high-torque servos directly to the Raspberry Pi’s 5V GPIO pin is the fastest way to corrupt your microSD card. A single large servo pulling 2.5A at stall will drag the Pi's 5V rail down below 4.6V, triggering a brownout. You must separate the logic power from the motor power.
| Terminal Label | Function | Voltage / Signal | Connection Target |
|---|---|---|---|
| VCC | Logic power for the PCA9685 IC | 3.3V DC | Raspberry Pi Pin 1 (3V3) |
| GND | Logic and Signal Ground | 0V | Raspberry Pi Pin 6 (GND) |
| V+ | High-current motor power rail | 5.0V - 6.0V DC | External 5V/6V Power Supply (+) |
| GND (Screw) | High-current motor ground | 0V | External Power Supply (-) AND Pi GND |
| SDA | I2C Data Line | 3.3V Logic | Raspberry Pi Pin 3 (GPIO 2) |
| SCL | I2C Clock Line | 3.3V Logic | Raspberry Pi Pin 5 (GPIO 3) |
| OE | Output Enable (Active Low) | 3.3V Logic | Leave unconnected (pulled low internally) or tie to Pi GND |
Establishing the Common Ground
The most frequent cause of servo jitter in Pi projects is a missing common ground. The PWM signal generated by the PCA9685 is referenced to its logic ground. If the external 5V power supply's ground is not physically tied to the Raspberry Pi's ground, the signal voltage will float, and the servo will interpret the noise as erratic position commands. Always run a dedicated ground wire from the external power supply's negative terminal to the GND screw terminal on the PCA9685, and ensure the PCA9685's logic GND is tied to the Pi's GND.
I2C Addressing and Pull-ups
By default, the PCA9685 listens on I2C address 0x40. If you need to daisy-chain multiple driver boards for a hexapod or complex animatronic, you can solder the A0 through A5 jumper pads on the PCB to shift the address up to 0x7F. The Raspberry Pi's internal I2C pull-up resistors (1.8kΩ) are generally sufficient for short wire runs (under 30cm). If you are running long I2C cables across a metal chassis, add external 4.7kΩ pull-up resistors to the SDA and SCL lines to prevent signal degradation and I2C bus lockups.
For complete software implementation, refer to the Adafruit PCA9685 Learning System, which provides robust Python libraries (CircuitPython and standard Python via adafruit-circuitpython-pca9685) that handle the 12-bit duty cycle math and 50Hz frequency configuration automatically. Always initialize the PWM frequency to exactly 50Hz before sending your first pulse to prevent the servo from slamming into its mechanical end-stops during boot.






