How to Control Servo Motor with Raspberry Pi: Simple Guide
To control a servo motor with a Raspberry Pi, use the
RPi.GPIO library to send PWM signals to the servo's control pin. Set the PWM frequency to 50Hz and adjust the duty cycle to move the servo to the desired angle.Syntax
Use the RPi.GPIO library to set up PWM on a GPIO pin connected to the servo. The key steps are:
GPIO.setmode(GPIO.BCM): Use Broadcom pin numbering.GPIO.setup(pin, GPIO.OUT): Set the pin as output.pwm = GPIO.PWM(pin, frequency): Create PWM instance with 50Hz frequency.pwm.start(duty_cycle): Start PWM with initial duty cycle.pwm.ChangeDutyCycle(duty_cycle): Change servo angle by adjusting duty cycle.pwm.stop()andGPIO.cleanup(): Stop PWM and clean GPIO settings.
python
import RPi.GPIO as GPIO import time GPIO.setmode(GPIO.BCM) # Use BCM pin numbering servo_pin = 18 GPIO.setup(servo_pin, GPIO.OUT) pwm = GPIO.PWM(servo_pin, 50) # 50Hz frequency for servo pwm.start(7.5) # Neutral position (90 degrees) time.sleep(1) pwm.ChangeDutyCycle(12.5) # Move to 180 degrees time.sleep(1) pwm.stop() GPIO.cleanup()
Example
This example shows how to sweep a servo motor from 0 to 180 degrees and back using Raspberry Pi GPIO pin 18. It uses PWM signals with duty cycles mapped to servo angles.
python
import RPi.GPIO as GPIO import time def angle_to_duty_cycle(angle): # Map angle (0-180) to duty cycle (2.5-12.5) return 2.5 + (angle / 180.0) * 10 GPIO.setmode(GPIO.BCM) servo_pin = 18 GPIO.setup(servo_pin, GPIO.OUT) pwm = GPIO.PWM(servo_pin, 50) # 50Hz pwm.start(angle_to_duty_cycle(0)) # Start at 0 degrees try: while True: for angle in range(0, 181, 10): duty = angle_to_duty_cycle(angle) pwm.ChangeDutyCycle(duty) time.sleep(0.3) for angle in range(180, -1, -10): duty = angle_to_duty_cycle(angle) pwm.ChangeDutyCycle(duty) time.sleep(0.3) except KeyboardInterrupt: pass pwm.stop() GPIO.cleanup()
Output
No printed output; servo motor smoothly moves from 0° to 180° and back repeatedly until stopped.
Common Pitfalls
Common mistakes when controlling servos with Raspberry Pi include:
- Using incorrect GPIO pin numbering mode (BCM vs BOARD).
- Setting PWM frequency other than 50Hz, which can cause erratic servo movement.
- Not mapping servo angles correctly to duty cycle values (usually between 2.5% and 12.5%).
- Failing to provide enough power to the servo, causing jitter or no movement.
- Not cleaning up GPIO pins after use, which can cause warnings or errors on next run.
python
import RPi.GPIO as GPIO import time # Wrong: Using BOARD mode but specifying BCM pin number GPIO.setmode(GPIO.BOARD) servo_pin = 12 # BOARD pin 12 corresponds to BCM 18 GPIO.setup(servo_pin, GPIO.OUT) # Correct way: GPIO.setmode(GPIO.BCM) servo_pin = 18 GPIO.setup(servo_pin, GPIO.OUT)
Quick Reference
| Step | Description | Example Code |
|---|---|---|
| 1 | Set GPIO mode to BCM | GPIO.setmode(GPIO.BCM) |
| 2 | Set servo pin as output | GPIO.setup(18, GPIO.OUT) |
| 3 | Create PWM at 50Hz | pwm = GPIO.PWM(18, 50) |
| 4 | Start PWM with neutral duty cycle | pwm.start(7.5) |
| 5 | Change duty cycle to move servo | pwm.ChangeDutyCycle(12.5) |
| 6 | Stop PWM and cleanup | pwm.stop(); GPIO.cleanup() |
Key Takeaways
Use 50Hz PWM frequency to control servo motors with Raspberry Pi.
Map servo angles (0-180°) to duty cycles between 2.5% and 12.5%.
Always set GPIO mode to BCM when using BCM pin numbers.
Provide stable power to the servo to avoid jitter.
Clean up GPIO pins after your program ends to prevent warnings.