Building game show buzzers with a Raspberry Pi
The Main Loop – Lines 70 to 91
Once everything is loaded and initialized, the main loop runs until the program terminates. To begin, set up the loop:
running = True while running == True:
The running
variable is what the while
statement will check. Any code or function that needs to end the program sets running = False
; then, the loop terminates on the next iteration. Any cleanup code is located below the loop, and the program ends. In the code in line 72,
choice = terminal.getch ( 12 , 5 )
terminal.getch
gets one character from the keyboard. The two parameters are the screen coordinates where the character is printed (if echo is turned on). The coordinates are relative to whichever window you call getch
on, in this case, you only have one window.
Because I set terminal.nodelay ( 1 )
when I initialized curses (line 50), terminal.getch
will not block (see "About Blocking Inputs" for more information). If no key press is waiting, then terminal.getch
returns -1
. An if
statement checks for this:
if choice == -1: continue
If there's nothing to do (i.e., no key press), continue
sends the loop back to the top. Once a key press has been received, the program proceeds to the rest of the loop:
if choice == ord ( "1" ): showWinner ( 1 )
The remainder of the main loop is a string of if
/elif
statements that check the key press that was received. If it was a number, it calls showWinner
, which manually shows a winner on the contestant's LCD. This demonstrates what the board looks like when someone buzzes in and provides a manual backup in case of hardware problems.
About Blocking Inputs
If an input blocks, then it will not return until it receives a character. This is often undesirable because your program will be unresponsive. Waiting for a keyboard input might not be so bad, but the same principal applies to network and serial communication. In that case, your program will appear to freeze until data arrives.
To solve this problem, programmers use non-blocking input and integrate input processing into the main loop of the program. Handling this is just one of the tasks, along with updating the screen, checking external inputs, and so on. When a key press (or other communication data) is received, it's added to a buffer, and the main loop continues to run. Eventually, an "I'm done" character (e.g., carriage return) or the appropriate number of bytes will arrive from your data source. Once this happens, your program can process the entire buffer at once, without locking up the user interface.
If the user presses b (line 85) then showWinner
is called again. Instead of passing a specific number, it also calls the getBuzzers
function, which watches for changes in the GPIO (the contestant's buzzers). getBuzzers
won't return (it blocks) until one of the contestant's buttons is pressed. When a contestant buzzes in, her number is passed to showWinner
, which displays the winner on the contestant's LCD.
Pressing r (line 88) resets the system. This step clears the screen on the contestant's LCD, but b must be pressed before the buzzers will respond again. Pressing x (line 90) sets running to False
. This represents the last elif
in the chain, so when the loop recycles it will check and find running
no longer to be true and will exit. Cleanup code located below the loop runs, and then the program ends normally.
Cleanup – Line 93
It's very important to call curses.endwin()
when you're done with curses. If you don't (or if the program crashes), your terminal may be left in an unusual state – echo disabled, strange colors, or worse. With the use of curses.endwin()
, you restore your terminal to whatever state it was in when you launched the program. If your terminal still isn't right, you can type reset
at a shell prompt (even if you can't see characters appearing in the terminal) and press Enter. After a few seconds, you should get a new prompt, and everything should be back to normal.
On the Pygame side of the house, there's not much to do. Pygame cleans up after itself when it sees that your program is ending. It will close the graphics window (if there is one) and uninitialize all of its modules.
Pygame does provide pygame.quit()
, but its use is recommended only when you've finished with your graphics needs but want the remainder of your program to continue running. This might be the case when using Pygame to plot graphs or show pictures but the program is otherwise widget or console based.
Buy this article as PDF
Pages: 8
(incl. VAT)