A little help with python

Caporegime
Joined
18 Oct 2002
Posts
25,289
Location
Lake District
I'm trying to wrap my brains around getting the following to work:

A timer is set for 5 minutes which then begins to count down, if a GPIO pin goes high, a command is executed then the timer is reset back to 5 minutes, however if it goes low, the timer continues to run out, when the timer reaches zero, a command is executed.

I think I'm going to have to use threading to do this? I'm using a callback from the GPIO.add_event_detect but I can't get my head around the logic required to make this work.
 
Man of Honour
Joined
13 Oct 2006
Posts
91,051
I'm not too familiar with Python and GPIO but there is two ways to approach it - either having a main loop in your program that periodically queries the GPIO state and then does something or interrupt based where a function will be called (externally program execution moved to a specific place) when an event happens.

I'm not personally a fan of built in timers - I prefer to set a variable to a millisecond value and then calculate time passed since when needed and reset as appropriate.

EDIT: For your use milliseconds probably not relevant so you can just use "import time" and reference time.time() to get seconds.
 
Last edited:
Caporegime
OP
Joined
18 Oct 2002
Posts
25,289
Location
Lake District
This is what I have ended up with and it appears to be working:

Code:
#!/usr/bin/python
import RPi.GPIO as GPIO
import time
import subprocess
GPIO.setmode(GPIO.BCM)
PIR_PIN = 7
GPIO.setup(PIR_PIN, GPIO.IN)
global timer
timer = 300 # 5 mins
subprocess.call("sudo /home/pi/rpi-hdmi.sh on", shell=True)
try :
    print "Screen Timer (CTRL+C to exit)"
    time.sleep(5)
    print "Ready..."
    while 1:
        time.sleep(0.985)
        print timer
        # Test PIR_PIN condition
        current_state = GPIO.input(PIR_PIN)
        if timer > 0:
            timer -= 1
            if current_state: #is true
                # Reset timer
                timer = 300
        else:
            if current_state: #is true
                subprocess.call("sudo /home/pi/rpi-hdmi.sh on", shell=True)
                # Reset timer
                timer = 300
            else:
                # Wait for edge
                channel = GPIO.wait_for_edge(PIR_PIN, GPIO.RISING)
                if channel is None:
                        print('Timeout occurred')
                else:
                        subprocess.call("sudo /home/pi/rpi-hdmi.sh on", shell=True)
                        # Reset timer
                        timer = 300
except KeyboardInterrupt:
    print "Quit"
    GPIO.cleanup()
 
Caporegime
OP
Joined
18 Oct 2002
Posts
25,289
Location
Lake District
Actually that didn't work and it got stuck waiting for edge, revised code is now below, but having issues with false positives on the PIR.

Code:
#!/usr/bin/python
import RPi.GPIO as GPIO
import time
import subprocess
GPIO.setmode(GPIO.BCM)
PIR_PIN = 7
GPIO.setup(PIR_PIN, GPIO.IN)
global timer
time_limit = 300 #5 mins
timer = time_limit
subprocess.call("sudo /home/pi/rpi-hdmi.sh off", shell=True)
try :
    print "Screen Timer (CTRL+C to exit)"
    time.sleep(5)
    print "Ready..."
    while 1:
        time.sleep(0.985)
        # Test PIR_PIN condition
        current_state = GPIO.input(PIR_PIN)
        if timer > 0:
            timer -= 1
        if current_state: #is true
                subprocess.call("sudo /home/pi/rpi-hdmi.sh on", shell=True)
                # Reset timer
                timer = time_limit
        elif timer == 0:
                # turn off hdmi as timer expired
                subprocess.call("sudo /home/pi/rpi-hdmi.sh off", shell=True)
                # Wait for edge
                channel = GPIO.wait_for_edge(PIR_PIN, GPIO.RISING)
                if channel == PIR_PIN:
                        # turn hdmi back on
                        subprocess.call("sudo /home/pi/rpi-hdmi.sh on", shell=True)
                        # Reset timer
                        timer = time_limit
except KeyboardInterrupt:
    print "Quit"
 
Last edited:
Man of Honour
Joined
13 Oct 2006
Posts
91,051
Some really quick and dirty code but my approach would have been

Code:
import time
import sys

timer_end = time.time() + 300

try:
    while 1:
        current_state = GPIO.input(PIR_PIN)
        if current_state:
            subprocess.call("sudo /home/pi/rpi-hdmi.sh on", shell=True)
            timer_end = time.time() + 300
        if time.time() >= timer_end:
            subprocess.call("sudo /home/pi/rpi-hdmi.sh off", shell=True)
            channel = GPIO.wait_for_edge(PIR_PIN, GPIO.RISING)
            if channel == PIR_PIN:
                subprocess.call("sudo /home/pi/rpi-hdmi.sh on", shell=True)
                timer_end = time.time() + 300
        time.sleep(1)
except KeyboardInterrupt:
    sys.exit(0)

No idea if that is functional and/or might have missed something in what you are trying to do - I've not touched Python in years and years. Not a fan of the way you are progressing the timer unless I'm misunderstanding and personally not a fan of blocking functions though for the kind of stuff you are doing that is by the by.
 
Back
Top Bottom