Raspberry Pi: PWM Outputs with Python (Fading LED)

In this guide, you’ll learn how to generate PWM signals on the Raspberry Pi GPIOs. As an example, we’ll show you how to dim the brightness of an LED by changing the duty cycle over time. Generating PWM signals can also be useful to control other peripherals like servo motors.

Raspberry Pi PWM Outputs with Python Fading LED

Table of Contents

Throughout this tutorial, we’ll cover the following main topics:

  1. Introducing the Raspberry Pi GPIOs
  2. Introducing PWM
  3. Connect an LED to the Raspberry Pi
  4. Dim an LED with the Raspberry Pi using PWM

Prerequisites

Before continuing with this tutorial, check the following prerequisites.

  1. Get familiar with the Raspberry Pi board—if you’re not familiar with the Raspberry Pi, you can read our Raspberry Pi Getting Started Guide.
  2. You must know how to run and create Python files on your Raspberry Pi. We like to program our Raspberry Pi via SSH using an extension on VS Code. We have a detailed tutorial about that subject: Programming Raspberry Pi Remotely using VS Code (Remote-SSH).

First time controlling the Raspberry Pi Outputs? Get Started by controlling the Raspberry Pi Digital Outputs.

Introducing the Raspberry Pi GPIOs

GPIO stands for General Purpose Input Output pins and those allow you to connect and control electronic hardware, like LEDs, motors, and sensors to your Raspberry Pi.

Most models of Raspberry Pi boards have a double row of 40 GPIO pins. The layout of the pins is usually the same for most Raspberry Pi models.

Raspberry Pi  Pinout Random Nerd Tutorials
Raspberry Pi Pinout

There are two different ways to refer to a GPIO pin: its name (which is known as GPIO numbering or Broadcom numbering) or its corresponding pin physical number (which corresponds to the pin’s physical location on the header).

For example, GPIO 25 corresponds to pin 22 (see the picture above). Throughout this tutorial, we’ll refer to GPIO pins by their GPIO numbering (Broadcom numbering).

To learn more about the Raspberry Pi GPIOs, check the Raspberry Pi Pinout Guide: Raspberry Pi Pinout Guide: How to use the Raspberry Pi GPIOs?

Introducing PWM (Pulse-Width Modulation)

The Raspberry Pi GPIOs can be set either to output 0V or 3.3V (check this tutorial about the Raspberry Pi Digital Outputs), but they can’t output any voltages in between. However, you can output “fake” mid-level voltages using pulse‑width modulation (PWM), which is how you’ll produce varying levels of LED brightness for this project. PWM is also useful for other applications like varying the speed of DC motors, setting the position of a servo motor, and much more.

If you alternate an LED’s voltage between HIGH and LOW very fast, your eyes can’t keep up with the speed at which the LED switches on and off; you’ll simply see some gradations in brightness.

Fade LED with Pulse-Width Modulation (PWM)

That’s basically how PWM works — by producing an output that changes between HIGH and LOW at a very high frequency.

The duty cycle is the fraction of the time period at which LED is set to HIGH. The following figure illustrates how PWM works.

How Pulse-Width Modulation (PWM) works to fade LED
How PWM Works

A duty cycle of 50 percent results in 50 percent LED brightness, a duty cycle of 0 means the LED is fully off, and a duty cycle of 100 means the LED is fully on. Changing the duty cycle is how you produce different levels of brightness.

PWM Pins on the Raspberry Pi

The Raspberry Pi has 4 hardware PWM pins: GPIO 12GPIO 13GPIO 18GPIO 19.

You can have software PWM on all pins. You can pretty much choose any pin (except GPIO 0 and 1) to output PWM signals.

Wiring the Circuit

Wire an LED to one of the Raspberry Pi GPIOs. We’ll connect one LED to GPIO 14 (pin 8). You can use any other pins, except GPIO 0 and GPIO 1.

Here’s a list of components you need:

You can use the preceding links or go directly to MakerAdvisor.com/tools to find all the parts for your projects at the best price!

LED connected to Raspberry Pi GPIO14 Circuit Diagram

Dim an LED with Python on the Raspberry Pi

The gpiozero library provides a collection of interfaces for everyday components like LEDs, buttons, potentiometers, sensors, and much more.

So, instead of setting the GPIO properties to dim an LED, the gpiozero provides an interface called PWMLED with methods that are useful to control LEDs, including a method to produce PWM signals to vary the LED brightness.

Instead, you can also use the PWMOutputDevice interface that can be used to control other digital outputs with PWM. Let’s see how it works.

The gpiozero library should already be installed if you’re running Raspberry Pi OS — if not, you can run:

python3 -m pip gpiozero.

Python Script – PWM on Raspberry Pi GPIOs

