Quantcast
Channel: Raspberry Pi Forums
Viewing all articles
Browse latest Browse all 4856

Automation, sensing and robotics • Re: How to Properly Initialize and Use PWM on GPIO 18 in Python?

$
0
0
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!
I just got our PWM program working, controlling LED brightness using Python. Here's the code we used:

```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? :?:
- Does it involve low-level machine instructions, or does it rely on hardware-specific PWM modules in the Raspberry Pi's chipset? :?:

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



Viewing all articles
Browse latest Browse all 4856

Trending Articles