Month 6 Box - Build TARS

Servos and the PCA9685 Driver

Servos and the PCA9685 Driver

Every move TARS makes comes from a servo, and all of them are driven through a single small board, the PCA9685, that the Raspberry Pi commands over I2C. This is one of the most satisfying moments of the build because it fuses two things you already know: the pulse width modulation that positions a servo, from Month 1, and the I2C protocol you used to talk to smart-home devices, from Month 4. Nothing here is new physics, it is your existing skills pointed at a robot.

How a servo knows where to go

A hobby servo is a little motor with built-in electronics that hold a commanded angle. You tell it the angle with a PWM signal, the same pulse-width idea from Month 1: the width of a repeating pulse sets the position, a short pulse sending it to one end of its travel and a longer pulse to the other. The servo constantly compares the signal it is receiving against where its output shaft actually is, and drives itself until the two match, then holds. So controlling TARS ultimately comes down to sending the right pulse widths to each joint, which is a comfortable idea once you have blinked an LED and dimmed one with PWM.

Why a dedicated driver board

TARS has many servos, and the Pi cannot cleanly generate that many precise PWM signals at once while also running its camera, its AI, and everything else. The PCA9685 solves this. It is a dedicated sixteen-channel PWM driver that the Pi commands over I2C, the same two-wire connection (a data line and a clock line) you used for I2C sensors and displays in Month 4. The Pi simply says, over that connection, "set channel three to this angle," and the PCA9685 does the real-time work of generating the steady pulse for that servo. Just as importantly, it lets the servos draw their power from the six-volt rail you built last lesson while the Pi only sends the tiny control signals, which is exactly the separation that keeps the Pi from crashing.

Two sizes of servo, matched to their jobs

TARS uses larger, stronger servos to move the body and legs where torque matters, and smaller ones to animate the hands and fingers in the full-arms build where the loads are light. This is the same match-the-part-to-the-job thinking as choosing PETG for the body and TPU for the feet: a strong servo where you need force, a small one where you need delicate motion.

Driving a servo in Python

With the PCA9685 wired to the Pi over I2C and powered from the servo rail, moving a servo is a few lines of Python, and it will feel familiar after Month 3. You install the driver library, tell it the PWM frequency servos expect, and set an angle:

import time
from board import SCL, SDA
import busio
from adafruit_pca9685 import PCA9685
from adafruit_motor import servo

i2c = busio.I2C(SCL, SDA)      # the same I2C bus as Month 4 devices
pca = PCA9685(i2c)
pca.frequency = 50            # 50 Hz is standard for hobby servos

joint = servo.Servo(pca.channels[0])   # a servo on channel 0

for angle in (0, 90, 180, 90):
    joint.angle = angle       # PWM sets the servo's position
    time.sleep(0.5)

joint.angle = 90              # leave it centered at its home position

Setting joint.angle sends that servo to that angle; the library and the PCA9685 handle turning it into the right pulse. Notice the last line: before you ever bolt a servo into the body, you send it to a defined home position. If you assemble a servo while it is sitting at a random angle, that joint will run out of travel on one side once it is built in. Setting each servo to home first, and only then attaching its horn and installing it, is the assembly rule that saves you from taking the robot apart later.

The channel-to-joint map and servo wiring come from TARS-AI

This lesson teaches how the driver works and how to command a servo. Which servo plugs into which PCA9685 channel, the servo power wiring, and the home angles for each joint are specified by the TARS-AI Community. Follow their wiring and their software, which already knows these mappings, and use their Discord if a servo behaves oddly:

Docs and wiring: docs-tars-ai.vercel.app · GitHub: github.com/TARS-AI-Community/TARS-AI · Discord: discord.gg/AmE2Gv9EUt

If a servo jitters or buzzes, the usual causes are power and grounding: the servos need their own rail, and the Pi and the PCA9685 must share a common ground so they agree on what zero volts means. Get power, ground, and I2C right, set each servo to home, and you have the muscles of the robot under your command.