Skip to main content

A comprehensive Python library for controlling servo motors using gpiod on Linux systems

Project description

Servo Control with gpiod

A comprehensive Python implementation for controlling servo motors using the gpiod library on Raspberry Pi and other Linux systems with GPIO support.

Features

  • Full PWM Control: Software-generated PWM signals using gpiod
  • Flexible Configuration: Customizable frequency, pulse width ranges, and angle limits
  • Multiple Control Methods: Angle-based, pulse width direct, and percentage-based control
  • Thread-Safe: Concurrent access protection with threading locks
  • Sweep Functions: Smooth servo movement between positions
  • Calibration Support: Custom pulse width calibration for different servo types
  • Context Manager: Automatic cleanup with with statement
  • Comprehensive Testing: Full test suite with mock hardware support
  • Error Handling: Custom exceptions and robust error management

Servo Control with gpiod

A comprehensive Python implementation for controlling servo motors using the gpiod library on Raspberry Pi and other Linux systems with GPIO support.


Requirements

PyPI Version PyPI Status Python Version PyPI Downloads License GitHub Stars GitHub Issues GitHub Forks Build and Test Publish to PyPI Code Size

Useful Links

Servo Class

Constructor

Servo(pin, chip="gpiochip4", frequency=50, min_pulse_width=1.0, max_pulse_width=2.0, min_angle=0, max_angle=90)
Parameter Type Default Description
pin int required GPIO pin number for servo signal
chip str "gpiochip4" GPIO chip name
frequency int 50 PWM frequency in Hz
min_pulse_width float 1.0 Minimum pulse width in ms
max_pulse_width float 2.0 Maximum pulse width in ms
min_angle int 0 Minimum servo angle in degrees
max_angle int 90 Maximum servo angle in degrees

Methods

Method Description
set_angle(angle) Set specific angle (degrees)
set_angle_rad(angle) Set specific angle (radians)
center() Move to center position
move_to_min() Move to minimum angle
move_to_max() Move to maximum angle
set_pulse_width(width_ms) Set pulse width directly (ms)
set_position_percent(percent) Set position as percentage (0-100%)
sweep(start, end, duration, steps=50) Smooth sweep between angles over duration
get_current_angle() Returns current angle
get_current_pulse_width() Returns current pulse width (ms)
get_current_position_percent() Returns current position (%)
is_running() Returns True if PWM is active
start() Start PWM signal generation
stop() Stop PWM signal generation
cleanup() Release GPIO resources
calibrate(min_pulse, max_pulse) Calibrate pulse width range
  • Python 3.12.3+
  • gpiod library (version 2.0+)
  • Linux system with GPIO support (Raspberry Pi, etc.)

Installation

From PyPI (Recommended)

pip install python-servo-gpiod

From Source

git clone https://github.com/Svndsn/python-servo.git
cd python-servo
pip install -e .

Quick Start

from python_servo_gpiod import Servo

# Create and use servo with context manager (recommended)
with Servo(pin=18) as servo:
    servo.set_angle(90)    # Move to 90 degrees
    servo.center()         # Move to center position
    servo.sweep(0, 90, 3) # Sweep from 0 to 90 degrees over 3 seconds

# Manual control
servo = Servo(pin=18)
servo.start()              # Start PWM
servo.set_angle(45)        # Set angle
servo.stop()               # Stop PWM
servo.cleanup()            # Clean up resources

API Reference

Servo Class

Constructor

Servo(pin, chip="gpiochip4", frequency=50, 
      min_pulse_width=1.0, max_pulse_width=2.0, 
      min_angle=0, max_angle=90)

Parameters:

  • pin: GPIO pin number for servo signal
  • chip: GPIO chip (default: "gpiochip4")
  • frequency: PWM frequency in Hz (default: 50Hz)
  • min_pulse_width: Minimum pulse width in ms (default: 1.0ms)
  • max_pulse_width: Maximum pulse width in ms (default: 2.0ms)
  • min_angle: Minimum servo angle in degrees (default: 0°)
  • max_angle: Maximum servo angle in degrees (default: 90°)

Control Methods

Angle Control:

servo.set_angle(angle)              # Set specific angle
servo.center()                      # Move to center position
servo.move_to_min()                 # Move to minimum angle
servo.move_to_max()                 # Move to maximum angle

Pulse Width Control:

servo.set_pulse_width(width_ms)     # Set pulse width directly (ms)

Percentage Control:

servo.set_position_percent(percent) # Set position as percentage (0-100%)

Movement Functions:

servo.sweep(start_angle, end_angle, duration, steps=50)
# Smooth sweep between angles over specified duration

Status Methods

servo.get_current_angle()           # Returns current angle
servo.get_current_pulse_width()     # Returns current pulse width (ms)
servo.get_current_position_percent() # Returns current position (%)
servo.is_running()                  # Returns True if PWM is active

PWM Control

servo.start()                       # Start PWM signal generation
servo.stop()                        # Stop PWM signal generation
servo.cleanup()                     # Release GPIO resources

Calibration

servo.calibrate(min_pulse, max_pulse) # Calibrate pulse width range

Examples

Basic Usage

from python_servo_gpiod import Servo
import time

# Initialize servo on GPIO pin 18
servo = Servo(pin=18)
servo.start()

# Test different positions
servo.set_angle(0)      # 0 degrees
time.sleep(1)
servo.set_angle(45)     # 45 degrees  
time.sleep(1)
servo.set_angle(90)    # 90 degrees
time.sleep(1)

