Project 5: PWM Servo and Motor Control Lab

Control servo position and DC motor speed safely using PWM, while measuring timing jitter under Linux.

Quick Reference

Attribute Value
Difficulty Intermediate
Time Estimate 1–2 weekends
Main Programming Language Python (Alternatives: C, Rust, Go)
Alternative Programming Languages C, Rust, Go
Coolness Level High
Business Potential Medium
Prerequisites GPIO basics, power electronics basics
Key Topics PWM duty cycle, motor drivers, power isolation, timing jitter

1. Learning Objectives

By completing this project, you will:

  1. Generate stable PWM for a servo and a DC motor.
  2. Explain why motor drivers and separate power are mandatory.
  3. Measure PWM jitter under CPU load on Linux.
  4. Implement safe startup and shutdown behavior.

2. All Theory Needed (Per-Concept Breakdown)

Concept 1: PWM Signal Generation and Safe Motor Driving on Linux

Fundamentals

Pulse-width modulation (PWM) controls average power by switching a signal on and off at a fixed frequency while varying the duty cycle. A servo expects a repeating pulse with a specific period (typically 20 ms) and a pulse width that maps to angle (e.g., 1.0–2.0 ms). A DC motor uses PWM duty cycle to control speed, but it draws far more current than a GPIO pin can supply. That’s why you must use a motor driver and a separate power rail. On Linux, timing is not perfectly deterministic; PWM generated in software can jitter. Understanding PWM behavior, power isolation, and timing constraints is the foundation for reliable motor control.

Deep Dive into the concept

PWM is fundamentally about time: a signal toggles between high and low at a fixed frequency, and the fraction of time it stays high determines average power. For a DC motor, the motor’s inertia and inductance smooth the pulses, so the duty cycle approximates speed. For a servo, the duty cycle is interpreted differently: the servo decodes pulse width, not average power. That means your PWM frequency and pulse width must be stable. A typical hobby servo expects a 50 Hz signal with pulse widths between 1–2 ms. If the pulse width jitters, the servo will twitch or buzz.

The Raspberry Pi Zero 2 W has limited hardware PWM channels. When you use software PWM, the Linux scheduler introduces jitter because other processes can preempt your loop. Even hardware PWM is affected by clock configuration. The key is to use hardware PWM when possible and to measure jitter under load. Tools like stress-ng can create CPU load while you log pulse timing. Jitter is not just a theoretical concern; it causes servo instability and inconsistent motor speed, especially at low duty cycles.

Power is the other critical aspect. GPIO pins can source only a few milliamps, while motors often draw hundreds of milliamps or more, especially at startup (stall current). Driving a motor directly from GPIO can reset the Pi or damage the pin. A motor driver (like an H-bridge or MOSFET) isolates logic from power. You must provide a separate power supply for motors and connect grounds together to provide a reference. Flyback diodes or driver modules with built-in protection are essential to absorb the inductive kick when motors are turned off.

For servos, the signal line is logic-level and can be connected to GPIO, but the servo power should come from a separate 5V supply. For DC motors, use a driver board that can handle the motor current and allows PWM input. The Pi’s 5V rail should not be used for high-current motor loads on the Zero 2 W; use an external supply and verify that the ground is common to avoid floating references.

A safe control design includes: a defined neutral state, a gradual ramp for DC motor duty cycle, and a failsafe stop on error. For servos, clamp pulse width to safe values to prevent overdriving. For motors, implement a ramp to avoid sudden inrush. You should also monitor the Pi’s voltage or logs for undervoltage warnings; these indicate power instability and require re-wiring or a better supply.

How this fit on projects

This concept is applied in §3 (requirements), §4 (architecture), and §5.10 (implementation). It also informs Project 15 (latency profiling).

Definitions & key terms

  • PWM: Pulse-width modulation.
  • Duty cycle: Percentage of time the signal is high.
  • Servo pulse width: Duration of the high pulse that maps to angle.
  • H-bridge: Motor driver that controls direction and speed.
  • Stall current: Maximum current draw when motor is blocked.

Mental model diagram (ASCII)

PWM:  _----_----_----_----_
Duty: 25%   50%   75%

Pi GPIO -> Driver -> Motor (separate power)

How it works (step-by-step, with invariants and failure modes)

  1. Configure PWM output (frequency + duty cycle).
  2. Drive servo pulse width or motor duty cycle.
  3. Measure jitter and adjust strategy.
  4. Use driver and external power.

