Admin 12 Jun 2026 04:48

 

Raspberry Pi Python PWM Servo Motor Control

Introduction to PWM and Servo Motors

Pulse Width Modulation (PWM) is a technique used to control analog devices using digital signals. With a Raspberry Pi, PWM can be implemented to precisely control servo motors, which are essential components in robotics, automation, and many DIY electronics projects.

servo motor has three wires: power (usually red), ground (black or brown), and control (yellow, orange, or white). The control wire receives PWM signals that determine the motor's position. By manipulating the timing of these signals, you can make the servo rotate to specific angles with high accuracy.

Understanding PWM for Servo Control

Most standard hobby servos require a PWM signal with the following characteristics:

  • Frequency of 50Hz (a 20ms period)
  • Pulse width typically between 1ms to 2ms for the standard rotation range (usually 0-180 degrees)

The relationship between pulse width and servo position is:

  • 1ms pulse = 0 degrees (or maximum counter-clockwise)
  • 1.5ms pulse = 90 degrees (or center position)
  • 2ms pulse = 180 degrees (or maximum clockwise)

Note: Different servo models may have slightly different pulse width and range specifications. Always check your servo's datasheet for the exact values.

Hardware Setup

To connect a servo motor to your Raspberry Pi:

  1. Connect the red (power) wire to a 5V GPIO pin (pins 2 or 4)
  2. Connect the black or brown (ground) wire to any ground pin (pins 6, 9, 14, 20, etc.)
  3. Connect the yellow, orange, or white (control) wire to a GPIO pin that supports PWM (GPIO 12, 13, 18, or 19)

Important: Servo motors can draw significant current. For small servos in simple projects, you can power them directly from the Pi. For more powerful servos or multiple servos, use an external power supply to avoid damaging your Raspberry Pi.

Software Requirements

Before coding, ensure your Raspberry Pi has the necessary software:

  1. Update your system: sudo apt update && sudo apt upgrade
  2. Install the RPi.GPIO library: sudo apt install python3-rpi.gpio
  3. For more precise PWM control, install the pigpio library: sudo apt install pigpio
  4. Enable and start the pigpio daemon:
    • sudo systemctl enable pigpiod
    • sudo systemctl start pigpiod

Basic Servo Control with RPi.GPIO

Here's a simple Python script to control a servo using the RPi.GPIO library:

import RPi.GPIO as GPIOimport time# Set the GPIO modeGPIO.setmode(GPIO.BCM)GPIO.setwarnings(False)# Define the servo GPIO pinservo_pin = 18# Setup the servo pin as an outputGPIO.setup(servo_pin, GPIO.OUT)# Create PWM instance with 50Hz frequencyservo = GPIO.PWM(servo_pin, 50)# Initialize servo at neutral position (90 degrees)servo.start(7.5)  # 7.5% duty cycle for neutral positiontry:    while True:        # Move to 0 degrees        print("Moving to 0 degrees")        servo.ChangeDutyCycle(2.5)  # ~2.5% duty cycle for 0 degrees        time.sleep(1)                # Move to 90 degrees        print("Moving to 90 degrees")        servo.ChangeDutyCycle(7.5)  # ~7.5% duty cycle for 90 degrees        time.sleep(1)                # Move to 180 degrees        print("Moving to 180 degrees")        servo.ChangeDutyCycle(12.5)  # ~12.5% duty cycle for 180 degrees        time.sleep(1)                # Return to neutral position        print("Moving back to center")        servo.ChangeDutyCycle(7.5)        time.sleep(1)        except KeyboardInterrupt:    print("Stopping...")# Clean up on exitservo.stop()GPIO.cleanup()print("Cleanup completed")

Advanced Control with pigpio Library

The pigpio library offers more precise PWM control by utilizing hardware features:

import pigpioimport time# Connect to pigpio daemonpi = pigpio.pi()# Check if connection was successfulif not pi.connected:    print("Error: Could not connect to pigpio daemon")    exit(1)# Define the servo pinservo_pin = 18# Function to move servo to angledef move_servo(pin, angle):    # Convert angle to pulse width (in microseconds)    # Standard servos use 1000-2000us range for 0-180 degrees    # Some servos might use different ranges, adjust as needed    pulse_width = 1000 + (angle * 1000 / 180)    pi.set_servo_pulsewidth(pin, pulse_width)try:    while True:        # Move to 0 degrees        print("Moving to 0 degrees")        move_servo(servo_pin, 0)        time.sleep(1)                # Move to 90 degrees        print("Moving to 90 degrees")        move_servo(servo_pin, 90)        time.sleep(1)                # Move to 180 degrees        print("Moving to 180 degrees")        move_servo(servo_pin, 180)        time.sleep(1)                # Sweep back and forth        print("Sweeping from 0 to 180 degrees")        for angle in range(0, 181):            move_servo(servo_pin, angle)            time.sleep(0.01)                print("Sweeping from 180 to 0 degrees")        for angle in range(180, -1, -1):            move_servo(servo_pin, angle)            time.sleep(0.01)        except KeyboardInterrupt:    print("\nStopping...")# Turn off servo and disconnect on exitpi.set_servo_pulsewidth(servo_pin, 0)pi.stop()print("Cleanup completed")

