Control DC Motor Speed with Raspberry Pi Using PWM
You can control a DC motor speed with a Raspberry Pi by using
PWM (Pulse Width Modulation) on a GPIO pin connected to a motor driver. By adjusting the PWM duty cycle in Python, you change the motor speed smoothly.Syntax
To control motor speed, use the RPi.GPIO library to set up PWM on a GPIO pin. The key parts are:
GPIO.setup(pin, GPIO.OUT): Set the pin as output.pwm = GPIO.PWM(pin, frequency): Create PWM on the pin with a frequency (e.g., 1000 Hz).pwm.start(duty_cycle): Start PWM with a duty cycle (0-100%).pwm.ChangeDutyCycle(duty_cycle): Change speed by adjusting duty cycle.pwm.stop(): Stop PWM when done.
python
import RPi.GPIO as GPIO GPIO.setmode(GPIO.BCM) motor_pin = 18 GPIO.setup(motor_pin, GPIO.OUT) pwm = GPIO.PWM(motor_pin, 1000) # 1000 Hz frequency pwm.start(0) # Start with 0% duty cycle (motor off) # To change speed: pwm.ChangeDutyCycle(50) # 50% speed # When finished: pwm.stop() GPIO.cleanup()
Example
This example shows how to gradually increase and then decrease the speed of a DC motor connected to GPIO pin 18 using PWM.
python
import RPi.GPIO as GPIO import time GPIO.setmode(GPIO.BCM) motor_pin = 18 GPIO.setup(motor_pin, GPIO.OUT) pwm = GPIO.PWM(motor_pin, 1000) # 1 kHz frequency pwm.start(0) # Motor off initially try: # Gradually increase speed for duty_cycle in range(0, 101, 10): pwm.ChangeDutyCycle(duty_cycle) print(f"Speed: {duty_cycle}%") time.sleep(0.5) # Gradually decrease speed for duty_cycle in range(100, -1, -10): pwm.ChangeDutyCycle(duty_cycle) print(f"Speed: {duty_cycle}%") time.sleep(0.5) finally: pwm.stop() GPIO.cleanup()
Output
Speed: 0%
Speed: 10%
Speed: 20%
Speed: 30%
Speed: 40%
Speed: 50%
Speed: 60%
Speed: 70%
Speed: 80%
Speed: 90%
Speed: 100%
Speed: 100%
Speed: 90%
Speed: 80%
Speed: 70%
Speed: 60%
Speed: 50%
Speed: 40%
Speed: 30%
Speed: 20%
Speed: 10%
Speed: 0%
Common Pitfalls
- Not using a motor driver: Raspberry Pi GPIO pins cannot power motors directly; always use a motor driver or transistor circuit.
- Incorrect GPIO pin mode: Use
GPIO.BCMorGPIO.BOARDconsistently and set pins as output. - Forgetting to clean up: Always call
GPIO.cleanup()to reset pins after running your program. - Using wrong PWM frequency: Too low frequency can cause motor noise; 1 kHz is a good start.
- Duty cycle out of range: Duty cycle must be between 0 and 100.
python
import RPi.GPIO as GPIO # Wrong: Trying to power motor directly without driver GPIO.setmode(GPIO.BCM) motor_pin = 18 GPIO.setup(motor_pin, GPIO.OUT) GPIO.output(motor_pin, GPIO.HIGH) # This can damage Pi # Right: Use PWM with motor driver pwm = GPIO.PWM(motor_pin, 1000) pwm.start(50) # 50% speed # Remember to cleanup pwm.stop() GPIO.cleanup()
Quick Reference
To control DC motor speed with Raspberry Pi:
- Use a motor driver circuit (e.g., L298N, L293D).
- Connect motor driver input to Raspberry Pi GPIO pin.
- Use
RPi.GPIOlibrary to create PWM on that pin. - Adjust PWM duty cycle (0-100%) to change speed.
- Always clean up GPIO pins after use.
Key Takeaways
Use PWM on a GPIO pin with a motor driver to control DC motor speed.
Adjust the PWM duty cycle between 0 and 100 to set motor speed smoothly.
Never power motors directly from Raspberry Pi pins; always use a driver.
Set GPIO pins correctly and clean up after your program to avoid issues.
A frequency around 1 kHz is effective for quiet and smooth motor control.