Raspberry Pi LED Python: Control, Blink, and PWM Dimming Guide

raspberry pi led control with python

Raspberry Pi LED Python projects connect LEDs to GPIO pins and control them with Python using the gpiozero library. gpiozero ships with Raspberry Pi OS and provides clean abstractions for turning LEDs on and off, blinking at set intervals, and PWM brightness control, all in a few lines of code. This guide covers the correct wiring (with the LED polarity corrected from what most guides get wrong), gpiozero-based control including patterns and sequences, PWMLED dimming and pulse effects, and troubleshooting the most common first-time failures. For the broader Python and GPIO setup on Raspberry Pi, see Python Raspberry Pi: Complete Practical Setup and Usage Guide.

Last tested: Raspberry Pi OS Bookworm Desktop 64-bit | May 2025 | Raspberry Pi 4 Model B (4GB) | Python 3.11, gpiozero 2.0

Key Takeaways

  • The LED’s anode is the longer lead and connects to the GPIO pin (positive side). The cathode is the shorter lead and connects to GND. The original article had this backwards. Wiring the LED in reverse polarity means it will not light up and may be damaged at higher voltages.
  • gpiozero is the recommended GPIO library on Bookworm. It ships with Raspberry Pi OS Desktop and does not require installation. The older RPi.GPIO library still works but is no longer pre-installed on Bookworm and requires sudo apt install python3-rpi.gpio to use. New projects should use gpiozero.
  • Always use a current-limiting resistor between the GPIO pin and the LED. Raspberry Pi GPIO pins output 3.3V. Without a resistor, the LED draws too much current, which can damage both the LED and the GPIO pin. A 330-ohm resistor is correct for standard 5mm LEDs with a typical forward voltage of 2.0–2.2V.

Wiring LEDs to Raspberry Pi GPIO

Every LED has two leads. The anode is the longer lead and is the positive terminal. The cathode is the shorter lead and is the negative terminal. When wiring to the Pi, the anode connects through a resistor to the GPIO pin, and the cathode connects to GND.

Parts needed: One standard 5mm LED. One 330-ohm resistor. Two male-to-female jumper wires. A breadboard is optional but recommended for beginners to keep connections organised.

Wiring steps:

  1. Insert the LED into the breadboard. The longer leg (anode) goes into one row, the shorter leg (cathode) into an adjacent row.
  2. Insert one end of the 330-ohm resistor into the same row as the anode. Insert the other end into a separate row.
  3. Connect a jumper wire from the resistor’s free row to GPIO17 on the Pi (pin 11 in physical numbering).
  4. Connect a jumper wire from the cathode row to any GND pin on the Pi (pin 6, 9, 14, 20, 25, 30, 34, or 39).

Raspberry Pi GPIO pins output 3.3V. The 330-ohm resistor limits current to approximately 3.3mA, well within safe limits for both the LED and the GPIO driver. A 470-ohm resistor reduces brightness slightly with no risk of damage. A 220-ohm resistor is the minimum safe value and produces maximum brightness.

Expected result: With the wiring complete, running a script that sets GPIO17 high should light the LED. If the LED does not light, check polarity first. Try reversing the LED in the breadboard. If it still does not light, verify the jumper wires are fully seated on the Pi’s GPIO header and in the breadboard rows.

Raspberry Pi LED Python control flow: wiring, gpiozero control, LED patterns, PWM dimming, and debugging

Controlling LEDs with Raspberry Pi LED Python and gpiozero

gpiozero is pre-installed on Raspberry Pi OS Desktop. On Raspberry Pi OS Lite, install it:

sudo apt install -y python3-gpiozero

Basic on/off control:

from gpiozero import LED
import time

led = LED(17)  # GPIO17

led.on()
time.sleep(2)
led.off()
print(f"LED is lit: {led.is_lit}")

Blink at a set interval:

from gpiozero import LED
from signal import pause

led = LED(17)
led.blink(on_time=0.5, off_time=0.5)  # 1Hz blink
pause()  # Keep script running until Ctrl+C

led.blink() runs in a background thread so the main program continues. pause() blocks until Ctrl+C without spinning the CPU in a loop. To blink for a fixed duration, use time.sleep() then led.off().

