Python "shutdown / reboot raspberry pi" script using one button

I got some of the 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 it.

Since this is the first time I am working with Python, I am stuck in understanding what is actually going on.

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

      

I want to do the following:

  • If the button is pressed once, a confirmation function is executed in which it resets the button to invoke the shutdown function if pressed for 3 seconds.
    • Continue, resume work with the main loop
  • In shutdown function, if it is pressed again (within 3 seconds), it is reset to call the restart function.
    • Go on and off

What's happening:

If I click the button two 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 again it calls the shutdown function.

I dont understand what:

Why does he want to define a gpio event in the main when the actual function reloads or exits (and it should cause reloads or exits)?

+3


source to share


2 answers


So, after Anton Glukhov explained to me what to look for, I learned how to solve each problem and now it works flawlessly.

This is a link that better explains what I did: http://sourceforge.net/p/raspberry-gpio-python/wiki/Inputs/

Unfortunately, I was unable to do this other than using a while loop in the main function. But since nothing is critical, 1 second sleep is added to each cycle, which ensures minimal CPU usage.



I am sharing the final code here, in the hopes that it might help others:

# 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
from os import system

gpio.setmode(gpio.BCM) # Set pin numbering to BCM numbering
gpio.setup(22, gpio.IN) # Set up pin 22 as an input

def confirmation(pin):
    #print "Confirmation Function on pin %d" % pin
    system('echo Press again to confirm Shut down menu! | wall -n') # let all logged in users know
    gpio.remove_event_detect(pin)
    gpio.add_event_detect(pin, gpio.RISING, bouncetime=200)
    sleep(2) # if button has been pressed again within 2 seconds, shut down function is called
    if gpio.event_detected(pin):
        shutdown(pin)
    else:
        #print "canceled"
        system('echo Shut down canceled! | wall -n') # let all logged in users know
        main()

def resetPin(pin):
    #print "Pin %d has been reset" % pin
    gpio.remove_event_detect(pin)
    gpio.add_event_detect(pin, gpio.RISING, bouncetime=200)

def reboot(pin):
    #print "Reboot Function on pin %d" % pin
    call('reboot', shell=False)
    exit(0)

# Define a function to run when an interrupt is called
def shutdown(pin):
    #print "ShutDown function on pin %d" % pin
    system('echo Press again if you want to reboot instead of shut down! | wall -n') # let all logged in users know
    gpio.remove_event_detect(pin)
    gpio.add_event_detect(pin, gpio.RISING, bouncetime=200)
    sleep(2) # if the button has been pressed for a third time, within 2 seconds, Pi will reboot
    if gpio.event_detected(pin):
        reboot(pin)
    else:
        call('halt', shell=False)
        exit(0)

# Define a function to keep script running
def main():
    #print "Main Function"
    resetPin(22)
    while True:
        sleep(1)
        if gpio.event_detected(22):
            confirmation(22)

main() # Run the main function to keep script running

      

0


source


Because the callback function runs on a separate thread. This means, for example, when you call any callback function in the main loop, it still runs (main loop), and this happens when you call the gpio.add_event_detect function from the callback function (thread # 1) and from the main loop (thread # 2) at the same time. This is a 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

      

+1


source







All Articles