Raspberry Pi Fading an LED

Fading an LED smoothly on a Raspberry Pi means controlling its brightness with pulse-width modulation (PWM) using gpiozero's PWMLED class, rather than simply switching it on or off.

Why a Plain LED Can Only Blink, Not Fade

A Raspberry Pi's GPIO pins are digital: at any instant a pin is either driving roughly 3.3V or 0V, with nothing in between. gpiozero's basic LED class reflects that directly - calling led.on() and led.off() is really just setting the pin high or low. To make an LED appear to glow at half brightness, you need a way to deliver something between full voltage and no voltage, on average, many times a second.

Pulse-Width Modulation in Plain Terms

PWM does not actually produce an in-between voltage. Instead it switches the pin on and off very rapidly, and varies the proportion of each cycle spent on - called the duty cycle. An LED reacts far faster than the eye can follow, so your eye averages the rapid on/off pulses into a single perceived brightness: a 25% duty cycle looks noticeably dimmer than a 75% duty cycle, even though the pin is only ever fully on or fully off at any given instant.

  • Duty cycle is the fraction of each PWM cycle the pin spends high, expressed from 0.0 (always off) to 1.0 (always on).
  • gpiozero's PWMLED picks a PWM frequency for you (100Hz by default) that is fast enough to be invisible to the eye.
  • Setting led.value to any float between 0.0 and 1.0 changes the duty cycle immediately, which is what makes brightness feel continuous rather than stepped.

Example

from gpiozero import PWMLED
from time import sleep

led = PWMLED(17)

# Manually ramp brightness from off to full over 2 seconds
for step in range(0, 101):
    led.value = step / 100  # value must be between 0.0 and 1.0
    sleep(0.02)

Automating the Ramp with pulse()

Writing your own loop is useful for understanding what is happening, but gpiozero also ships a ready-made pulse() method that fades an LED up and down in a background thread, so the rest of your program can keep running. You just specify how many seconds each fade should take and how many times to repeat it - or leave n_times as None to fade forever.

Example

from gpiozero import PWMLED
from signal import pause

led = PWMLED(17)

# fade_in_time/fade_out_time are seconds; n_times=None repeats forever
led.pulse(fade_in_time=1, fade_out_time=1, n_times=None)

pause()
ClassBrightness controlTypical use
LEDOn or off onlyStatus indicators, simple alerts
PWMLEDAny level from 0.0 to 1.0Fading effects, dimmable lighting, driving PWM-friendly loads
Note: Human brightness perception is closer to logarithmic than linear, so stepping the duty cycle in equal increments (0.0, 0.1, 0.2 ...) tends to look like it brightens quickly at first and then barely changes near full brightness. Squaring the value, or using an exponential curve, usually looks smoother to the eye than a straight linear ramp.
Note: PWM changes how long the pin is on, not how much current it can supply - you still need the same current-limiting resistor (commonly 220 to 330 ohms) in series with the LED that a plain on/off circuit would need.