servo.cleanup()

Custom Servo Configuration

# Configure for a servo with different specifications
servo = Servo(
    pin=20,
    frequency=60,           # 60Hz instead of 50Hz
    min_pulse_width=0.5,    # 0.5ms minimum pulse
    max_pulse_width=2.5,    # 2.5ms maximum pulse
    min_angle=-90,          # -90 to +90 degree range
    max_angle=90
)

Percentage Control

with Servo(pin=18) as servo:
    servo.set_position_percent(0)    # Minimum position
    time.sleep(1)
    servo.set_position_percent(50)   # Center position
    time.sleep(1)
    servo.set_position_percent(100)  # Maximum position

Smooth Sweeping

with Servo(pin=18) as servo:
    # Sweep from 0 to 90 degrees over 5 seconds
    servo.sweep(0, 90, duration=5.0, steps=100)
    
    # Sweep back with fewer steps (less smooth)
    servo.sweep(90, 0, duration=3.0, steps=30)

Calibration for Custom Servos

servo = Servo(pin=18)
# Calibrate for a servo that needs 0.8ms to 2.2ms pulse widths
servo.calibrate(0.8, 2.2)
servo.start()

# Now angle control uses the calibrated pulse widths
servo.set_angle(90)  # Uses 1.5ms pulse width

Testing

Run Unit Tests

python test_servo.py --verbose

Hardware Testing

# WARNING: Only run with real servo connected!
python test_servo.py --hardware

Demo Scripts

# Simple demonstration
python demo.py simple

# Interactive control
python demo.py interactive

# Performance benchmark
python demo.py benchmark

PWM Signal Details

The servo generates PWM signals with the following characteristics:

  • Default Frequency: 50Hz (20ms period)
  • Pulse Width Range: 1.0ms to 2.0ms
  • Resolution: Limited by Python's time.sleep() precision
  • Duty Cycle: 5% (1ms) to 10% (2ms) at 50Hz

Timing Calculations

  • 0° position: 1.0ms pulse width (5% duty cycle)
  • 45° position: 1.5ms pulse width (7.5% duty cycle)
  • 90° position: 2.0ms pulse width (10% duty cycle)

Thread Safety

The Servo class is thread-safe for concurrent access:

  • Multiple threads can safely call angle/position setting methods
  • PWM generation runs in a separate daemon thread
  • Thread locks protect shared state variables

Error Handling

The implementation includes comprehensive error handling:

try:
    servo = Servo(pin=18)
    servo.start()
    servo.set_angle(270)  # Invalid angle
except ServoError as e:
    print(f"Servo error: {e}")
except Exception as e:
    print(f"Unexpected error: {e}")
finally:
    servo.cleanup()

Common error conditions:

  • GPIO initialization failures
  • Invalid angle ranges
  • Invalid pulse width values
  • PWM already running when starting
  • Hardware access permissions

Hardware Connections

Standard Servo Connection

Servo Wire Colors:
- Red:  +5V power supply
- Brown/Black: Ground (GND)
- Orange: Signal (connect to GPIO pin)

Limitations

  1. Software PWM: Uses software timing, less precise than hardware PWM
  2. CPU Usage: PWM generation consumes CPU cycles
  3. Timing Jitter: Python's threading may introduce small timing variations
  4. Single Servo: Each instance controls one servo (multiple instances needed for multiple servos)

Performance

Typical performance characteristics:

  • Command Response: < 1ms for angle/position changes
  • PWM Frequency: Stable 50Hz ±1Hz
  • Pulse Width Accuracy: ±50μs (depending on system load)
  • CPU Usage: ~1-2% per active servo on Raspberry Pi 5

License

This project is licensed under the MIT License.

See LICENSE.md for full license details.

Contributing

Feel free to submit issues, improvements, or extensions to this servo control implementation.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

python_servo_gpiod-1.1.0.tar.gz (17.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

python_servo_gpiod-1.1.0-py3-none-any.whl (14.7 kB view details)

Uploaded Python 3

File details

Details for the file python_servo_gpiod-1.1.0.tar.gz.

File metadata

  • Download URL: python_servo_gpiod-1.1.0.tar.gz
  • Upload date:
  • Size: 17.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.12.9

File hashes

Hashes for python_servo_gpiod-1.1.0.tar.gz
Algorithm Hash digest
SHA256 05f62c70aaa881b876c2acccfebd7ac714f3fc6913f42e29f1601198db7c79cd
MD5 60ca28c43762a9c7ea1300e630e2b562
BLAKE2b-256 1b79e0b421dca37977ffc3dcd800991de4526952acfec8d9e5868e2f750c7d8f

See more details on using hashes here.

Provenance

The following attestation bundles were made for python_servo_gpiod-1.1.0.tar.gz:

Publisher: publish.yml on Svndsn/python-servo

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file python_servo_gpiod-1.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for python_servo_gpiod-1.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 1038257c516bbbbc161a13c769475b5078e6f80130f655b697cdb96c62186fd9
MD5 19591d1880e8602c72c6acf145694ee9
BLAKE2b-256 3459a18ac07c66deba0c6bdf4f5fb4b619862e1639fff55e70258b7baf8fc772

See more details on using hashes here.

Provenance

The following attestation bundles were made for python_servo_gpiod-1.1.0-py3-none-any.whl:

Publisher: publish.yml on Svndsn/python-servo

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page