Failure modes:

  • Direct motor on GPIO -> brownouts.
  • Software PWM jitter -> servo twitch.
  • No flyback protection -> voltage spikes.

Minimal concrete example

pwm = GPIO.PWM(pin, 50)  # 50 Hz for servo
pwm.start(7.5)           # neutral ~1.5ms

Common misconceptions

  • “PWM always equals speed.” Servo PWM maps to position, not speed.
  • “GPIO can drive motors.” It cannot; use drivers.
  • “Linux timing is precise enough.” It isn’t for hard real-time control.

Check-your-understanding questions

  1. Why do servos use 50 Hz pulses?
  2. What happens if you power a motor from the Pi’s 5V rail?
  3. How does jitter affect servo position?

Check-your-understanding answers

  1. The servo expects a 20 ms period for its internal control loop.
  2. The Pi can brown out or reset due to current spikes.
  3. The servo interprets jitter as changing position, causing twitching.

Real-world applications

  • Camera pan/tilt rigs, small robots, and actuator control.

Where you’ll apply it

  • This project: §3.2, §4.1, §5.10.
  • Other projects: Project 15.

References

  • “Making Embedded Systems” — timing and control.
  • Motor driver datasheets.

Key insights

PWM is easy to generate but hard to make stable under a non-real-time OS.

Summary

Safe motor control requires both correct PWM timing and correct power isolation.

Homework/Exercises to practice the concept

  1. Measure servo pulse width with a logic analyzer.
  2. Compare jitter under idle vs stress-ng load.
  3. Measure motor current at startup.

Solutions to the homework/exercises

  1. Pulse widths should stay within 1–2 ms.
  2. Jitter increases under load; document worst case.
  3. Stall current is highest at startup; ensure driver can handle it.

3. Project Specification

3.1 What You Will Build

A PWM control lab that moves a servo to fixed angles and varies DC motor speed with safe power isolation.

3.2 Functional Requirements

  1. Servo reaches 0°, 90°, 180° using calibrated pulse widths.
  2. DC motor speed increases smoothly via PWM ramp.
  3. Jitter is measured and logged under load.

3.3 Non-Functional Requirements

  • Performance: Motor ramp completes within 2 seconds.
  • Reliability: No Pi resets during motor operation.
  • Usability: Clear logs and repeatable tests.

3.4 Example Usage / Output

$ ./motor_lab
Servo set to 0 deg
Servo set to 90 deg
Motor speed: 30%
Motor speed: 60%
Motor stopped

3.5 Data Formats / Schemas / Protocols

CSV jitter log:

TIMESTAMP,PULSE_US,DELTA_US
2026-01-01T10:30:00Z,1500,20

3.6 Edge Cases

  • Servo hits mechanical stops.
  • Motor draws too much current.
  • CPU load causes jitter.

3.7 Real World Outcome

Servo and motor behave predictably, and jitter data explains timing limits.

3.7.1 How to Run (Copy/Paste)

python3 motor_lab.py --servo 18 --motor 13 --ramp 2.0

3.7.2 Golden Path Demo (Deterministic)

export FIXED_TIME="2026-01-01T10:30:00Z"
python3 motor_lab.py --simulate --angles "0,90,180" --duty "30,60"

Expected output:

[2026-01-01T10:30:00Z] Servo 0 deg
[2026-01-01T10:30:00Z] Motor 30%

3.7.3 Failure Demo (Deterministic)

python3 motor_lab.py --motor 13 --simulate --current-limit 1000

Expected output:

[ERROR] Motor current exceeds limit

Exit code: 51

3.7.4 CLI Exit Codes

  • 0: Success
  • 50: PWM init failure
  • 51: Overcurrent detected

4. Solution Architecture

4.1 High-Level Design

PWM Generator -> Servo Driver
PWM Generator -> Motor Driver -> DC Motor

4.2 Key Components

| Component | Responsibility | Key Decisions | |—|—|—| | PWM Generator | Generate stable PWM | Hardware vs software | | Servo Controller | Map angle to pulse | Calibration table | | Motor Controller | Ramp duty cycle | Ramp rate | | Logger | Record jitter | Sampling interval |

4.3 Data Structures (No Full Code)

servo_map = {0:1000, 90:1500, 180:2000}

4.4 Algorithm Overview