Creating a Servo Controller Class

For more complex projects, creating a dedicated class for servo control can help organize your code:

import pigpioimport timeclass ServoController:    def __init__(self, pin, min_pulse=1000, max_pulse=2000):        """        Initialize servo controller                Args:            pin: GPIO pin number            min_pulse: Minimum pulse width in microseconds (default: 1000)            max_pulse: Maximum pulse width in microseconds (default: 2000)        """        self.pin = pin        self.pi = pigpio.pi()        self.min_pulse = min_pulse        self.max_pulse = max_pulse                if not self.pi.connected:            raise ConnectionError("Could not connect to pigpio daemon")        def move_to_angle(self, angle):        """        Move servo to specific angle                Args:            angle: Angle in degrees (0-180)        """        # Clamp angle to valid range        angle = max(0, min(180, angle))                # Convert angle to pulse width        pulse_width = self.min_pulse + (angle * (self.max_pulse - self.min_pulse) / 180)                # Set pulse width        self.pi.set_servo_pulsewidth(self.pin, pulse_width)        def sweep(self, start_angle=0, end_angle=180, delay=0.01):        """        Sweep servo between angles                Args:            start_angle: Starting angle in degrees            end_angle: Ending angle in degrees            delay: Delay between steps in seconds        """        # Determine direction        if start_angle < end_angle:            angles = range(start_angle, end_angle + 1)        else:            angles = range(start_angle, end_angle - 1, -1)                # Sweep through angles        for angle in angles:            self.move_to_angle(angle)            time.sleep(delay)        def cleanup(self):        """Turn off servo and disconnect from pigpio"""        self.pi.set_servo_pulsewidth(self.pin, 0)        self.pi.stop()# Example usageif __name__ == "__main__":    try:        # Initialize servo on GPIO 18        servo = ServoController(pin=18)                # Move to middle position        print("Moving to center position (90 degrees)")        servo.move_to_angle(90)        time.sleep(1)                # Sweep from 0 to 180 degrees        print("Sweeping from 0 to 180 degrees")        servo.sweep(0, 180, 0.02)        time.sleep(1)                # Sweep back from 180 to 0 degrees        print("Sweeping from 180 back to 0 degrees")        servo.sweep(180, 0, 0.02)        time.sleep(1)                # Move to specific angles        print("Moving to specific angles: 45, 90, 135 degrees")        servo.move_to_angle(45)        time.sleep(1)        servo.move_to_angle(90)        time.sleep(1)        servo.move_to_angle(135)        time.sleep(1)            except KeyboardInterrupt:        print("\nStopping...")        servo.cleanup()        print("Cleanup completed")

Common Issues and Troubleshooting

Servo Jittering or Not Moving Smoothly

  • Check power supply - servos might malfunction if not receiving adequate current
  • Use the pigpio library for more precise PWM signals
  • Add a capacitor across the servo's power and ground pins to reduce electrical noise
  • Ensure the control wire is properly connected and not picking up interference

Servo Not Moving Full Range

  • Adjust the min_pulse and max_pulse values to match your servo's specifications
  • Some servos have limited rotation ranges (e.g., 90) rather than full 180 rotation
  • Check if mechanical constraints are limiting the servo's movement
  • Verify that your PWM duty cycle calculations are correct

Advanced Techniques

Smooth Motion with Interpolation

For smoother servo movements, you can use interpolation to calculate intermediate positions:

import timeimport mathdef smooth_move(pin, start_angle, end_angle, duration, move_func):    """    Move servo smoothly from start to end angle over specified duration        Args:        pin: GPIO pin number        start_angle: Starting angle in degrees        end_angle: Target angle in degrees        duration: Movement duration in seconds        move_func: Function to move servo to a given angle    """    num_steps = 20  # Number of intermediate positions    step_time = duration / num_steps        for step in range(num_steps + 1):        # Calculate interpolation factor (0 to 1)        t = step / num_steps                # Apply easing function for smoother motion (ease-in-out cubic)        t_smooth = t * t * (3 - 2 * t)                # Calculate current angle        current_angle = start_angle + (end_angle - start_angle) * t_smooth                # Move to current angle        move_func(pin, current_angle)        time.sleep(step_time)# Example usage with pigpiodef move_servo(pin, angle):    pulse_width = 1000 + (angle * 1000 / 180)    pi.set_servo_pulsewidth(pin, pulse_width)# Move smoothly from 0 to 180 over 2 secondssmooth_move(18, 0, 180, 2.0, move_servo)

