The pan-tilt bracket turns two ordinary 9 g micro servos into a two-axis motion platform: one servo swings the head left-right (pan), the other nods it up-down (tilt). Bolt a sensor or small camera to the top plate and you can aim, sweep, and track from code — the mechanism behind robot heads, ultrasonic radar sweepers, laser pointers, FPV camera mounts, and face-tracking builds.
The kit is sized for the SG90 (plastic gear) and MG90S (metal gear) footprint, which means it pairs with the cheapest and best-documented servos in the hobby. Assembly takes a few minutes and one screwdriver, with a single rule that saves the whole experience: center both servos at 90° before screwing horns into brackets, so the assembled head sits centered when your code says center.
Driving it is standard servo work — two 50 Hz PWM channels — so every board here (Arduino, ESP32, Raspberry Pi, Pico) controls it natively. This manual covers assembly, wiring for all four platforms, scanning and pose code you can paste in, and the practical questions on payload, jitter, and which servo to choose for each axis.
At a Glance
Motion
2-axis: pan + tilt
Servo Fit
SG90 & MG90S (9 g class)
Range
~180° pan · ~90–150° usable tilt
Payload
Light sensors & mini cameras
Control
2 × standard 50 Hz PWM
Assembly
Required — small screwdriver
Specifications
Parameter
Value
Axes
2 — pan (base rotation) and tilt (nod)
Servo compatibility
SG90, MG90S, and same-footprint 9 g micro servos
Servos included
Brackets and hardware only — servos sold separately
USB 5 V tolerates gentle moves; external is reliable
Both servo browns
Supply − AND Arduino GND
Common ground always
Center before you screw. Command both servos to 90° first, then attach horns to brackets with the head physically centered and level. Skip this and the assembled head will be built crooked — and its very first move can drive the tilt into the bracket at full torque.
ESP32 Wiring
Connection
ESP32
Notes
Pan servo signal
GPIO 26
3.3 V signal drives 5 V servos fine
Tilt servo signal
GPIO 27
Any free output pin works
Servo power (red)
External 5 V (or strong VIN)
Not the 3V3 pin
Servo ground (brown)
Supply − AND ESP32 GND
Common ground
The classic pairing. Pan-tilt + ESP32 + HC-SR04 gives you a scanning “radar”; pan-tilt + ESP32-CAM gives you a camera you steer from a browser. Both stay within the bracket’s payload happily — keep camera ribbon and sensor cables slack so the head turns freely.
Raspberry Pi Wiring
Connection
Raspberry Pi
Notes
Pan servo signal
GPIO 17 (Pin 11)
—
Tilt servo signal
GPIO 27 (Pin 13)
—
Servo power (red)
External 5 V supply +
The Pi’s 5 V rail browns out under servo spikes
Servo ground (brown)
Supply − AND Pi GND (Pin 6)
Common ground
Kill the jitter. Linux software PWM makes servos tremble. The example below uses the pigpio pin factory for hardware-timed pulses — run sudo systemctl start pigpiod first — and the trembling stops.
Raspberry Pi Pico Wiring
Connection
Pico
Notes
Pan servo signal
GP14 (Pin 19)
Any PWM pin
Tilt servo signal
GP15 (Pin 20)
Any PWM pin
Servo power (red)
VBUS (Pin 40) or external 5 V
External if moves are fast or loaded
Servo ground (brown)
GND (Pin 38) + supply −
Common ground
Define soft limits. Find the tilt angles where the bracket just touches itself, back off 5°, and clamp every commanded angle to that window in code. A servo pushed against the bracket buzzes, heats, and eventually strips — soft limits make the mechanism effectively unbreakable.
Code Examples
Arduino — Smooth Scan Pattern
pan_tilt_scan.ino
#include <Servo.h>
Servo pan, tilt;
const int PAN_MIN = 20, PAN_MAX = 160; // soft limits
const int TILT_MIN = 60, TILT_MAX = 120;
void setup() {
pan.attach(9);
tilt.attach(10);
pan.write(90);
tilt.write(90);
delay(800);
}
void loop() {
// sweep pan at each tilt step - a "radar" raster
for (int t = TILT_MIN; t <= TILT_MAX; t += 20) {
tilt.write(t);
for (int p = PAN_MIN; p <= PAN_MAX; p += 2) {
pan.write(p);
delay(15);
}
for (int p = PAN_MAX; p >= PAN_MIN; p -= 2) {
pan.write(p);
delay(15);
}
}
}
ESP32 — Aim at Named Targets
esp32_pan_tilt.ino
// Library Manager: install "ESP32Servo"
#include <ESP32Servo.h>
Servo pan, tilt;
void aim(int p, int t) { // glide both axes together
static int cp = 90, ct = 90;
while (cp != p || ct != t) {
if (cp < p) cp++; else if (cp > p) cp--;
if (ct < t) ct++; else if (ct > t) ct--;
pan.write(cp);
tilt.write(ct);
delay(10);
}
}
void setup() {
pan.setPeriodHertz(50); pan.attach(26, 500, 2500);
tilt.setPeriodHertz(50); tilt.attach(27, 500, 2500);
pan.write(90); tilt.write(90);
delay(800);
}
void loop() {
aim(40, 80); delay(700); // look left-down
aim(140, 80); delay(700); // look right-down
aim(90, 115); delay(700); // look up-center
aim(90, 90); delay(1200); // home
}
Raspberry Pi — Python (gpiozero + pigpio)
pan_tilt.py
from gpiozero import AngularServo
from gpiozero.pins.pigpio import PiGPIOFactory
from time import sleep
# sudo apt install pigpio; sudo systemctl start pigpiod
factory = PiGPIOFactory()
def servo(pin):
return AngularServo(pin, min_angle=0, max_angle=180,
min_pulse_width=0.0005, max_pulse_width=0.0025,
pin_factory=factory)
pan, tilt = servo(17), servo(27)
pan.angle, tilt.angle = 90, 90
sleep(1)
def glide(s, start, end, step=2, dt=0.02):
rng = range(start, end + 1, step) if end > start else range(start, end - 1, -step)
for a in rng:
s.angle = a
sleep(dt)
while True:
glide(pan, 90, 30)
glide(pan, 30, 150)
glide(pan, 150, 90)
glide(tilt, 90, 65)
glide(tilt, 65, 115)
glide(tilt, 115, 90)
sleep(1)
Raspberry Pi Pico — MicroPython
pico_pan_tilt.py
from machine import Pin, PWM
import time
pan = PWM(Pin(14)); pan.freq(50)
tilt = PWM(Pin(15)); tilt.freq(50)
def angle(pwm, deg):
deg = max(0, min(180, deg)) # clamp
us = 500 + deg * (2000 / 180) # 500-2500 us
pwm.duty_u16(int(us * 65535 / 20000))
angle(pan, 90); angle(tilt, 90)
time.sleep(1)
while True:
# lazy-eight patrol
for d in range(30, 151, 2):
angle(pan, d)
angle(tilt, 90 + (25 if d < 90 else -25))
time.sleep(0.02)
for d in range(150, 29, -2):
angle(pan, d)
angle(tilt, 90 + (-25 if d < 90 else 25))
time.sleep(0.02)
Frequently Asked Questions
SG90 or MG90S — which should I put in it?
Both fit. The SG90 (plastic gears) is lighter and fine for feather-weight loads like a PIR or laser diode. The MG90S (metal gears) shrugs off the bumps and stalls that strip plastic gears, which makes it the better choice for cameras, ultrasonic sensors, and anything that will run scanning patterns for hours. Many builds split the difference: MG90S on tilt (it fights gravity), SG90 on pan.
The head sits crooked when I command 90/90. Did I break it?
No — the horns went on while the servos were off-center, or one spline tooth off. Unscrew the horn, command the servo to 90°, and reseat the horn with the bracket physically centered. One spline tooth on these servos is ~4°, so being one tooth off is visible; recentering takes two minutes.
How much weight can it carry?
Think in tens of grams: an HC-SR04, a PIR, a laser module, or an ESP32-CAM are all comfortable. A 9 g servo makes ~1.8–2.2 kg·cm of torque, and the tilt axis holds the payload on a lever arm — past roughly 50–80 g the tilt servo hums, drifts, and overheats. Action cameras and phone-sized loads need a bigger bracket and standard-size servos.
The servos buzz and twitch even when “still.” Why?
Three usual suspects, in order: power (share a solid 5 V supply with common ground — USB rails sag), software PWM on the Pi (use pigpio as in the example), and commanding an angle the bracket cannot reach (add soft limits). A servo holding against gravity also murmurs a little under load — that part is normal.
Can I hang it upside down or on a wall?
Yes — the geometry works in any orientation; only your angle math changes (invert pan and/or tilt in code rather than rebuilding). Ceiling-mounted pan-tilt with a camera is a classic surveillance-style build. Just re-derive the soft limits in the new orientation, since gravity now loads the tilt differently.
How do I control it with a joystick?
Map the joystick’s two analog axes to pan and tilt angles — read X and Y with analogRead, scale 0–1023 to your soft-limit window, and write the servos each loop with a little smoothing. A KY-023 joystick module drops into this in twenty lines; it is the most satisfying first upgrade to the scanning demos above.
Do I need a servo driver board for just two servos?
No — every platform here drives two servos directly. A PCA9685 driver becomes worthwhile on the Raspberry Pi (hardware PWM without pigpio) or the day the project grows into multiple pan-tilt heads or an arm. For a single bracket, two GPIOs and a decent 5 V supply are the whole requirement.