Adafruit Blinka supports PWMOut! This means you can easily pulse LEDs and control servos from your Raspberry Pi using any GPIO pin! This page will walk you through wiring up an LED and a servo, and provide an example for each.

Update Adafruit Blinka

Before getting started, make sure you're running the latest version of Adafruit Blinka. If you have not already installed it, run the following:

pip3 install adafruit-blinka

If you've previously installed it, you should run a pip3 update:

pip3 install --upgrade adafruit-blinka

Once you're certain that you are running the latest version of Adafruit Blinka, you can continue!

Supported Pins

PWMOut is supported on all GPIO pins on the Raspberry Pi! They are independent, and each can have a different frequency and duty cycle.

PWM - LEDs

This example will show you how to use PWM to pulse fade an LED.

First, wire up the LED to the Raspberry Pi.

  • LED - (negative) to Pi GND
  • LED + (positive) to 470Ω resistor
  • 470Ω resistor to Pi GPIO5

Double-check you have the right wires connected to the right location, it can be tough to keep track of pins as there are forty of them!

No additional libraries are needed, so we can go straight on to the example code.

Run the following code:

import time
import board
import pulseio

led = pulseio.PWMOut(board.D5, frequency=5000, duty_cycle=0)

while True:
    for i in range(100):
        # PWM LED up and down
        if i < 50:
            led.duty_cycle = int(i * 2 * 65535 / 100)  # Up
        else:
            led.duty_cycle = 65535 - int((i - 50) * 2 * 65535 / 100)  # Down
        time.sleep(0.01)

Verify that the LED is pulsing. If not, check that it's wired to GPIO #5, the resistor is installed correctly, and you have a ground wire to the Raspberry Pi.

Type control-C to quit.

Servo Control

In order to use servos, we take advantage of pulseio. You have two options. You can use the raw pulseio calls to set the frequency to 50 Hz and then set the pulse widths. Or, you can use adafruit_motor which manages servos for you quite nicely.

This section will cover both options.

Install adafruit_motor by running pip3 install adafruit-circuitpython-motor

First, wire up a servo to your Raspberry Pi:

  • Servo power (red wire) to Raspberry Pi 5V
  • Servo ground (black/brown wire) to Raspberry Pi ground
  • Servo signal (yellow/white wire) to Raspberry Pi GPIO5 

pulseio Servo Control

Run the following code:

import time
import board
import pulseio

# Initialize PWM output for the servo (on pin D5):
servo = pulseio.PWMOut(board.D5, frequency=50)


# Create a function to simplify setting PWM duty cycle for the servo:
def servo_duty_cycle(pulse_ms, frequency=50):
    period_ms = 1.0 / frequency * 1000.0
    duty_cycle = int(pulse_ms / (period_ms / 65535.0))
    return duty_cycle


# Main loop will run forever moving between 1.0 and 2.0 mS long pulses:
while True:
    servo.duty_cycle = servo_duty_cycle(1.0)
    time.sleep(1.0)
    servo.duty_cycle = servo_duty_cycle(2.0)
    time.sleep(1.0)

The servo should sweep back and forth repeatedly. If it does not, verify your wiring matches the diagram above.

Type control-C to quit.

adafruit_motor Servo Control

Run the following code:

import time
import board
import pulseio
from adafruit_motor import servo

# create a PWMOut object on Pin D5.
pwm = pulseio.PWMOut(board.D5, duty_cycle=2 ** 15,  frequency=50)

# Create a servo object.
servo = servo.Servo(pwm)

while True:
    for angle in range(0, 180, 5):  # 0 - 180 degrees, 5 degrees at a time.
        servo.angle = angle
        time.sleep(0.05)
    for angle in range(180, 0, -5): # 180 - 0 degrees, 5 degrees at a time.
        servo.angle = angle
        time.sleep(0.05)

The servo should sweep back and forth in steps. If it does not, verify your wiring matches the diagram above.

Type control-C to quit.

This guide was first published on Jun 30, 2018. It was last updated on Jun 30, 2018.
This page (PWM Outputs & Servos) was last updated on Oct 24, 2020.