Multiple Servo Control

When controlling multiple servos, you can extend the ServoController class or manage multiple instances:

import pigpioimport time# Connect to pigpio daemonpi = pigpio.pi()if not pi.connected:    print("Error: Could not connect to pigpio daemon")    exit(1)class MultiServoController:    def __init__(self):        self.pi = pigpio.pi()        self.servos = {}                if not self.pi.connected:            raise ConnectionError("Could not connect to pigpio daemon")        def add_servo(self, servo_id, pin, min_pulse=1000, max_pulse=2000):        """        Add a servo to the controller                Args:            servo_id: Identifier for the servo            pin: GPIO pin number            min_pulse: Minimum pulse width in microseconds            max_pulse: Maximum pulse width in microseconds        """        self.servos[servo_id] = {            'pin': pin,            'min_pulse': min_pulse,            'max_pulse': max_pulse        }        def move_servo(self, servo_id, angle):        """        Move a specific servo to an angle                Args:            servo_id: Identifier for the servo            angle: Target angle in degrees        """        if servo_id not in self.servos:            raise ValueError(f"Servo {servo_id} not found")                servo = self.servos[servo_id]                # Clamp angle to valid range        angle = max(0, min(180, angle))                # Convert angle to pulse width        pulse_width = servo['min_pulse'] + (angle * (servo['max_pulse'] - servo['min_pulse']) / 180)                # Set pulse width        self.pi.set_servo_pulsewidth(servo['pin'], pulse_width)        def cleanup(self):        """Turn off all servos and disconnect"""        for servo_id, servo in self.servos.items():            self.pi.set_servo_pulsewidth(servo['pin'], 0)        self.pi.stop()# Example usagetry:    multi_servo = MultiServoController()        # Add two servos    multi_servo.add_servo('pan', 18)   # Pan servo on pin 18    multi_servo.add_servo('tilt', 19)  # Tilt servo on pin 19        # Move servos independently    multi_servo.move_servo('pan', 90)    multi_servo.move_servo('tilt', 90)    time.sleep(1)        # Create a simple pattern    for i in range(5):        # Pan left and right        multi_servo.move_servo('pan', 45)        time.sleep(0.5)        multi_servo.move_servo('pan', 135)        time.sleep(0.5)                # Tilt up and down        multi_servo.move_servo('tilt', 60)        time.sleep(0.5)        multi_servo.move_servo('tilt', 120)        time.sleep(0.5)            # Return to center    multi_servo.move_servo('pan', 90)    multi_servo.move_servo('tilt', 90)    time.sleep(1)    except KeyboardInterrupt:    print("\nStopping...")    finally:    multi_servo.cleanup()    print("Cleanup completed")

Applications and Project Ideas

With servo motor control on your Raspberry Pi, you can build various projects:

  • Robotic Arms: Multiple servos working together to create articulated movement.
  • Camera Mounts: Pan-and-tilt systems for surveillance, photography, or time-lapse videos.
  • Smart Locks: Servo-controlled latch mechanisms for automated door locking.
  • Automated Pet Feeders: Precise dispensing of food at scheduled times.
  • Drawing Robots: X-Y plotters using two servos for creating drawings.
  • Weather Stations: Servo-controlled directional sensors or moving parts.

Conclusion

Controlling servo motors with PWM on a Raspberry Pi opens up numerous possibilities for interactive and automated projects. By understanding the fundamentals of PWM and servo operation, you can create precise movement control with relatively simple Python code.

As you become more comfortable with basic servo control, consider exploring more advanced techniques like sensor integration, computer vision, and multi-servo coordination. The combination of the Raspberry Pi's computing power and the precision of servo motors provides a powerful platform for creating complex electronic systems and robotic applications.

Reference Files For Raspberry Pi Python PWM Servo Motor Control
Screenshoot
File Name
raspberrypi_pwm_servo.pptx

File Size
0.20 MB

File Type
PPTX

File Site
Description
This file is just a reference file for Raspberry Pi Python PWM Servo Motor Control. Does not guarantee that the specific things you want are included in it.
Direct download (wait 10 seconds)

Raspberry Pi Python PWM Servo Motor Control and Reference File Download Link


admin
Admin
2026-06-12 04:48:11

Arduino Servo Motor PWM Frequency and Reference File Download Link


admin
Admin
2026-06-12 15:46:15

Speed Control Of DC Motor By Pulse Width Modulation (PWM) and Reference File Download Link


admin
Admin
2026-06-12 08:16:11

Gourmet Peach Raspberry Pie and Reference File Download Link


admin
Admin
2026-06-08 04:46:06

Speed Control Of A Three Phase Induction Motor Using Field Oriented Control and Reference...


admin
Admin
2026-06-09 06:38:21