I have some python code on a raspberry pi that I want to run and carry on a loop until a button is pressed.
The button.wait_for_press() is not suitable because that pauses the program until it runs, but I have tried it out to see if the hardware is working and it does.
def shutterPressed():
global shutterHasBeenPressed
shutterHasBeenPressed = True
def main():
"""
Main program loop
"""
#start camera preview
camera.start_preview(resolution=(SCREEN_W, SCREEN_H))
#Display Intro screens
intro_image_1 = REAL_PATH + '/assets/intro_1.png'
intro_image_2 = REAL_PATH + '/assets/intro_2.png'
overlay_1 = overlay_image(intro_image_1, 0, 3)
overlay_2 = overlay_image(intro_image_2, 0, 4)
#Wait for button press
i = 0
blink_speed = 10
button.when_pressed = shutterPressed
while True:
global shutterHasBeenPressed
shutterHasBeenPressed = False
#Stay in loop until button is pressed
if shutterHasBeenPressed is False:
i += 1
if i == blink_speed:
overlay_2.alpha = 255
elif i == (2 * blink_speed):
overlay_2.alpha = 0
i = 0
#Restart while loop
sleep(0.1)
continue
#button has been pressed!
print("Button Pressed!")
When I run this code, the button press is not registered at all.
What have I got wrong?
EDIT: so I added a print statement to the shutterPressed() function and confirmed that it is running when the button is pressed.
In also added a statement to print the value of shutterHasBeenPressed just before the if statement. This never changed from false.
However, if I removed the line changing the variable to false at the beginning of the loop, then code worked, so it is obviously something to do with when various bits get run. Maybe the while loop starts again after the shutterPressed() function runs?
Either way, i have fixed it by moving the reassignment of the variable to after the if statement.
Welcome to the world of concurrency (somewhat)!
Just imagine your program running: the instructions are being executed one after the other in the order in which they are written, according to the execution flow that they define with the exception of shutterPressed
which is asynchronously executed (maybe).
Therefore, imagine we enter the loop and are at the first line, <here>
:
while True:
global shutterHasBeenPressed
shutterHasBeenPressed = False # <here>
#Stay in loop until button is pressed
if shutterHasBeenPressed is False:
i += 1
if i == blink_speed:
overlay_2.alpha = 255
elif i == (2 * blink_speed):
overlay_2.alpha = 0
i = 0
#Restart while loop
sleep(0.1)
continue
#button has been pressed!
print("Button Pressed!")
Now, shutterHasBeenPressed
has been set to False
and the condition that follows is verified so that we enter the if
.
the program keeps running until, unexpectedly, the button is pressed. Say, it reached <here>
:
while True:
global shutterHasBeenPressed
shutterHasBeenPressed = False
#Stay in loop until button is pressed
if shutterHasBeenPressed is False:
i += 1
if i == blink_speed:
overlay_2.alpha = 255 # <here>
elif i == (2 * blink_speed):
overlay_2.alpha = 0
i = 0
#Restart while loop
sleep(0.1)
continue
#button has been pressed!
print("Button Pressed!")
At this point, shutterPressed
runs, sets shutterHasBeenPressed
to True
. Then, back in our loop, the iteration finishes, we continue
at the start of the loop and ... what's there?!
shutterHasBeenPressed = False
and the button press just went completely unnoticed!
I believe this answers your question asking what you have got wrong.