How to Control Servo Motors Using Raspberry Pi and the WiringPi Library

Micro Servo Motor with Raspberry Pi / Visits:6

Micro servo motors are the unsung heroes of the modern maker movement. From animating robot arms and DIY camera gimbals to controlling small valves in automated gardens, these compact, precise devices translate digital commands into physical movement. While the Arduino often gets the spotlight for servo control, the Raspberry Pi offers a powerful, Linux-based alternative, capable of integrating complex logic, computer vision, and internet connectivity into your projects. This guide dives deep into the art and science of controlling micro servos using a Raspberry Pi and the robust, if now legacy, WiringPi library.

Why the Raspberry Pi and Micro Servos Are a Perfect Match

The Raspberry Pi is more than just a small computer; it's a gateway to sophisticated physical computing. Unlike microcontrollers, the Pi runs a full operating system, allowing you to write programs in high-level languages like Python, C, or C++ while managing multiple processes. Micro servos, particularly the ubiquitous SG90, are ideal partners for the Pi. They are lightweight, require relatively low current (often under 500mA when moving, which a good 5V external supply can handle for a few servos), and provide a useful range of motion—typically 180 degrees.

The challenge, and the core of this tutorial, lies in the Raspberry Pi's lack of a true analog output. Servos are controlled not by voltage level, but by a Pulse Width Modulation (PWM) signal. This is where the WiringPi library shines. It provides a straightforward, C-based API to generate precise, timed pulses on the Pi's GPIO pins, abstracting away much of the complex low-level hardware interaction.

Understanding the Pulse: How Micro Servos Work

Before writing a single line of code, it's crucial to grasp the signal you need to generate. A standard micro servo like the SG90 expects a pulse every 20 milliseconds (a 50Hz frequency). The width of this pulse determines the servo's angular position.

  • A 1.0 ms pulse typically drives the servo to its 0-degree position (full left or counter-clockwise, depending on model).
  • A 1.5 ms pulse centers the servo at 90 degrees.
  • A 2.0 ms pulse moves it to its 180-degree position (full right or clockwise).

It's a linear relationship: pulse width between 1.0ms and 2.0ms yields a proportional angle between 0 and 180 degrees. This pulse train must be consistent; the servo's internal circuitry constantly adjusts to match the received pulse width.

Setting Up Your Hardware and Software

Essential Components and Wiring

