Python Forum
Seemingly unstable GPIO output while executing from RetroPie
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Seemingly unstable GPIO output while executing from RetroPie
#1
I have Python code on a Raspberry Pi running RetroPie. It instructs a GPIO pin to supply a MOSFET transistor with a signal to turn on/off LED lights. I have problems with the lights not staying on when I use a fading-up routine. After executing the code via RetroPie (automatically at boot, and manually via the RetroPie menu). I do not believe it has anything to do with the electronics; the signal seems to be dropped to the output pin.

More detailed description:
I have LED lights fade up with pulse width modulation (PWM), and then I attempt to set the pin to "on" following the ramp-up. It seems to have a problem after PWM. I set the pin HIGH, LOW, 0, 1 -- it just seems to do whatever it wants after the PWM, that is, either on or off whether it was told to be on or off. I've tried putting a pause after the modulation, and I currently have the whole pin re-initiated after the PWM loop (which I don't know why that isn't putting out an error). It seems to work fine from command line (but I have messed with this for so long, that I may not be correct on that). My program logic is that the pin is opened/initialized, faded up with PWM, and then set to "on" after the fade-up, but something goes regularly wrong.


During RetroPie boot, the Python code is run from ( /etc/rc.local):
...
python /home/pi/gameltsfade.py &
exit 0

Manually, the code can be operated from the RetroPie menu ( ~RetroPie/retropiemenu/Game lights ON.sh):
!#/bin/bash

python /home/pi/gameltsfade.py


My gameltsfade.py programming:
import RPi.GPIO as GPIO # Importing RPi library to use the GPIO pins
from time import sleep # Importing sleep from time library
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD) # set BOARD pin numbering system
GPIO.setup(11, GPIO.OUT) # Declaring pin 11 as output pin

pwm=GPIO.PWM(11,100) # Created a PWM object
pwm.start(0) # Started PWM at 0% duty cycle

for x in range(100): # loop for 200 times
    pwm.ChangeDutyCycle(x) # set duty cycle
    sleep(0.01) # Delay for 30mS in loop
#pwm.stop()
#GPIO.setup(11, GPIO.OUT, initial=GPIO.HIGH)
#pwm.start(100)
#pwm.ChangeDutyCycle(100)
#print("end of loop")
#sleep(2)
#GPIO.output(11, 1)******
sleep(0.5)
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD) # set BOARD pin numbering system
GPIO.setup(11, GPIO.OUT) # Declaring pin 11 as output pin
GPIO.output(11, GPIO.HIGH)
#print("set at 1")
#sleep(3)
As it stands, it functions, although unreliable.

(I also have this manually operable through Kodi add-ons (separate code, running in RetroPie) with similar results - actually in Kodi, it never stays on (when pulse width modulation is used).


This is my first post, and I am new to Raspberry Pi, Python and this forum. I've tried to comply with forum policies as much as possible. The RetroPie forum is not willing to comment (as maybe not focused on Python and GPIO programming), and I hope this forum doesn't shy away from this being in the RetroPie environment. Thanks for reading.

Pi Model: 4B (2GB), 5.4.72-v7l+ firmware, 3A power supply
RetroPie v. 4.7.1
Emulation Station v. 2.9.6RP
Python 2.7.16
Linux Buster
Reply
#2
sleep(0.01) # Delay for 30mS in loop
this will delay for only 10 ms. per iteration. For 30 use .03

There's an example here where author is illuminating an led using pwm: https://www.mbtechworks.com/projects/ras...i-pwm.html
Reply
#3
This is a great example of why the comments should never duplicate the code. 100 steps instead of 200, sleep 10 ms instead of 30. Comments should be seldom and describe purpose, not implementation. If the implementation is unclear, change the code to make the implementation clear.

I think your problem is caused by not stopping PWM. Since PWM is toggling power on/off at some frequency/duty cycle I would expect this to override setting the GPIO output. What happens if you run this?
import RPi.GPIO as GPIO
from time import sleep

GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD)
GPIO.setup(11, GPIO.OUT)

