0
0
Iot-protocolsHow-ToBeginner · 4 min read

How to Use PWM on Raspberry Pi: Simple Guide with Code

To use PWM on Raspberry Pi, you can use the RPi.GPIO Python library to control the pulse width on a GPIO pin. Initialize PWM on a pin with a frequency, then start it with a duty cycle to control devices like LEDs or motors.
📐

Syntax

Using PWM with the RPi.GPIO library involves these steps:

  • GPIO.setmode(GPIO.BCM): Set pin numbering mode.
  • GPIO.setup(pin, GPIO.OUT): Set the pin as output.
  • pwm = GPIO.PWM(pin, frequency): Create PWM instance on the pin with frequency in Hz.
  • pwm.start(duty_cycle): Start PWM with duty cycle (0-100%).
  • pwm.ChangeDutyCycle(duty_cycle): Change duty cycle while running.
  • pwm.stop(): Stop PWM.
  • GPIO.cleanup(): Clean up GPIO settings.
python
import RPi.GPIO as GPIO

GPIO.setmode(GPIO.BCM)  # Use BCM pin numbering
pin = 18
GPIO.setup(pin, GPIO.OUT)  # Set pin 18 as output

pwm = GPIO.PWM(pin, 1000)  # Create PWM on pin 18 at 1000Hz
pwm.start(50)  # Start PWM with 50% duty cycle

# Change duty cycle later
pwm.ChangeDutyCycle(75)

pwm.stop()  # Stop PWM
GPIO.cleanup()  # Reset GPIO
💻

Example

This example smoothly changes the brightness of an LED connected to GPIO pin 18 using PWM. It increases the duty cycle from 0% to 100% and back, making the LED fade in and out.

python
import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BCM)
pin = 18
GPIO.setup(pin, GPIO.OUT)

pwm = GPIO.PWM(pin, 500)  # 500Hz frequency
pwm.start(0)  # Start with LED off

try:
    while True:
        for dc in range(0, 101, 5):  # Increase duty cycle
            pwm.ChangeDutyCycle(dc)
            time.sleep(0.05)
        for dc in range(100, -1, -5):  # Decrease duty cycle
            pwm.ChangeDutyCycle(dc)
            time.sleep(0.05)
except KeyboardInterrupt:
    pass

pwm.stop()
GPIO.cleanup()
⚠️

Common Pitfalls

Common mistakes when using PWM on Raspberry Pi include:

  • Not setting the GPIO mode with GPIO.setmode() before setup.
  • Forgetting to call GPIO.cleanup() after the program ends, which can cause warnings on next run.
  • Using the wrong pin numbering system (BCM vs BOARD).
  • Setting duty cycle values outside 0-100%, which causes errors.
  • Trying to use PWM on pins that do not support hardware PWM (software PWM works on most pins but is less precise).

Example of wrong and right usage:

python
import RPi.GPIO as GPIO

# Wrong: No setmode called
pin = 18
GPIO.setup(pin, GPIO.OUT)  # This will raise a warning or error

# Right:
GPIO.setmode(GPIO.BCM)
GPIO.setup(pin, GPIO.OUT)
pwm = GPIO.PWM(pin, 1000)
pwm.start(50)
pwm.stop()
GPIO.cleanup()
📊

Quick Reference

CommandDescription
GPIO.setmode(GPIO.BCM)Set pin numbering to BCM mode
GPIO.setup(pin, GPIO.OUT)Set pin as output
GPIO.PWM(pin, frequency)Create PWM instance on pin with frequency in Hz
pwm.start(duty_cycle)Start PWM with duty cycle (0-100%)
pwm.ChangeDutyCycle(duty_cycle)Change duty cycle while running
pwm.stop()Stop PWM signal
GPIO.cleanup()Reset GPIO pins and clean up

Key Takeaways

Always set GPIO mode with GPIO.setmode() before using pins.
Use GPIO.PWM(pin, frequency) to create PWM and start it with a duty cycle.
Duty cycle controls the power delivered; 0% is off, 100% is fully on.
Call GPIO.cleanup() after your program to avoid warnings and free pins.
Software PWM works on most pins but hardware PWM pins offer better precision.