Create a new python file on your Raspberry Pi called fade_led.py and copy the following code.

# Complete Project Details: https://RandomNerdTutorials.com/raspberry-pi-pwm-python/

from gpiozero import PWMLED
from time import sleep

led = PWMLED(14)

led.value = 1   #LED fully on
sleep(1)
led.value = 0.5  #LED half-brightness
sleep(1)
led.value = 0    #LED fully off
sleep(1)

try:
  # fade in and out forever
  while True:
    #fade in
    for duty_cycle in range(0, 100, 1):
      led.value = duty_cycle/100.0
      sleep(0.05)

    #fade out
    for duty_cycle in range(100, 0, -1):
      led.value = duty_cycle/100.0
      sleep(0.05)
      
except KeyboardInterrupt:
  print("Stop the program and turning off the LED")
  led.value = 0
  pass

View raw code

How the Code Works

Continue reading to learn how the code works.

Importing Libraries

First, you import the PWMLED component from the gpiozero library to control the GPIO that the LED is connected to. Then, you also need to import the sleep() function from the time module to create delays in the code.

from gpiozero import LED
from time import sleep

Instead of the PWMLED component, you can use the PWMOutputDevice component which works exactly the same.

from gpiozero import PWMOutputDevice

Declaring the PWM LED

Next, you create a PWMLED object called led that refers to GPIO 14, which is the GPIO that the LED is connected to. Change the number if you’re using another GPIO.

led = LED(14)

When you create and use this PWMLED object, your program knows that GPIO 14 is a PWM output that can produce PWM signals with different duty cycle values. After this declaration, you can use led to refer to your GPIO 14.

Note: if you want to use the PWMOutputDevice component instead, the declaration would be as follows:

led = PWMOutputDevice(14)

Note: if you want to use PWM signals to control DC and servo motors, the gpiozero provides the Motor, Servo, and AngularServo classes.

Control the LED Brightness

You can assign a specific brightness level to the LED by setting a specific number to the value property as follows:

led.value = 1   #LED fully on

Setting led.value to 1 corresponds to 100% duty cycle, and so the LED will be fully on.

To turn off the LED completely, you set the value to 0 (0% duty cycle).

led.value = 0    #LED fully off

For varying levels of duty cycle, and thus varying brightness levels, set the value to a number between 0 and 1.

led.value = 0.5  #LED half-brightness

Fade In an LED

The code then enters a loop where it gradually increases the duty cycle from 0% to 100% in steps of 1% with a delay of 0.05 seconds between each step. This causes the LED to fade in gradually.

for duty_cycle in range(0, 100, 1):
      led.value = duty_cycle/100.0
      sleep(0.05)

The range() function only accepts integer numbers, that’s why then we divide the duty_cycle variable by 100 so that we can have a value between 0 and 1.

The range(start, stop, increment) function in Python generates a sequence of numbers. It accepts as arguments the following:

  • start: the starting value of the sequence (inclusive)
  • stop: the last value of the sequence (exclusive)
  • step: increment between each value, the default is 1

Fade Out an LED

We do exactly the same thing to fade out the LED, but we change the arguments of the range() function so that it starts at 100 and decreases the duty cycle by 1 in each loop.

#fade out
for duty_cycle in range(100, 0, -1):
  led.value = duty_cycle/100.0
  sleep(0.05)

Try and Except with Keyboard Interrupt

To prevent staying with an LED on when you stop the execution of the program, we added a Try and Except statement. This will catch the KeyboardInterrupt exception, which is raised when you press Ctrl+C to stop the program. When this happens, we turn off the LED before exiting the program.

except KeyboardInterrupt:
  print("Stop the program and turning off the LED")
  led.value = 0
  pass

In summary…

1) To output PWM signals on the Raspberry Pi GPIOs, you can use the PWMLED or the PWMOutputDevice interface of the gpiozero library. You need to import it first like this:

from gpiozero import PWMLED

or like this:

from gpiozero import PWMOutputDevice

2) Define the GPIO that you want to control. Using the LED interface:

led = PWMLED(GPIO_NUMBER_OF_YOUR_CHOICE)

Or if you use the DigitalOutputDevice interface:

led = PWMOutputDevice(GPIO_NUMBER_OF_YOUR_CHOICE)

3) Set the duty cycle (change the LED brightness) with the value property:

led.value = 1   #LED fully on 
led.value = 0.5  #LED half-brightness
led.value = 0    #LED fully off

Demonstration

Save your python file. Then run it on your Raspberry Pi. Run the following command on the directory of your project file (use the name of your file):

python fade_led.py

The LED connected to GPIO 14 will first turn on, then with 50% brightness, and next, it will turn off.

Finally, it will start fading in and out continuously until you stop the execution of the program.

We added a condition that when the program stops, the LED turns off.