LED sequence across multiple pins:

from gpiozero import LED
import time

pins = [17, 27, 22, 10]  # Four LEDs on GPIO17, 27, 22, 10
leds = [LED(p) for p in pins]

# Chase pattern: each LED on for 0.2s in sequence
try:
    while True:
        for led in leds:
            led.on()
            time.sleep(0.2)
            led.off()
except KeyboardInterrupt:
    for led in leds:
        led.off()

Expected result: The four LEDs light in sequence, creating a chasing effect. The try/except ensures all LEDs switch off cleanly when Ctrl+C is pressed rather than leaving one LED on after the script exits.

gpiozero also provides a LEDBoard class for controlling multiple LEDs as a group, and LEDBarGraph for a progress-bar style display. Both are covered in the gpiozero output devices documentation.

PWM LED Dimming and RGB Control on Raspberry Pi

PWM (Pulse Width Modulation) controls LED brightness by rapidly switching the pin on and off at varying duty cycles. A duty cycle of 1.0 is full brightness; 0.0 is off; 0.5 is half brightness. gpiozero’s PWMLED class handles all the PWM setup:

from gpiozero import PWMLED
import time

led = PWMLED(17)

# Fade up from 0% to 100%
for brightness in range(0, 101, 5):
    led.value = brightness / 100
    time.sleep(0.05)

# Fade down from 100% to 0%
for brightness in range(100, -1, -5):
    led.value = brightness / 100
    time.sleep(0.05)

led.off()

gpiozero also provides a built-in pulse() method that fades up and down continuously:

from gpiozero import PWMLED
from signal import pause

led = PWMLED(17)
led.pulse(fade_in_time=1, fade_out_time=1)  # 1s fade up, 1s fade down
pause()

Expected result: The LED breathes slowly at a 2-second cycle. Adjusting fade_in_time and fade_out_time controls the speed. If the LED jumps to full brightness rather than fading, the pin may not support hardware PWM. GPIO17 and GPIO18 support hardware PWM on Pi 4; other pins use software PWM which works but is less smooth.

RGB LED control. A common-cathode RGB LED has four pins: red, green, blue, and a shared cathode (GND). Wire each colour pin through a 330-ohm resistor to separate GPIO pins. gpiozero’s RGBLED class controls all three channels:

from gpiozero import RGBLED
import time

# Red=GPIO17, Green=GPIO27, Blue=GPIO22
rgb = RGBLED(red=17, green=27, blue=22)

rgb.color = (1, 0, 0)   # Red
time.sleep(1)
rgb.color = (0, 1, 0)   # Green
time.sleep(1)
rgb.color = (0, 0, 1)   # Blue
time.sleep(1)
rgb.color = (1, 0.5, 0) # Orange (mix)
time.sleep(1)
rgb.off()

Colour values are tuples of (red, green, blue) with each channel between 0.0 and 1.0. For a common-anode RGB LED (where the long shared lead goes to 3.3V instead of GND), add active_high=False to the RGBLED constructor.

Troubleshooting Raspberry Pi LED Python Projects

LED does not light at all. Work through these checks in order. First, polarity: the longer lead (anode) must connect through the resistor to the GPIO pin, not to GND. Try reversing the LED and test again. Second, confirm the script is running and the GPIO pin is being set high. Print led.is_lit or led.value to verify the software state. Third, check the jumper wire connections are fully seated on both the GPIO pin and the breadboard. A partially inserted jumper wire is a very common failure point. Fourth, test with a known-good LED from a different batch.

LED is very dim. The resistor value may be too high. A 1k-ohm resistor limits current to about 1mA, producing noticeable dimming. Swap to a 330-ohm or 220-ohm resistor for full brightness. Also verify the GPIO pin is outputting at 3.3V. Some pins can be inadvertently configured as inputs if GPIO setup code runs before the script.

gpiozero import error or “no module named gpiozero”. On Raspberry Pi OS Lite, gpiozero needs installation: sudo apt install python3-gpiozero. On Desktop it should be pre-installed but verify with python3 -c "import gpiozero; print(gpiozero.__version__)". If running inside a virtual environment, activate it and install gpiozero inside it: pip install gpiozero.