Key Algorithm: PWM Ramp

  1. Start at 0% duty.
  2. Increase duty in steps.
  3. Hold at target.

Complexity Analysis:

  • Time: O(n) steps
  • Space: O(1)

5. Implementation Guide

5.1 Development Environment Setup

sudo apt-get install -y python3-rpi.gpio

5.2 Project Structure

project-root/
├── motor_lab.py
├── pwm_utils.py
└── README.md

5.3 The Core Question You’re Answering

“How do you control physical motion with timing signals from a non-real-time OS?”

5.4 Concepts You Must Understand First

  1. PWM duty cycle and servo pulse widths.
  2. Power isolation and motor driver usage.
  3. Timing jitter and Linux scheduling.

5.5 Questions to Guide Your Design

  1. How will you prevent the Pi from brownout?
  2. How will you measure jitter without skewing results?

5.6 Thinking Exercise

Calculate the pulse width needed for a 45° servo position.

5.7 The Interview Questions They’ll Ask

  1. Why can’t GPIO drive motors directly?
  2. How does jitter affect servo position?
  3. What is stall current?

5.8 Hints in Layers

Hint 1: Start with a servo only.

Hint 2: Add motor driver and separate power.

Hint 3: Add jitter logging with time.monotonic().

5.9 Books That Will Help

| Topic | Book | Chapter | |—|—|—| | PWM timing | Making Embedded Systems | Ch. 5 | | Power electronics | Practical Electronics for Inventors | Ch. 3 |

5.10 Implementation Phases

Phase 1: Servo Calibration (3 hours)

  • Map pulse width to angle.

Phase 2: Motor Control (4 hours)

  • Add driver and ramp duty cycle.

Phase 3: Jitter Logging (3 hours)

  • Stress CPU and log timing.

5.11 Key Implementation Decisions

| Decision | Options | Recommendation | Rationale | |—|—|—|—| | PWM source | Hardware / Software | Hardware if available | Lower jitter | | Motor power | Pi 5V / External | External | Avoid brownouts |


6. Testing Strategy

6.1 Test Categories

| Category | Purpose | Examples | |—|—|—| | Unit Tests | Angle mapping | 0°, 90°, 180° | | Integration Tests | Full motion | Servo + motor | | Edge Case Tests | Overcurrent | Simulated current spike |

6.2 Critical Test Cases

  1. Servo reaches 90° within tolerance.
  2. Motor ramp completes without reset.
  3. Jitter stays below 2 ms under idle.

6.3 Test Data

Angles: 0, 90, 180
Duty steps: 10%, 30%, 60%

7. Common Pitfalls & Debugging

7.1 Frequent Mistakes

| Pitfall | Symptom | Solution | |—|—|—| | Motor on 5V rail | Pi resets | Use external supply | | Wrong servo range | Servo buzz | Clamp pulse width | | High jitter | Twitching | Reduce load or hardware PWM |

7.2 Debugging Strategies

  • Use a logic analyzer to observe PWM.
  • Monitor dmesg for undervoltage warnings.

7.3 Performance Traps

  • Software PWM with heavy logging introduces jitter.

8. Extensions & Challenges

8.1 Beginner Extensions

  • Add a second servo.

8.2 Intermediate Extensions

  • Add acceleration profiles for motor ramp.

8.3 Advanced Extensions

  • Implement closed-loop speed control with encoder feedback.

9. Real-World Connections

9.1 Industry Applications

  • Robotics, camera gimbals, and actuator control.
  • pigpio hardware PWM library.

9.3 Interview Relevance

  • Power isolation and PWM control are common embedded topics.

10. Resources

10.1 Essential Reading

  • Servo and motor driver datasheets.

10.2 Video Resources

  • PWM and motor control tutorials.

10.3 Tools & Documentation

  • pigpio docs for hardware PWM.

11. Self-Assessment Checklist

11.1 Understanding

  • I can explain PWM duty cycle and servo pulse width mapping.
  • I can explain why motor drivers are required.

11.2 Implementation

  • Servo and motor control are stable.
  • Jitter is measured and logged.

11.3 Growth

  • I can discuss timing jitter in an interview.

12. Submission / Completion Criteria

Minimum Viable Completion:

  • Servo moves to two positions reliably.

Full Completion:

  • Servo + motor control with safe power isolation.

Excellence (Going Above & Beyond):

  • Closed-loop speed control with encoder feedback.