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.


Python Version License Build Status

Requirements

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)
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 .

Dependencies

# On Ubuntu/Debian systems, you may need:
sudo apt-get install -y libgpiod-dev python3-libgpiod

# Install Python package
pip install gpiod

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.0.0.tar.gz (10.7 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.0.0-py3-none-any.whl (6.2 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: python_servo_gpiod-1.0.0.tar.gz
  • Upload date:
  • Size: 10.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.3

File hashes

Hashes for python_servo_gpiod-1.0.0.tar.gz
Algorithm Hash digest
SHA256 f6f0a3e7c5c20273023778270c93e2687ce70f2725e3c861a58c8dc3bb5e26bf
MD5 6cdf7ca90a912f0186d85cda2f3fc320
BLAKE2b-256 81f679de223e6f7c0aea88a6348cfc97a13c8dd873775ecb28265a988132c622

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for python_servo_gpiod-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 0f7832933c222a22bbf3911b9aa325c191554fb76233854a086cf790425e8723
MD5 b50e700d3281abb116fe33e8232ffcc9
BLAKE2b-256 70c22f352d210dc5a1ea1e15ba826c1932b89294d2ee45ebf3a73dade893f61d

See more details on using hashes here.

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