GPIO pin busy or “GPIO already in use” error. A previous script did not clean up and left the GPIO pin in a configured state. gpiozero handles cleanup automatically when the script exits normally, but a Ctrl+C during execution may leave pins configured. Reboot the Pi to clear all GPIO state, or use GPIOZero.Device.pin_factory.reset() if available in the version installed.

PWM LED flickers visibly. Software PWM on Bookworm can produce visible flicker on non-hardware-PWM pins at certain duty cycles. Switch to GPIO18 (hardware PWM pin on Pi 4) for the smoothest PWM output. Alternatively, install the pigpio daemon as a pin factory for gpiozero, which provides better software PWM timing than the default factory. For the IoT robot project patterns that combine GPIO LED indicators with motor control, see Raspberry Pi Robot Basics: The Complete Beginners Guide. For Tkinter GUI apps that include LED status indicators, see Raspberry Pi Tkinter: Building GUIs and GPIO-Connected Apps.

FAQ

Which lead is the anode on an LED?

The anode is the longer lead and is the positive terminal. It connects through a current-limiting resistor to the GPIO pin. The cathode is the shorter lead and is the negative terminal; it connects to GND. If the LED has been trimmed to equal length, the flat side of the LED’s plastic housing marks the cathode. Wiring the LED backwards (cathode to GPIO, anode to GND) means it will not light regardless of the software state.

What resistor value do I need for an LED on Raspberry Pi?

For a standard 5mm LED with a forward voltage of approximately 2.0V connected to a 3.3V GPIO pin: a 330-ohm resistor limits current to approximately 3.9mA, which produces good brightness safely within the GPIO driver’s 8mA current limit. A 470-ohm resistor reduces brightness slightly and provides additional safety margin. A 220-ohm resistor is the minimum safe value. Do not connect an LED directly to a GPIO pin without a resistor; the current draw will damage the GPIO driver over time.

Should I use gpiozero or RPi.GPIO for Raspberry Pi LED Python projects?

gpiozero for new projects on Bookworm. It ships with Raspberry Pi OS, provides clean abstractions (LED, PWMLED, RGBLED, Button) that reduce boilerplate, and handles GPIO cleanup automatically. RPi.GPIO still works and has a larger volume of older tutorials, but it is no longer pre-installed on Bookworm and requires sudo apt install python3-rpi.gpio. If following a guide that uses RPi.GPIO, it will still run after installing the package, but new code should use gpiozero.

How do I control LED brightness on Raspberry Pi with Python?

Use gpiozero’s PWMLED class instead of LED. Set led.value to a float between 0.0 (off) and 1.0 (full brightness). For a breathing effect, use led.pulse(). For a custom fade loop, increment led.value in steps with time.sleep() between each step. GPIO18 provides hardware PWM on Pi 4 and produces the smoothest dimming. Other GPIO pins use software PWM which works for most applications but may flicker at some duty cycles.

Can I control an RGB LED with Raspberry Pi and Python?

Yes. Use gpiozero’s RGBLED class with three GPIO pins, one for each colour channel. Each channel needs its own 330-ohm resistor. For a common-cathode RGB LED (shared GND), connect the cathode to GND and use the default active_high=True. For a common-anode RGB LED (shared 3.3V), connect the anode to 3.3V and pass active_high=False to the RGBLED constructor. Set colours as (red, green, blue) tuples with values between 0.0 and 1.0.

References:


About the Author

Chuck Wilson has been programming and building with computers since the Tandy 1000 era. His professional background includes CAD drafting, manufacturing line programming, and custom computer design. He runs PidiyLab in retirement, documenting Raspberry Pi and homelab projects that he actually deploys and maintains on real hardware. Every article on this site reflects hands-on testing on specific hardware and OS versions, not theoretical walkthroughs.

Last tested hardware: Raspberry Pi 4 Model B (4GB). Last tested OS: Raspberry Pi OS Bookworm Desktop 64-bit. Python 3.11, gpiozero 2.0.