2

Here's a link to what I have been trying a accomplish: https://projects.raspberrypi.org/en/projects/physical-computing/9

Near the bottom of the page it says, "Try adding the button for a pedestrian crossing. The button should move the lights to red (not immediately), and give the pedestrians time to cross before moving back to green until the button is pressed again."

This is what I currently have for code:

from gpiozero import Button, TrafficLights
from time import sleep
from signal import pause

button = Button(21)
lights = TrafficLights(4, 5, 6)

print("Normal operation")
def sleep1():
        for i in range(100):
                sleep(0.1)
                if button.is_pressed:
                        sleep(4)
                        lights.off()
                        lights.amber.on()
                        sleep(3)
                        lights.amber.off()
                        lights.red.on()
                        print("Pedestian crossing")
                        sleep(10)
                        lights.off()
                        lights.green.on()
                        sleep(6)

while True:
        lights.green.on()
        sleep1()
        lights.green.off()
        lights.amber.on()
        sleep(3)
        lights.amber.off()
        lights.red.on()
        sleep(10)
        lights.off()

It sort of does what I want it to do. I would like for the "while True" sequence to restart once the "Pedestrian" sequence is completed. Does anyone have any suggestions?

7
  • 1
    start by making a list of actions that have to occur when the button is pressed
    – jsotola
    Commented Feb 18, 2020 at 5:36
  • 1
    I’m not sure I follow? The actions to be carried out are listed in the link and quoted in my description. I’m not sure the webpage provides enough information to complete what it’s asking? I attempted to use a “while True” loop but no luck.
    – Fernando
    Commented Feb 18, 2020 at 6:11
  • 1
    the program that you write has to do a lot of little steps to accomplish a task ... what you listed is a description of the end result ... you need to write down all of the steps needed to accomplish the end result from the microcontroller's point of view
    – jsotola
    Commented Feb 18, 2020 at 6:39
  • 2
    Hello, here's a hint... look at using an interrupt to break out of the usual sequence when the button is pressed. In gpiozero you'd use button.when_pressed to set up a callback function: gpiozero.readthedocs.io/en/v1.2.0/recipes.html#button Commented Feb 18, 2020 at 15:45
  • 1
    Just to be sure, you should never use a Raspberry Pi to make an actual traffic light. As traffic lights are safety critical devices, and require robust circuitry including such things as watchdog circuits that make sure the actual circuit is functioning properly and put the device in a failsafe mode (such as flashing red-lights all directions) if an error is detected.
    – Glen Yates
    Commented Feb 18, 2020 at 17:26

2 Answers 2

0

Try the when_pressed method of the Button class from earlier project in the same tutorial.

It would be great if you could make the LED switch on only when the button is being held down. With GPIO Zero, that’s easy. There are two methods of the Button class called when_pressed and when_released. These don’t block the flow of the program, so if they are placed in a loop, the program will continue to cycle indefinitely.

0

I was trying to solve this same issue and found the need for a global variable to keep track of the status of if the button had been clicked or not. It seems that button.when_pressed starts a new thread and the code in the loop continues to execute along with the function assigned to the button call. The accepted answer does not explain how to solve this problem, but just suggests a method to use without giving an explanation of how to implement it.

Notice the for loop and if statement in the run_lights() function. You have to make sure that you sleep for the accumulated amount of time that your function runs that was triggered by the button press.

Also, by turning the green light back on at the end of the pressed() function fixed an issue where there could be >1 second with no lights on due to a mid-second button push.

from gpiozero import LED, Button, TrafficLights
from time import sleep

traffic_light = TrafficLights(16, 20, 21)
button = Button(26)
white_light = LED(19)

is_pressed = False


def pressed():
    if traffic_light.green.is_lit:
        global is_pressed
        is_pressed = True

        white_light.on()
        sleep(1)
        traffic_light.green.off()
        traffic_light.yellow.on()
        sleep(3)
        traffic_light.yellow.off()

        white_light.off()
        traffic_light.red.on()
        sleep(10)
        traffic_light.red.off()
        traffic_light.green.on()


def run_lights():
    global is_pressed
    while True:
        button.when_pressed = pressed

        traffic_light.green.on()

        for i in range(10):
            sleep(1)
            if is_pressed:
                button.when_pressed = None
                sleep(14)
                break
        if is_pressed:
            is_pressed = False
            continue

        traffic_light.green.off()

        traffic_light.yellow.on()
        sleep(3)
        traffic_light.yellow.off()

        traffic_light.red.on()
        sleep(10)
        traffic_light.red.off()


def main():
    run_lights()


if __name__ == '__main__':
    main()

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.