How to Control SG90 Servo Motors Using Raspberry Pi
If you’ve ever wanted to add precise, programmable movement to your Raspberry Pi projects, the SG90 micro servo motor is one of the easiest and most rewarding components to start with. These tiny motors pack a surprising amount of torque and accuracy into a package smaller than a matchbox, making them ideal for robotics arms, camera gimbals, animatronics, and even small-scale automation.
In this guide, we’ll walk through everything you need to know: from wiring and power considerations to Python code that gives you full control over position, speed, and multi-servo coordination. By the end, you’ll be able to command your SG90 servos like a pro.
Why the SG90 Micro Servo Is So Popular
Before diving into the wiring and code, it’s worth understanding what makes the SG90 a favorite among makers and hobbyists.
Key Specs That Matter
- Operating Voltage: 4.8V to 6.0V (5V is the sweet spot)
- Stall Torque: 1.8 kg·cm at 4.8V (enough to lift small objects or rotate a lightweight camera)
- Operating Speed: 0.12 seconds per 60° at 4.8V (fast enough for most motion projects)
- Weight: Just 9 grams (barely adds any load to your robot)
- Rotation Range: 0° to 180° (standard servo) or 360° continuous rotation (modified versions)
What sets the SG90 apart from larger servos is its low power consumption and direct 5V compatibility with the Raspberry Pi’s GPIO pins (as long as you don’t draw too much current from the 5V rail). The plastic gears are lightweight and quiet, and the price is low enough that you can buy a handful for multi-axis projects.
Common Use Cases
- Pan-and-tilt camera mounts
- Small robotic arms (2–3 DOF)
- RC car steering
- Automatic door locks
- Model train switch controls
- Interactive art installations
Understanding PWM: The Language of Servos
The SG90, like all standard hobby servos, is controlled using Pulse Width Modulation (PWM) . The Raspberry Pi doesn’t output true analog voltages, but it can generate precise digital pulses that the servo interprets as position commands.
How PWM Controls Position
A servo expects a 50 Hz signal (20 ms period). Within each period, a pulse of a specific width tells the servo where to go:
- 1 ms pulse (0.5–1 ms typical): 0° position (full left)
- 1.5 ms pulse: 90° position (center)
- 2 ms pulse (2–2.5 ms typical): 180° position (full right)
The exact pulse widths vary slightly between servos, so you’ll often need to calibrate your SG90 by testing the minimum and maximum values that actually move the horn to the mechanical stops.
20 ms period (50 Hz) |--------|--------|--------|--------| ↑ 1 ms → 0° ↑ 1.5 ms → 90° ↑ 2 ms → 180°
Why Raspberry Pi’s Software PWM Works Well
The Raspberry Pi has built-in hardware PWM on GPIO12, GPIO13, GPIO18, and GPIO19, but you can also use software PWM on any GPIO pin. For most SG90 projects, software PWM is perfectly fine because the servo doesn’t require microsecond-level precision—the mechanical gears smooth out small timing jitter.
Wiring the SG90 to Your Raspberry Pi
The SG90 has three wires, usually color-coded as:
- Orange (or Yellow): Signal (PWM input)
- Red: Power (5V)
- Brown (or Black): Ground
The Critical Power Consideration
Never power the servo directly from the Raspberry Pi’s 3.3V pin. The SG90 needs 5V, and even more importantly, it can draw up to 500 mA under load. The Pi’s 5V rail can supply around 1.2A total (depending on the model), so one or two servos might be okay if you’re not also powering USB devices. But for anything beyond that, or if you want reliable operation, use an external 5V power supply.
Recommended Wiring Diagram
Raspberry Pi GPIO SG90 Servo ----------------- ---------- GPIO18 (Pin 12) ────── Orange (Signal) 5V Pin (Pin 2 or 4) ──── Red (Power) GND Pin (Pin 6) ────── Brown (Ground)
External 5V Supply (optional for multiple servos) +5V ──────────────── Red (Power) GND ──────────────── Brown (Ground)
If using an external supply, connect the ground of the external supply to the Raspberry Pi’s ground to create a common reference. Otherwise, the signal voltage won’t be interpreted correctly.
Adding a Capacitor for Smooth Operation
A 470 µF electrolytic capacitor across the servo’s power and ground (close to the servo) helps absorb current spikes and prevents voltage drops that could reset your Pi. This is especially important when the servo starts moving under load.
Software Setup: Installing Required Libraries
We’ll use Python with the RPi.GPIO library, which comes pre-installed on most Raspberry Pi OS images. If you’re using a fresh install, it’s already there.
Step 1: Enable PWM on Your Chosen Pin
You don’t need to enable anything special for software PWM. Just make sure your user has permission to access the GPIO pins (usually gpio group membership).
bash sudo usermod -a -G gpio pi
Log out and back in for the change to take effect.
Step 2: Test Your Wiring with a Simple Script
Create a file called servo_test.py:
python import RPi.GPIO as GPIO import time
SERVO_PIN = 18
GPIO.setmode(GPIO.BCM) GPIO.setup(SERVO_PIN, GPIO.OUT)
Create PWM instance with 50 Hz frequency
pwm = GPIO.PWM(SERVO_PIN, 50) pwm.start(0) # Start with duty cycle 0 (no signal)
def set_angle(angle): # Convert angle (0-180) to duty cycle (2.5-12.5 typical) duty = 2.5 + (angle / 180.0) * 10.0 pwm.ChangeDutyCycle(duty) time.sleep(0.5) # Give servo time to move pwm.ChangeDutyCycle(0) # Stop sending signal to reduce jitter
try: while True: setangle(0) time.sleep(1) setangle(90) time.sleep(1) set_angle(180) time.sleep(1) except KeyboardInterrupt: pwm.stop() GPIO.cleanup()
Run it with:
bash python3 servo_test.py
You should see the servo sweep from 0° to 180° and back. If it doesn’t move to the full range, adjust the duty calculation—some SG90s need 2.0–12.0 instead of 2.5–12.5.
Fine-Tuning the Pulse Width Range
Every SG90 is slightly different due to manufacturing tolerances. The duty cycle values I gave above are a good starting point, but you may need to calibrate.
Finding the True Min and Max
Write a script that lets you manually adjust the duty cycle:
python import RPi.GPIO as GPIO import time
SERVOPIN = 18 GPIO.setmode(GPIO.BCM) GPIO.setup(SERVOPIN, GPIO.OUT) pwm = GPIO.PWM(SERVO_PIN, 50) pwm.start(0)
try: while True: duty = float(input("Enter duty cycle (2.0 to 12.0): ")) pwm.ChangeDutyCycle(duty) time.sleep(0.5) pwm.ChangeDutyCycle(0) except KeyboardInterrupt: pwm.stop() GPIO.cleanup()
Start at 2.5 and increase by 0.1 until you hear the servo click against its mechanical stop. That’s your 0° position. Then do the same from the high end (12.5 downward) to find 180°. Record these values and use them in your code.
Why You Should Stop the PWM Signal After Moving
Notice in the code above we set duty cycle to 0 after each move. This is important: if you leave a constant PWM signal on the servo, it will continue to draw power trying to hold that position, causing jitter and overheating. Sending a 0% duty cycle effectively disables the signal, and the servo’s internal controller will hold the last position with less power.
Controlling Multiple SG90 Servos Simultaneously
One Raspberry Pi can control many servos, but you need to be careful about power and GPIO pin allocation.
Power Budget for Multiple Servos
- 1 servo: ~200 mA idle, up to 500 mA under load
- 4 servos: ~2A peak (external 5V supply strongly recommended)
- 8 servos: ~4A peak (dedicated servo controller like PCA9685 recommended)
If you’re using more than 2 servos, do not power them from the Pi’s 5V rail. Use a separate 5V supply and connect its ground to the Pi’s ground.
Multi-Servo Code Example
Here’s how to control 4 servos on GPIO18, 19, 20, and 21:
python import RPi.GPIO as GPIO import time
SERVOPINS = [18, 19, 20, 21] NUMSERVOS = len(SERVO_PINS)
GPIO.setmode(GPIO.BCM) for pin in SERVO_PINS: GPIO.setup(pin, GPIO.OUT)
pwms = [] for pin in SERVO_PINS: pwm = GPIO.PWM(pin, 50) pwm.start(0) pwms.append(pwm)
def set_angles(angles): for i, angle in enumerate(angles): duty = 2.5 + (angle / 180.0) * 10.0 pwms[i].ChangeDutyCycle(duty) time.sleep(0.5) for pwm in pwms: pwm.ChangeDutyCycle(0)
try: while True: setangles([0, 0, 0, 0]) time.sleep(1) setangles([90, 90, 90, 90]) time.sleep(1) set_angles([180, 180, 180, 180]) time.sleep(1) except KeyboardInterrupt: for pwm in pwms: pwm.stop() GPIO.cleanup()
Using a Servo Driver Board (PCA9685)
If you need 8+ servos or want to offload PWM generation from the Pi’s CPU, use an I2C-based PCA9685 servo driver. It can control 16 servos with just two I2C pins (SDA/SCL) and has its own clock for jitter-free PWM.
Wiring for PCA9685:
PCA9685 VCC → Raspberry Pi 5V PCA9685 GND → Raspberry Pi GND PCA9685 SDA → Raspberry Pi GPIO2 (Pin 3) PCA9685 SCL → Raspberry Pi GPIO3 (Pin 5)
Install the library:
bash pip3 install adafruit-circuitpython-servokit
Code example:
python from adafruit_servokit import ServoKit kit = ServoKit(channels=16)
Set servo 0 to 90 degrees
kit.servo[0].angle = 90
Set servo 1 to 45 degrees
kit.servo[1].angle = 45
The PCA9685 handles all the PWM timing, leaving your Pi free for other tasks.
Smooth Motion: Adding Acceleration and Deceleration
A servo that snaps instantly from 0° to 180° can be jarring and may cause mechanical stress. For more natural motion, increment the angle in small steps with a delay.
Simple Smooth Sweep Function
python import RPi.GPIO as GPIO import time
SERVOPIN = 18 GPIO.setmode(GPIO.BCM) GPIO.setup(SERVOPIN, GPIO.OUT) pwm = GPIO.PWM(SERVO_PIN, 50) pwm.start(0)
def smoothmove(startangle, endangle, steps=50, delay=0.02): anglerange = endangle - startangle for i in range(steps + 1): currentangle = startangle + (anglerange * i / steps) duty = 2.5 + (currentangle / 180.0) * 10.0 pwm.ChangeDutyCycle(duty) time.sleep(delay) pwm.ChangeDutyCycle(0)
try: smoothmove(0, 180, steps=100, delay=0.01) time.sleep(1) smoothmove(180, 0, steps=100, delay=0.01) finally: pwm.stop() GPIO.cleanup()
You can also implement easing functions (ease-in, ease-out) by varying the step size:
python import math
def easeinout(t): # t goes from 0 to 1, returns eased value return t * t * (3 - 2 * t) # smoothstep
def smoothmoveeased(startangle, endangle, duration=2.0, fps=50): totalsteps = int(duration * fps) for step in range(totalsteps + 1): t = step / totalsteps easedt = easeinout(t) currentangle = startangle + (endangle - startangle) * easedt duty = 2.5 + (currentangle / 180.0) * 10.0 pwm.ChangeDutyCycle(duty) time.sleep(1.0 / fps) pwm.ChangeDutyCycle(0)
Continuous Rotation Servos (360° Modification)
Standard SG90 servos are limited to 180°, but you can modify them for continuous rotation (useful for wheels or conveyor belts). Alternatively, you can buy pre-modified continuous rotation servos.
How Continuous Rotation Works
Instead of position, the PWM signal controls speed and direction:
- 1 ms pulse: Full speed clockwise
- 1.5 ms pulse: Stop
- 2 ms pulse: Full speed counterclockwise
The duty cycle between these values gives proportional speed.
Code for Continuous Rotation
python import RPi.GPIO as GPIO import time
SERVOPIN = 18 GPIO.setmode(GPIO.BCM) GPIO.setup(SERVOPIN, GPIO.OUT) pwm = GPIO.PWM(SERVO_PIN, 50) pwm.start(0)
def set_speed(speed): # speed: -1 (full CW) to 1 (full CCW), 0 = stop duty = 7.5 + (speed * 5.0) # 7.5 is center (stop) pwm.ChangeDutyCycle(duty)
try: setspeed(0.5) # Half speed CCW time.sleep(2) setspeed(-0.3) # Slow CW time.sleep(2) set_speed(0) # Stop finally: pwm.stop() GPIO.cleanup()
Note: Continuous rotation servos often have a trim potentiometer to fine-tune the “stop” position. You may need to adjust it with a small screwdriver until the servo stops completely at 1.5 ms.
Advanced: Using Hardware PWM for Jitter-Free Control
Software PWM works well, but if you need ultra-smooth motion (e.g., for a camera gimbal), hardware PWM is better. The Raspberry Pi has hardware PWM on GPIO12 (PWM0) and GPIO18 (PWM0 on some models), GPIO13 (PWM1), and GPIO19 (PWM1).
Enabling Hardware PWM
You need to modify /boot/config.txt to enable the PWM overlays:
bash sudo nano /boot/config.txt
Add these lines:
dtoverlay=pwm-2chan
Reboot:
bash sudo reboot
Now you can use hardware PWM with the pigpio library, which is much more precise.
Using pigpio for Hardware PWM
Install pigpio:
bash sudo apt install pigpio sudo systemctl enable pigpiod sudo systemctl start pigpiod
Then in Python:
python import pigpio import time
SERVO_PIN = 18 pi = pigpio.pi()
def setangle(angle): # Convert angle to pulse width in microseconds pulsewidth = 500 + (angle / 180.0) * 2000 # 500 to 2500 µs pi.setservopulsewidth(SERVOPIN, pulsewidth)
try: setangle(0) time.sleep(1) setangle(90) time.sleep(1) setangle(180) time.sleep(1) finally: pi.setservopulsewidth(SERVOPIN, 0) # Stop signal pi.stop()
The pigpio library uses the Pi’s dedicated PWM hardware, resulting in jitter-free motion even under heavy CPU load.
Troubleshooting Common SG90 Issues
Even with correct wiring, you may run into problems. Here are the most common ones and how to fix them.
Servo Jitters or Vibrates
- Cause: PWM signal is left on continuously.
Fix: Set duty cycle to 0 after moving, or use
pi.set_servo_pulsewidth(pin, 0)in pigpio.Cause: Power supply voltage drops under load.
- Fix: Add a 470 µF capacitor across power and ground near the servo. Use a separate 5V supply for multiple servos.
Servo Doesn’t Move Full Range
- Cause: Pulse width range is wrong for your specific servo.
- Fix: Calibrate min and max duty cycles as described earlier. Some SG90s need 2.0–12.0 duty cycle, others need 2.5–12.5.
Servo Moves Erratically or Not at All
- Cause: Ground not shared between Pi and external power supply.
Fix: Connect the GND of your external supply to a GND pin on the Pi.
Cause: PWM frequency is not 50 Hz.
- Fix: Double-check that
GPIO.PWM(pin, 50)uses 50 Hz.
Raspberry Pi Reboots When Servo Moves
- Cause: Current spike exceeding the Pi’s power supply capacity.
- Fix: Use a higher-rated power adapter (2.5A minimum for Pi + servos). Add a capacitor. Use external servo power.
Real-World Project: Pan-Tilt Camera Mount
Let’s put everything together into a practical project: a two-servo pan-tilt mount for a Raspberry Pi camera.
Hardware Needed
- 2 × SG90 servos
- Pan-tilt bracket (plastic 2-DOF mount)
- Raspberry Pi Camera Module
- External 5V power supply (2A minimum)
- 470 µF capacitor
Wiring
- Servo 1 (pan, horizontal): GPIO18
- Servo 2 (tilt, vertical): GPIO19
- Both servos powered from external 5V supply
- Common ground
Python Code
python import RPi.GPIO as GPIO import time
PANPIN = 18 TILTPIN = 19
GPIO.setmode(GPIO.BCM) GPIO.setup(PANPIN, GPIO.OUT) GPIO.setup(TILTPIN, GPIO.OUT)
panpwm = GPIO.PWM(PANPIN, 50) tiltpwm = GPIO.PWM(TILTPIN, 50) panpwm.start(0) tiltpwm.start(0)
def move_servo(pwm, angle): duty = 2.5 + (angle / 180.0) * 10.0 pwm.ChangeDutyCycle(duty) time.sleep(0.3) pwm.ChangeDutyCycle(0)
def lookat(panangle, tiltangle): moveservo(panpwm, panangle) moveservo(tiltpwm, tilt_angle)
Example: scan left to right
try: for pan in range(0, 181, 10): lookat(pan, 90) time.sleep(0.5) for pan in range(180, -1, -10): lookat(pan, 90) time.sleep(0.5) finally: panpwm.stop() tiltpwm.stop() GPIO.cleanup()
You can extend this by adding keyboard control or integrating with OpenCV face tracking.
Final Tips for Reliable Servo Control
- Always use a separate power supply for 3+ servos. The Pi’s 5V rail is not designed for high-current loads.
- Add a heat sink to the servo driver chip if using PCA9685 with many servos.
- Test with a multimeter to verify your external supply is outputting a stable 5V under load.
- Use shielded cables for long runs (over 30 cm) to reduce noise on the signal line.
- Store your calibration values in a config file so you can swap servos without re-tuning.
The SG90 micro servo is a fantastic component that bridges the gap between simple blinking LEDs and complex robotics. With the Raspberry Pi’s flexibility and the techniques covered here, you can add smooth, precise motion to almost any project. Whether you’re building a robot arm, a weather station with a moving sensor, or a tiny animatronic figure, the SG90 will serve you well.
Copyright Statement:
Author: Micro Servo Motor
Link: https://microservomotor.com/micro-servo-motor-with-raspberry-pi/control-sg90-servo-raspberry-pi.htm
Source: Micro Servo Motor
The copyright of this article belongs to the author. Reproduction is not allowed without permission.
Recommended Blog
- How to Calibrate Servo Motors for Precise Control with Raspberry Pi
- Using Raspberry Pi to Control Servo Motors in Automated Packaging and Labeling Systems
- How to Control Servo Motors Using Raspberry Pi and the pigpio Library for Precision Robotics
- Implementing Servo Motors in Raspberry Pi-Based Automated Sorting and Packaging Systems
- Creating a Servo-Controlled Automated Trash Can Lid with Raspberry Pi
- How to Use Raspberry Pi to Control Servo Motors in Automated Assembly Lines
- Implementing Servo Motors in Raspberry Pi-Based Automated Sorting and Packaging Systems
- Implementing Servo Motors in Raspberry Pi-Based Automated Sorting Lines
- Building a Servo-Powered Automated Sorting Robot with Raspberry Pi and Sensors
- Integrating Multiple Servo Motors with Raspberry Pi
About Us
- Lucas Bennett
- Welcome to my blog!
Hot Blog
- How to Build a Remote-Controlled Car with a 3D-Printed Chassis
- How Gear Teeth Design Influences Servo Motor Operation
- The Impact of Gear Materials on Servo Motor Heat Generation
- Micro Servo Motor Explained: A Simple Guide for Students
- Using Raspberry Pi to Control Servo Motors in Automated Packaging and Labeling Systems
- How to Implement PWM in Arduino Projects
- The Role of Gear Materials in High-Torque Servo Motors
- DIY Servo-Powered Blinds: Step-by-Step Guide
- The Future of Micro Servo Motors: Insights from Leading Brands
- Continuous Rotation Micro Servos for Wheeled Robots
Latest Blog
- Why Servo Motors Rely on Narrow Pulse Ranges
- How to Control SG90 Servo Motors Using Raspberry Pi
- Specification Declared Speed (s/60°) vs Real Time Tests
- Building a Micro Servo Robotic Arm with a Servo Motor Driver
- Using a Webcam to Control Your Micro Servo Robotic Arm
- How Cloud Computing is Impacting Micro Servo Motor Applications
- Brush vs Coreless Motor: How Motor Type Affects Spec Sheets
- Building a Micro Servo Robotic Arm for Pick and Place Applications
- Enhancing Precision in Robotics with Micro Servo Motors
- Common Causes of Motor Overheating and How to Prevent Them
- Micro Servo Motors in Automated Welding Systems
- The Mechanism of Continuous Adjustment in Micro Servo Motors
- Micro Servo Motors in Autonomous Robotics: Current Applications
- PWM Control in Robotics: A Practical Guide
- Maintenance Schedules for Micro Servos on Working Drones
- How to Implement Active Cooling Systems in Motors
- Micro Servo vs Standard Servo: Start-Up Torque Performance
- The Impact of Quantum Computing on Micro Servo Motor Design
- How to Build a Remote-Controlled Car with a Smartphone App
- How to Design Motors for Optimal Heat Dissipation