I just got our PWM program working, controlling LED brightness using Python. Here's the code we used:Hi,
I am working on controlling a laser diode using PWM on GPIO 18 of a Raspberry Pi. My setup includes the following:
1. Device Tree Configuration:
I have configured PWM in `/boot/config.txt` as follows:
```txt
dtoverlay=pwm-2chan,pin=18,func=2
```
2. GPIO 18 Initial State:
Before running the program, the command `raspi-gpio get 18` outputs:
```txt
GPIO 18: level=0 alt=5 func=PWM0
```
This confirms that GPIO 18 is correctly set to `ALT5` (PWM mode).
3. Python Program:
Below is my Python code for testing PWM functionality:
```python
import RPi.GPIO as GPIO
import time
# Set GPIO pins
RELAY_PIN = 26 # Control laser switch
PWM_PIN = 18 # Control PWM brightness
PWM_FREQUENCY = 2000 # Set PWM frequency (Hz)
def setup_gpio():
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
# Print the state of GPIO 18 before initialization
print("Before PWM setup:", GPIO.gpio_function(PWM_PIN)) # Check GPIO function state
# Set laser switch pin
GPIO.setup(RELAY_PIN, GPIO.OUT)
GPIO.output(RELAY_PIN, False) # Initial state is OFF
# Directly initialize PWM
global pwm
pwm = GPIO.PWM(PWM_PIN, PWM_FREQUENCY)
pwm.start(0) # Initial duty cycle is 0
# Print the state of GPIO 18 after initialization
print("After PWM setup:", GPIO.gpio_function(PWM_PIN)) # Check GPIO function state
def toggle_laser(state):
GPIO.output(RELAY_PIN, state)
if state:
print("Laser is ON")
else:
print("Laser is OFF")
def set_laser_brightness(duty_cycle):
if 0 <= duty_cycle <= 100:
pwm.ChangeDutyCycle(duty_cycle)
print(f"Laser brightness set to {duty_cycle}%")
else:
print("Invalid duty cycle. Please provide a value between 0 and 100.")
def main():
setup_gpio()
try:
while True:
# Turn on laser
toggle_laser(True)
set_laser_brightness(80) # Set brightness to 80%
time.sleep(20) # Keep laser ON for 20 seconds
# Turn off laser
set_laser_brightness(0) # Set brightness to 0 (OFF)
toggle_laser(False)
time.sleep(3) # Keep laser OFF for 3 seconds
except KeyboardInterrupt:
print("Exiting program.")
finally:
pwm.stop()
GPIO.cleanup([RELAY_PIN]) # Only clean up laser switch pin, keep PWM_PIN
if __name__ == "__main__":
main()
```
4. The Issue:
- When I run the program, I encounter the following error:
```
RuntimeError: You must setup() the GPIO channel as an output first
```
- If I add `GPIO.setup(PWM_PIN, GPIO.OUT)` before initializing PWM, GPIO 18 gets reconfigured to a regular output mode (`OUTPUT`), and PWM functionality is lost.
5. What I Need Help With:
- How can I properly initialize and use PWM on GPIO 18 without overwriting its `ALT5` (PWM) mode?
- Is there a way to avoid the `RuntimeError` without resetting GPIO 18's configuration?
Any guidance would be greatly appreciated. Thank you!
```python
import RPi.GPIO as GPIO
from time import sleep
ledpin = 18 # PWM pin connected to LED (using BCM mode)
GPIO.setwarnings(False) # Disable warnings
GPIO.setmode(GPIO.BCM) # Set pin numbering system to BCM
GPIO.setup(ledpin, GPIO.OUT)
# Create PWM instance with frequency of 1000Hz
pi_pwm = GPIO.PWM(ledpin, 1000)
pi_pwm.start(0) # Start PWM with 0% duty cycle
try:
while True:
# Gradually increase duty cycle from 0% to 100%
for duty in range(0, 101, 1):
pi_pwm.ChangeDutyCycle(duty) # Provide duty cycle in the range 0-100
print(f"Increasing brightness: {duty}%") # Print current duty cycle
sleep(0.01) # Small delay for smooth transition
sleep(0.5) # Wait for 0.5 seconds
# Gradually decrease duty cycle from 100% to 0%
for duty in range(100, -1, -1):
pi_pwm.ChangeDutyCycle(duty)
print(f"Decreasing brightness: {duty}%") # Print current duty cycle
sleep(0.01) # Small delay for smooth transition
sleep(0.5) # Wait for 0.5 seconds
except KeyboardInterrupt:
print("Exiting program.")
pi_pwm.stop() # Stop PWM
GPIO.cleanup() # Cleanup all GPIO
```
The LED smoothly transitions its brightness from 0% to 100% and back, with real-time duty cycle values printed to the console.
While this works well, I’m curious about the **relationship between machine-level PWM code and Python’s PWM implementation**:
- How does Python's `RPi.GPIO` library translate high-level `ChangeDutyCycle` calls into the actual hardware-level PWM signals? Image may be NSFW.
Clik here to view.

- Does it involve low-level machine instructions, or does it rely on hardware-specific PWM modules in the Raspberry Pi's chipset? Image may be NSFW.
Clik here to view.

If anyone could explain this process or share references on how Python interacts with the hardware at a deeper level for PWM, it would be very helpful!
Statistics: Posted by dgy411852 — Mon Jan 06, 2025 6:58 pm