You will need: 1. A Raspberry Pi (any model with GPIO pins, tested here on a Pi 3B+). 2. A micro servo motor (SG90 or equivalent). 3. A 5V power supply (a dedicated UBEC or a stable 5V from a bench supply is best for more than one servo. Do not power a servo directly from the Pi's 5V pin for anything beyond light testing). 4. Jumper wires (female-to-male for connecting to the servo).

Critical Wiring Diagram: * Servo Yellow/Orange Wire (Signal): Connect to a GPIO pin on the Pi, e.g., GPIO 18 (Physical pin 12). This is the PWM control line. * Servo Red Wire (Power - 5V): Connect to your external 5V power supply's positive terminal. The Pi's ground and the external supply's ground must be connected. * Servo Brown/Black Wire (Ground): Connect to the common ground between the Pi and the external power supply.

Power Advisory: A moving servo can cause significant current spikes. These spikes can cause your Pi to brown-out and reset if powered from the same source. Always use a separate, regulated 5V supply for the servo(s), with the grounds tied together.

Installing and Configuring WiringPi

While WiringPi is deprecated for new projects, it remains a stable and excellent tool for learning precise timing control. It may already be installed on your Raspberry Pi OS (Legacy) image. To check and install:

bash

Check if WiringPi is installed and its version

gpio -v

If not installed, you can clone and build it from its archive

git clone https://github.com/WiringPi/WiringPi cd WiringPi ./build

The library includes both a command-line tool (gpio) and a C library (wiringPi). We will focus on using the C library for programmatic control.

Programming Servo Control in C with WiringPi

Let's write a C program that gives you complete control over your micro servo. We'll start with a basic example and build up to more complex movements.

Basic Code Structure: Initialization and Sweep

Create a file named servo_basic.c:

c

include <wiringPi.h>

include <stdio.h>

include <stdlib.h>

// Define our servo pin. We use WiringPi pin numbering. // WiringPi Pin 1 corresponds to BCM_GPIO 18.

define SERVO_PIN 1

// Constants for pulse timing (based on 100µs increments, common in WiringPi servo code) // These values are typical for a 180-degree servo. YOU MAY NEED TO CALIBRATE.

define PWM_FREQ 50 // Hz

define PWM_RANGE 200 // This number times 100µs = 20ms period

define MINPULSEWIDTH 10 // 10 * 100µs = 1.0ms (0 degrees)

define MAXPULSEWIDTH 30 // 30 * 100µs = 2.0ms (180 degrees)

void setup() { if (wiringPiSetup() == -1) { printf("WiringPi setup failed!\n"); exit(1); }

pinMode(SERVO_PIN, PWM_OUTPUT); // Set the pin to PWM mode pwmSetMode(PWM_MODE_MS); // Use Mark-Space mode, which is correct for servos pwmSetRange(PWM_RANGE); pwmSetClock(192); // This clock divisor gives a 50Hz signal on Pi. (19.2MHz / (192 * 2000)) ~= 50Hz 

}

void setServoAngle(int angle) { // Constrain angle to 0-180 if (angle < 0) angle = 0; if (angle > 180) angle = 180;

// Map the angle (0-180) to the pulse width (MIN_PULSE_WIDTH - MAX_PULSE_WIDTH) int pulseWidth = MIN_PULSE_WIDTH + ((angle * (MAX_PULSE_WIDTH - MIN_PULSE_WIDTH)) / 180); pwmWrite(SERVO_PIN, pulseWidth); delay(100); // Give the servo time to move 

}

int main(void) { setup(); printf("Raspberry Pi Micro Servo Control Started.\n");

// Perform a smooth sweep from 0 to 180 degrees and back while (1) {     for (int angle = 0; angle <= 180; angle += 5) {         setServoAngle(angle);         printf("Angle set to: %d degrees\n", angle);     }     for (int angle = 180; angle >= 0; angle -= 5) {         setServoAngle(angle);         printf("Angle set to: %d degrees\n", angle);     } } return 0; 

}

To compile and run this program: bash gcc -o servo_basic servo_basic.c -lwiringPi sudo ./servo_basic Note: sudo is often required for accessing the GPIO hardware.

Calibration and Fine-Tuning Your Servo

Not all servos are created equal. The MIN_PULSE_WIDTH and MAX_PULSE_WIDTH values in the code are theoretical. Your specific servo might have a slightly different range.

How to Calibrate: 1. Set the pulse width to the theoretical center (e.g., 20, which is 1.5ms). Does the servo shaft point to 90 degrees? 2. If not, adjust the values. Use the gpio command for quick testing: bash # Switch pin to PWM mode gpio mode 1 pwm gpio pwm-ms gpio pwmc 192 gpio pwmr 2000 # Test a value (e.g., 150 for ~1.5ms) gpio pwm 1 150 Experiment with different values to find the true minimum and maximum pulse widths your servo responds to without straining. Update the constants in your C code accordingly.

Advanced Techniques and Project Integration

Creating Smooth, Non-Blocking Movements

The delay() function in the sweep example is blocking. For a responsive system (e.g., a robot that needs to listen for commands while moving), you must manage timing without blocking.

Example: Non-Blocking Sweep using millis()-like logic c

include <wiringPi.h>

include <stdio.h>

define SERVO_PIN 1

unsigned long previousMillis = 0; int currentAngle = 0; int targetAngle = 180; int sweepDirection = 1; // 1 for increasing, -1 for decreasing

void updateServoSmoothly() { unsigned long currentMillis = millis();

// Update angle every 20ms for smooth motion if (currentMillis - previousMillis >= 20) {     previousMillis = currentMillis;      if (currentAngle != targetAngle) {         currentAngle += sweepDirection;         // Use your setServoAngle function here (without its delay)         int pulseWidth = 10 + ((currentAngle * 20) / 180);         pwmWrite(SERVO_PIN, pulseWidth);     } else {         // Change direction when target is reached         sweepDirection *= -1;         targetAngle = (targetAngle == 180) ? 0 : 180;     } } 

}

int main(void) { // ... setup code ... while (1) { updateServoSmoothly(); // You can do other tasks here, like reading sensors or network calls // delay(1); // Small delay to prevent CPU overuse } }

Building a Web-Controlled Servo Pan-Tilt

Combine your servo knowledge with a simple web server to create a remote-controlled camera platform.

Conceptual Steps: 1. Use Two Servos: One for pan (horizontal), one for tilt (vertical). Connect each to its own GPIO pin (e.g., GPIO 18 and GPIO 13). 2. Write a CGI Program: In C, using WiringPi for servo control, create a program that reads query parameters (e.g., ?pan=90&tilt=45) and sets the servo angles accordingly. 3. Lightweight Web Server: Use a simple server like lighttpd and configure it to execute your CGI program. 4. HTML Interface: Create a webpage with sliders or buttons that send GET requests to your CGI endpoint.

This project demonstrates the Raspberry Pi's unique strength: bridging the physical world of motors with the networked world of the internet.

Troubleshooting Common Issues

  • Servo Jitters or Vibrates: This is often caused by electrical noise or an unstable power supply. Ensure your power supply is adequate and your grounds are solidly connected. Adding a large capacitor (e.g., 470µF to 1000µF) across the servo's power and ground leads, close to the servo, can smooth out spikes.
  • Servo Doesn't Move / Pi Crashes: You are likely drawing too much current through the Pi. Immediately switch to an external 5V power supply for the servo.
  • Incomplete Range of Motion: Your pulse width constants need calibration. Adjust MIN_PULSE_WIDTH and MAX_PULSE_WIDTH as described in the calibration section.
  • "wiringPi.h: No such file or directory": The WiringPi development package is not installed. Ensure you built the library correctly.

While newer libraries like pigpio offer more features and active development, WiringPi provides a direct, no-frills path to understanding the fundamental timing required for servo control. Its simplicity is its didactic strength. By mastering these principles—PWM signal generation, power management, and non-blocking code—you equip yourself to integrate the dynamic motion of micro servos into virtually any Raspberry Pi project, from simple automations to complex robotic systems.

Copyright Statement:

Author: Micro Servo Motor

Link: https://microservomotor.com/micro-servo-motor-with-raspberry-pi/wiringpi-servo-control-raspberry-pi.htm

Source: Micro Servo Motor

The copyright of this article belongs to the author. Reproduction is not allowed without permission.

About Us

Lucas Bennett avatar
Lucas Bennett
Welcome to my blog!

Tags