1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

A little help with python

Discussion in 'HTML, Graphics & Programming' started by PiKe, Jul 1, 2018.

  1. PiKe

    Capodecina

    Joined: Oct 18, 2002

    Posts: 22,718

    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.
     
  2. Rroff

    Man of Honour

    Joined: Oct 13, 2006

    Posts: 55,885

    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: Jul 1, 2018
  3. PiKe

    Capodecina

    Joined: Oct 18, 2002

    Posts: 22,718

    Location: Lake District

    I would like to use the interrupt method really, looping would be easier but that's more CPU intensive.
     
  4. PiKe

    Capodecina

    Joined: Oct 18, 2002

    Posts: 22,718

    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()
    
     
  5. PiKe

    Capodecina

    Joined: Oct 18, 2002

    Posts: 22,718

    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: Jul 2, 2018
  6. Rroff

    Man of Honour

    Joined: Oct 13, 2006

    Posts: 55,885

    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.
     
  7. PiKe

    Capodecina

    Joined: Oct 18, 2002

    Posts: 22,718

    Location: Lake District

    Would you choose to just loop instead of using a blocking function?