# Using PWM ramp power from 0 to 100% 
pwm=GPIO.PWM(11,100)
pwm.start(0)
for x in range(100): 
    pwm.ChangeDutyCycle(x)
    sleep(0.01)

# Stop PWM and toggle LED on/off at 1 second intervals
pwm.stop()
for _ in range(10)
    GPIO.output(11, GPIO.HIGH)
    sleep(1)
    GPIO.output(11, GPIO.LOW)
    sleep(1)
LouF likes this post
Reply
#4
Yes, that does it! The lights blinked on and off after the PWM.

Experimenting, trying to minimize, and fine-tuning:
-It had to go through (1) off and (1) on cycle in order to work; it would not work just going directly to "on".
-One cycle is needed, and there had to be a minimum pause (sleep) of 0.01 seconds after "off"; omitting any pause after "on" retained functionality.

Here is what I reduced it to:
for _ in range(1):
    GPIO.output(11, GPIO.LOW)
    sleep(0.01)
    GPIO.output(11, GPIO.HIGH)
I apologize for the inconsistencies in the comments; it makes for nonsense. They originally came from a tutorial, and the differences were from tweaking. I was pre-occupied with forum format and wondering why the straight forward logic of the code wasn't operating as intended.

Thanks, deanhystad!


It's interesting, now that I've got this under control, I can see how and why PWM does not always give smooth dimming effect at very low cycle duty - the "flicker" is so slow that it is somewhat discernable rocky blips (at least, a subliminal mess at startup). Additionally, there is occasional haphazard loop steps. Oh well, that's another issue for another time.
Reply
#5
Thanks Larz60.

Those examples usually keep the computer in the program. I need it to do the setting and get out w/o keyboard interuption.
Reply
#6
My guess is you have to wait for the current duty cycle to complete. This should work to bring the light up and leave it on.
import RPi.GPIO as GPIO
from time import sleep
 
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD)
GPIO.setup(11, GPIO.OUT)
 
# Using PWM ramp power from 0 to 100% 
pwm=GPIO.PWM(11,100)
pwm.start(0)
for x in range(100): 
    pwm.ChangeDutyCycle(x)
    sleep(0.01)
pwm.stop()
sleep(0.01)  # Wait length of 1 duty cycle
GPIO.output(11, GPIO.HIGH)
When I was looking at the rpi stuff I remember reading the default PWM frequency is 1000Hz. I don't know why the examples set it at 100Hz.
Reply
#7
Thumbs Up 
Yes, that works and puts the final clean-up on it.

Thanks for all your help!!
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  why does VS want to install seemingly unrelated products? db042190 3 608 Jun-12-2023, 02:47 PM
Last Post: deanhystad
  function return boolean based on GPIO pin reading caslor 2 1,130 Feb-04-2023, 12:30 PM
Last Post: caslor
  class Update input (Gpio pin raspberry pi) caslor 2 742 Jan-30-2023, 08:05 PM
Last Post: caslor
  Webhook, post_data, GPIO partial changes DigitalID 2 953 Nov-10-2022, 09:50 PM
Last Post: deanhystad
  Pexpect timesout before executing whole output eagerissac 0 1,451 Jun-23-2021, 03:30 AM
Last Post: eagerissac
  Seemingly simple loop Weber585 7 3,434 Mar-21-2021, 07:19 PM
Last Post: jefsummers
  Picture changing triggered by GPIO q_nerk 2 2,517 Dec-14-2020, 03:32 PM
Last Post: DeaD_EyE
  GPIO high if network IP has good ping duckredbeard 3 2,280 Oct-12-2020, 10:41 PM
Last Post: bowlofred
  raspberry pi tank gpio help jatgm1 1 2,369 May-06-2020, 09:00 PM
Last Post: Larz60+
  Where should I place GPIO.cleanup() shallanq 2 2,110 Apr-11-2020, 05:02 AM
Last Post: shallanq

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020