PWM Outputs & Servos

Some Linux boards, like the Coral, have PWM outputs. You can use these to pulse LEDs to dim them, or color mix, control motor speeds with a motor driver, or even hobby servos!

Supported Pins

The Coral only has 3 PWM pins:

  • Pin #33 is PWM1
  • Pin #32 is PWM2
  • Pin #15  is PWM3

These are independent PWM outputs, each can have a different frequency and duty cycle

You can check that the 3 PWM's are enabled with ls /sys/class/pwm/

PWM with Fixed Frequency - LEDs

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

Wire up an LED like before, but this time to PWM3 and GND

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

However, we recommend running a pip3 update!

pip3 install --upgrade adafruit_blinka

Download: file
import time
import board
import pulseio

led = pulseio.PWMOut(board.PWM3, 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 the LED is blinking. If not, check that it's wired to GPIO #15, the resistor is installed correctly, and you have a Ground wire to the Coral.

Type Control-C to quit

Servo Control

In order to use servos, we take advantage of pulseio. Now, in theory, you could just use the raw pulseio calls to set the frequency to 50 Hz and then set the pulse widths. But we would rather make it a little more elegant and easy!

So, instead we will use adafruit_motor which manages servos for you quite nicely

Install it with pip3 install adafruit-circuitpython-motor

The PWM output from the Coral is only 2.5V peak, and not very strong, so you need to buffer it, we recommend using an HC4050 or similar low cost level shifter/buffer. Wire VCC and GND to 5V and GND on the Coral, and then the PWM output goes into one of the 6 inputs of the '4050.

  • Connect the servo's brown or black ground wire to ground
  • Connect the servo's red power wire to 5V power, USB power is good for a servo or two. For more than that, you'll need an external battery pack. Do not use 3.3V for powering a servo!
  • Connect the servo's yellow or white signal wire to the control/data pin. In this case we're using the shifted PWM3

74LVC245 - Breadboard Friendly 8-bit Logic Level Shifter

PRODUCT ID: 735
Most of our customers love using the Arduino for prototyping, design and invention but find themselves stuck when trying to connect the Arduino to the latest sensors, displays,...
$1.50
IN STOCK

Micro servo

PRODUCT ID: 169
Tiny little servo can rotate approximately 180 degrees (90 in each direction), and works just like the standard kinds you're used to but smaller. You can use any servo code,...
$5.95
IN STOCK

Standard servo - TowerPro SG-5010

PRODUCT ID: 155
This high-torque standard servo can rotate approximately 180 degrees (90 in each direction). You can use any servo code, hardware or library to control these servos. Good for beginners...
$12.00
IN STOCK
Download: file
import time
import board
import pulseio
from adafruit_motor import servo

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

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

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

PWM Output with Variable Frequency - Buzzers

This example will show you how to beep a piezo buzzer at different PWM frequencies

Connect a common Piezo buzzer to PWM3 and GND. Don't connect a speaker unless you have an amplifier - the pins on the Coral can only drive small buzzers!

Piezo Buzzer

PRODUCT ID: 160
Piezo buzzers are used for making beeps, tones and alerts. This one is petite but loud! Drive it with 3-30V peak-to-peak square wave. To use, connect one pin to ground (either one) and...
$1.50
IN STOCK
Download: file
import time
import board
import pulseio

piezo = pulseio.PWMOut(board.PWM3, duty_cycle=0, frequency=440, variable_frequency=True)

while True:
    for f in (262, 294, 330, 349, 392, 440, 494, 523):
        print(f)
        piezo.frequency = f
        piezo.duty_cycle = 65536 // 2  # On 50%
        time.sleep(0.25)  # On for 1/4 second
        piezo.duty_cycle = 0  # Off
        time.sleep(0.05)  # Pause between notes
    time.sleep(0.5)

If you want to make lots of tones, we recommend using the tone helper functions in simpleio

Install it with pip3 install adafruit-circuitpython-simpleio and then follow this guide page

The output of the PWM pins isn't very strong, so if you want louder beeps, use the '4050 level shifting arrangement above

This guide was first published on May 12, 2019. It was last updated on May 12, 2019. This page (PWM Outputs & Servos) was last updated on Aug 13, 2019.