Using hardware PWM/CLK to get exact timings on a Raspberry Pi

Introduction

This might not be a common issue, that hobbyists run into when creating their projects, because usually the software PWM, offered by the raspberry pi’s RPi.GPIO-Module, is exact enough for dimming some lights or controlling dc-motors. But for real-time and time-critical applications, this is actually an issue:

The pulses created by the RPi.GPIO Python-Library are not very exact (usually something like +/-100µs):

Bildschirmfoto 2016-05-06 um 19.34.25
Image 1: You can see the difference in the pulses. One takes way longer, than the other

This happens because of the way software runs on a computer. Without digging too deep into the topic of scheduling and multi-tasking let’s just say: the linux OS on the pi has to give itself and other applications, running on the pi, some time too for processing. So your e.g. Python script, which is doing the PWM work, will just get some time for doing it’s stuff before an other app gets it’s runtime. After an undefined period of time (might even take some ms to seconds) the OS will give your PWM-Program the focus again and it can generate some waveform output. And this is the problem: The time is undefined. It might take 1µs and the pulse gets accurate or it might take 127µs and the pulse is malformed. As mentioned above: This is absolutely no issue when dealing with e.g. LEDs. You won’t notice a difference, because the PWM-Signal is used to generate an average voltage.

Exact timings

But what if you need the signal to be very precise? Let’s say with an inaccuracy of max.
+/- 1µs for e.g. transmitting data? You’ll have to use a hardware generated Signal. Luckily the pi can even do this! And with the help of well written high-level libraries you can easily create accurate PWM-Signals with software without having to know anything about the ARM-CPU or about PWM-Registers or about low-level programming. If you want to learn more about the CPU and it’s peripherals anyways, you can read the official documentation: BCM2835-ARM-Peripherals.

After digging a bit into the documentation and after a google search, reading lots of forum posts, i found an easy to use gpio library for the pi. I’ve heard about it before, but I somehow totally forgot about it over the last years. I’m talking about the pigpio library. At this point I want to mention that there are many other good libraries out there, but I liked this the most. Another good one is WiringPi from drogon. He seems to be very active in the Raspberry Pi forums, and the command line tools, that come with WiringPi, are great (you can create pwm-signals from the command-line), but I’ve found the WiringPi-Library to be poorly documented (Not everything, but examples are missing everywhere in the api and also max/min values, etc.). Therefore I’m using pigpio instead.

What I want to create, is this signal:

wunschsignal
Image 2: This is the Signal we want (Ch1)

As you can see, it is a 22.26kHz rectangular wave with a duty cycle of roughly 59% (If you are not familiar with the term duty cycle or PWM in general, watch this video). After taking a quick look into the pigio API i found this method:

Bildschirmfoto 2016-05-06 um 19.57.41.png
Image 3: A snapshot of the pigpio API

With this method you can create a signal just like the one in Image 2. I’ve quickly written the following lines of code in python:

import pigpio
import time

GPIO = pigpio.pi()

#
# pigpio uses BROADCOM PIN NUMBERING !!!
#

HSYNC = 18 # Physical Pin #12

# Set the GPIO-Mode to ALT5 for HW-PWM
GPIO.set_mode(HSYNC, pigpio.ALT5)

# Start the signal generation
# 22,26kHz, 59% Duty Cycle
GPIO.hardware_PWM(HSYNC, 22260, 590000)

try:
        # Keep the script running until Ctrl + C are pressed
        while True:
                time.sleep(1)
except KeyboardInterrupt:
        pass

# Pull down the GPIO-Pin and cleanup with stop()
GPIO.write(HSYNC, 0)
GPIO.stop()

This script simply uses the pigpio library to create the desired waveform. The infinite while loop is not necessary, but I like to keep the program open and to pull the gpio to zero when ending the script with Ctrl + C. So let’s check, what this script does on the GPIO-Pin:

wiringpi.png
Image 4: The result

It looks like I didn’t measure a different signal to the one seen in image 2. The two signals are absolutely the same.

Conclusion

If you need to generate exact pulses (or use a hardware clock signal) with the raspberry pi: It is absolutely possible with low level programming or the use of a good library, but sometimes using the internal clock signals is not precise enough, so be aware of that!

comment-banner

Advertisements

5 thoughts on “Using hardware PWM/CLK to get exact timings on a Raspberry Pi

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s