You can stop the execution of the program by pressing CTRL+C. Notice that the LED will turn off, and a message will be printed on the Terminal shell.

PWM Output Device

If you’re using a Generic PWM Output device, here’s an example using the PWMOutputDevice class.

# Complete Project Details: https://RandomNerdTutorials.com/raspberry-pi-pwm-python/

from gpiozero import PWMOutputDevice
from time import sleep

led = PWMOutputDevice(14)

led.value = 1   #LED fully on
sleep(1)
led.value = 0.5  #LED half-brightness
sleep(1)
led.value = 0    #LED fully off
sleep(1)

try:
  # Fade in and out forever
  while True:
    #fade in
    for duty_cycle in range(0, 100, 1):
      led.value = duty_cycle/100.0
      sleep(0.05)

    #fade out
    for duty_cycle in range(100, 0, -1):
      led.value = duty_cycle/100.0
      sleep(0.05)

except KeyboardInterrupt:
  print("Stop the program and turning off the LED")
  led.value = 0
  pass

View raw code

Other Useful Methods

The PWMLED and DigitalOutputDevice interfaces provide other useful additional methods.

pulse()

The pulse() method fades in and out repeatedly. Here’s an example of how you use the pulse() method.

# Complete Project Details: https://RandomNerdTutorials.com/raspberry-pi-pwm-python/

from gpiozero import PWMLED
from signal import pause

led = PWMLED(14)

# pulse an LED forever
led.pulse()
pause()

View raw code

You can pass the following parameters to the pulse() method:

pulse(fade_in_time=1, fade_out_time=1, n=None, background=True)
  • fade_in_time: number of seconds to spend fading in. The default is one second.
  • fade_out_time: number of seconds to spend fading out. The default is one second.
  • n: number of times to pulse. Set to None to run forever. None is the default value.
  • background: if True (the default), start a background thread to continue pulsing and return immediately.

blink()

The blink() method of the PWMLED object can be either used to blink an LED or to fade in and out an LED. Here’s an example of how yo use the blink() method to fade an LED.

# Complete Project Details: https://RandomNerdTutorials.com/raspberry-pi-pwm-python/

from gpiozero import PWMLED
from signal import pause

led = PWMLED(14)

#blink(on_time=1, off_time=1, fade_in_time=0, fade_out_time=0, n=None, background=True)
# fading an LED forever
led.blink(0, 0, 1, 1, None, True)
pause()

View raw code

The blink() method accepts the following arguments, with the following values as default:

blink(on_time=1, off_time=1, fade_in_time=0, fade_out_time=0, n=None, background=True)

So, to fade the LED instead of blinking, you need to pass the following parameters:

led.blink(0, 0, 1, 1, None, True)

Wrapping Up

In this tutorial, you learned how to output PWM signals on the Raspberry Pi GPIOs using the PWMLED and PWMOutputDevice interfaces of the gpiozero library. We’ve also explored three different ways to fade in and out an LED.

We hope you found this tutorial useful. If you’re new to the Raspberry Pi, I’m sure you’ll find the following tutorials useful:

You can check all our Raspberry Pi projects on the following link:

Thanks for reading.



Learn how to build a home automation system and we’ll cover the following main subjects: Node-RED, Node-RED Dashboard, Raspberry Pi, ESP32, ESP8266, MQTT, and InfluxDB database DOWNLOAD »
Learn how to build a home automation system and we’ll cover the following main subjects: Node-RED, Node-RED Dashboard, Raspberry Pi, ESP32, ESP8266, MQTT, and InfluxDB database DOWNLOAD »

Recommended Resources

Build a Home Automation System from Scratch » With Raspberry Pi, ESP8266, Arduino, and Node-RED.

Home Automation using ESP8266 eBook and video course » Build IoT and home automation projects.

Arduino Step-by-Step Projects » Build 25 Arduino projects with our course, even with no prior experience!

What to Read Next…


Enjoyed this project? Stay updated by subscribing our newsletter!

3 thoughts on “Raspberry Pi: PWM Outputs with Python (Fading LED)”

  1. For me to install the gpiozero module i had to type “python3 -m pip install gpiozero” not “python3 -m pip gpiozero”. Im running Ubuntu on my Pi. The module isnt preinstalled there. Also I had to download pip first.

    Reply
  2. It is a nice article, BUT, there are a few things not clear enough.
    RPi has 4 PWM pins and 2 PWM channels. Say, I want to use 4 MOSFETs to drive an RGBW LED strip. I can’t do it without some PWM IC, as the RPi can drive only two pins at once.

    Am I right?

    Reply

Leave a Comment

Download Our Free eBooks and Resources

Get instant access to our FREE eBooks, Resources, and Exclusive Electronics Projects by entering your email address below.