简体   繁体   中英

How to interrupt a while loop, run a function and go back to the loop

I'm beginning with Python and Raspberry Pi and was trying to make some Physical Computing with them.

I began with that: https://www.raspberrypi.org/learning/physical-computing-with-python/ and everything went well.

Than I tried to play around with traffic lights (with success!): https://www.raspberrypi.org/learning/physical-computing-with-python/trafficlights/

Here my code:

from gpiozero import Button, TrafficLights
from time import sleep

lights = TrafficLights(25, 8, 7)

while True:
    lights.green.on()
    print("GREEN")
    sleep(12)
    lights.green.off()
    lights.amber.on()
    print("AMBER")
    sleep(4)
    lights.red.on()
    lights.amber.off()
    print("RED")
    sleep(12)
    lights.amber.on()
    print("RED & AMBER")
    sleep(4)
    lights.red.off()
    lights.amber.off()

Than I tried to add a button for a pedestrian crossing. But here I have problems.

Here the code:

from gpiozero import Button, TrafficLights
from time import sleep

button = Button(21)
lights = TrafficLights(25, 8, 7)

def pedestrian_crossing():
    sleep(4)
    lights.off()
    lights.amber.on()
    print("Pedestrian crossing: AMBER")
    sleep(4)
    lights.red.on()
    lights.amber.off()
    print("Pedestrian crossing: RED")
    sleep(12)
    lights.amber.on()
    print("Pedestrian crossing: RED & AMBER")
    sleep(4)
    lights.red.off()
    lights.amber.off()

button.when_pressed = pedestrian_crossing

while True:
    lights.green.on()
    print("GREEN")
    sleep(12)
    lights.green.off()
    lights.amber.on()
    print("AMBER")
    sleep(4)
    lights.red.on()
    lights.amber.off()
    print("RED")
    sleep(12)
    lights.amber.on()
    print("RED & AMBER")
    sleep(4)
    lights.red.off()
    lights.amber.off()

I tried with button.wait_for_press , button.wait_for_release & Co., but button.is_pressed was the one that gave me the best result.

The problem is that when I press the button, the function is called, but the loop continues. So how could I rewrite the code and than when I press the button the loop stops, the function is called, everything inside the function is done and then it goes back to the loop?

Or there's another solution, with the other button attributes?

Thanks in advance!

How about like below, Instead of call the pedestrian crossing function directly when button press, set a variable to indicate pedestrian crossing press trigger, then inside while loop will call pedestrian_crossing function if being press then return to while loop

put the checking for pedestrian_press var at my_sleep function so it will get check everytime my_sleep being call in while loop that make it almost ~1s delay interrupt

pedestrian_press = False
def pedestrian_crossing():
    global pedestrian_press
    pedestrian_press = False # reset press
    sleep(4)
    lights.off()
    lights.amber.on()
    print("Pedestrian crossing: AMBER")
    sleep(4)
    lights.red.on()
    lights.amber.off()
    print("Pedestrian crossing: RED")
    sleep(12)
    lights.amber.on()
    print("Pedestrian crossing: RED & AMBER")
    sleep(4)
    lights.red.off()
    lights.amber.off()

def set_pedestrian_press():
    global pedestrian_press
    pedestrian_press = True

button.when_pressed = set_pedestrian_press


def my_sleep(n):
    # checking for pedestrian press done at 1 sec interval
    # to make it check at smaller interval
    # change to range(n*10) then sleep(0.1), for 0.1s interval
    for i in range(n):
        sleep(1)
        if pedestrian_press:  # check if pedestrian press
            pedestrian_crossing()

while True:
    lights.green.on()
    print("GREEN")
    my_sleep(12) # every second will check for pedestrian_press
    lights.green.off()
    lights.amber.on()
    print("AMBER")
    my_sleep(4) # every second will check for pedestrian_press
    lights.red.on()
    lights.amber.off()
    print("RED")
    my_sleep(12) # every second will check for pedestrian_press
    lights.amber.on()
    print("RED & AMBER")
    my_sleep(4) # every second will check for pedestrian_press
    lights.red.off()
    lights.amber.off()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM