I got a piece of code in Python from here: http://www.raspberry-pi-geek.com/Archive/2013/01/Adding-an-On-Off-switch-to-your-Raspberry-Pi
And I wanted to improve on it.
Since this is the first time I work with Python, I got stuck on understanding what actually happens.
Here is the code:
# Import the modules to send commands to the system and access GPIO pins
from subprocess import call
import RPi.GPIO as gpio
from time import sleep
gpio.setmode(gpio.BCM) # Set pin numbering to board numbering
gpio.setup(22, gpio.IN) # Set up pin 22 as an input
rebootBool = 0
# Define a function to keep script running
def main(pin):
while True:
#gpio.remove_event_detect(pin)
gpio.add_event_detect(22, gpio.RISING, callback=confirmation, bouncetime=200) # Set up an interrupt to look for button presses
sleep(5000000)
def confirmation(pin):
gpio.remove_event_detect(pin)
gpio.add_event_detect(22, gpio.RISING, callback=shutdown, bouncetime=200)
sleep(3) # if button has been pressed again within 3 seconds, shut down will happen
main(22)
def reboot(pin):
rebootBool = 1
call('reboot', shell=False)
exit(0)
# Define a function to run when an interrupt is called
def shutdown(pin):
gpio.remove_event_detect(pin)
gpio.add_event_detect(22, gpio.RISING, callback=reboot, bouncetime=200)
sleep(3) # if the button has been pressed for a third time, within 3 seconds, Pi will reboot
if rebootBool == 0: # Just to make sure a halt is not called after the 3 seconds have passed, if reboot is called
call('halt', shell=False)
exit(0)
main(22) # Run the loop function to keep script running
What I want to do is this:
What happens is this:
If I press the button twice or three times, it tells me that gpio.add_event_detect is already defined, when it tries to define it in main(). So it doesn't change it, and if I press it one more time, it calls the shutdown function.
What I don't understand is:
Why does it want to define the gpio event in main, when the actual function is either reboot or shutdown (and it should call either reboot or shutdown)?
Because a callback function is running in a separate thread. This means, for example, when you call any callback function in the main loop it still works(main loop), and thus it happens when you call a function gpio.add_event_detect from a callback function(thread #1) and from the main loop(thread #2) at the same time. It's typical race condition. You can check it by running this code:
#!/usr/bin/python
# Import the modules to send commands to the system and access GPIO pins
from subprocess import call
import RPi.GPIO as gpio
from time import sleep
gpio.setmode(gpio.BCM) # Set pin numbering to board numbering
gpio.setup(22, gpio.IN, pull_up_down=gpio.PUD_DOWN) # Set up pin 22 as an input
rebootBool = 0
# Define a function to keep script running
def main(pin):
while True:
print "main loop"
gpio.remove_event_detect(22)
gpio.add_event_detect(22, gpio.RISING, callback=confirmation, bouncetime=200) # Set up an interrupt to look for button presses
sleep(1)
#raw_input()
def confirmation(pin):
print "confirmation1"
sleep(5)
print "confirmation2"
gpio.remove_event_detect(22)
gpio.add_event_detect(22, gpio.RISING, callback=shutdown, bouncetime=200)
sleep(5) # if button has been pressed again within 3 seconds, shut down will happen
gpio.remove_event_detect(22)
main(22)
def reboot(pin):
rebootBool = 1
print "reboot"
#call('reboot', shell=False)
exit(0)
# Define a function to run when an interrupt is called
def shutdown(pin):
print "shutdown"
gpio.remove_event_detect(pin)
gpio.add_event_detect(22, gpio.RISING, callback=reboot, bouncetime=200)
sleep(3) # if the button has been pressed for a third time, within 3 seconds, Pi will reboot
if rebootBool == 0: # Just to make sure a halt is not called after the 3 seconds have passed, if reboot is called
#call('halt', shell=False)
print "halt"
exit(0)
main(22) # Run the loop function to keep script running
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With