Simon Says Game
Students will use the circuit from the previous lab to build a simple game. The LEDs will light up in a sequence. The user will need to imitate the sequence by pushing buttons associated with the LEDs. Each time the user correctly pushed the buttons the computer will add to the sequence. The sequence will be created with a random number generator. If the user fails or correctly plays back the sequence, sound or visual signals could be displayed.
Learning outcome: Writing a full sized computer program. Applying State Machine concept.
Assignment
This assignment is intended for you to become familiar with the Raspberry Pi, Python and GPIO interface using a simple circuits and a real working application.
Example
An online version of the application is the game that can be played in a web browser at: http://www.freesimon.org/
PLEASE READ SAFETY AT THE BOTTOM OF THIS DOCUMENT.
Instructions
Lecture Slides: Game Summary
Video (1): Intro Simons Says
Video (2): Simon Says Programming
Submission
Minimum to submit:
Circuit Schematic (as shown in class and laboratory)
Proof of Construction (4 LEDs, 4 buttons, minimum is all working in hardware and software)
Proof of Operation (playing the game, short and long presses detected as single press, failed sequence, correct sequence, length of sequence, additional elements such as score or buzzer, minimal is no additional features)
Python Code (organization and commenting, minimum is minimal comments)
Grading
The minimum expected game has at least two buttons and two LEDs.
What the grades mean:
A – Exemplary, far beyond requirements/expectations
B – Exceeds requirements/expectations
C – Meets requirements/expectations
D – Falls short of requirements/expectations
F – Substantially does not meet requirements/expectations
Simply completing the laboratories/assignments will result in a grade of “C”. Students must extend the work in one or more directions (additional hardware, software, designs, and/or analyses, etc) in substantial ways, and/or submit exceedingly good documentation/write-ups with exceptional presentation to receive higher grades.
Example additional work is "fun lights" if users plays new high-score, playing sound when keys are pressed or score increases, more than 2 LEDs and buttons etc. For sound you would need to lookup sound output in python with Raspberry Pi (Jessie) (http://www.pygame.org/).
A helpful rule of thumb is that the additional hardware/software/designs/analyses should be approximately half again as much intellectual and implementation effort as the main assignment. Please discuss your plans for additions with the instructor if you have any questions.
Safety
Safety reminder for building real circuits: Before energizing (powering on) your circuit, ask the instructor to review your schematic and your physical bread boarded circuit. This review should happen before you energize your circuit each time there is a change in the circuit. This review can happen after class, or during class as appropriate.
Example Pseudo Code
There is no single "correct" program. Please practice using state machine concept. You are already familiar with reading and setting GPIO pins. To debug your program use the debugger as shown in class. On the debugger command line, when the program is stopped, you can probe variables by for example entering print(sequence).
P.S. If this assignment would call for commercial grade software, you would use events which are triggered if any button is pressed, but we are not introducing this concept here.
Main Program as Statemachine
Principle: You have global variable describing the state. You call functions that advance the state depending what is happening in them.
##################################################
# Forever loop
##################################################
state = "startUp"
while True:
if state == "startUp":
state = startUp()
elif state == "appendSequence":
state, sequence = appendSequnce(sequence)
elif state == ""userSequenceInput":
state = userSequenceInput()
elif ...
elif state == "idle":
time.sleep(0.01)
state = checkifUserwantstoPlay() # maybe include a hello show,
elif state == "exit":
break
else:
pass # we should never end up here
# Close GPIO
Header of the Program
Here you put description and define global variables.
#####################################################
# Simon Says Game
# BME 210
# Urs Utzinger 2023
######################################################
# Importing libraries
import time # import timing
import RPi.GPIO as GPIO # import Raspberry Pi input out put
import random # import random number generator
# Global Variables
# Buttons
red_button = 12
green_button = 14
yellow_button =
blue_button =
# LEDs
red_LED = 24
green_LED = 27
yellow_LED =
blue_LED =
# Simplifications
PUSHED = True
NOT_PUSHED = False
ON = GPIO.HIGH
OFF = GPIO.LOW
# Sequence List
sequence = [] # empty List
Functions
Logically organized sections of your code. If you use statemachine, they need to advance the state.
###################################################
# Custom Functions
##################################################
def startUP():
'''
Initialize GPIO and random number generator
'''
GPIO.setmode(GPIO.BCM)
# LED is output
GPIO.setup(yellow_LED, GPIO.OUT)
# Button is input
GPIO.setup(yellow_button, GPIO.IN) #figure out the correct statements
# initialize random number generator
random.seed()
# when we are done, next step is idling
return "idle"
def appendSequence(sequence):
'''
Append new random number to sequence
'''
sequence.append(random.randomrange(0,4,1))
return "displaySequence", sequence
def displaySquence(sequence, wait_time):
'''
Display sequence
'''
for element in sequence:
turn on LED corresponding to element
time.sleep(wait_time)
turn off LED corresponing to element
time.sleep(wait_time)
return "userInput"
User Input
Deal with button debouncing. Check if correct buttons were pressed.
def userInput(sequence):
'''
Wait until user presses button
Wait until user releases button
Check if button is the right one
'''
for expectedButton in sequence:
# wait until button is pressed:
pressed = False
while not pressed:
B1 = GPIO.input(red_button)
B2 = GPIO.input(green_button)
...
pressed = (B1 == PUSHED) or (B2 == PUSHED) or (B3 == PUSHED)
# decode which button was pressed
button = -1
if B1 == PUSHED: #
button = 1
elif B2 == PUSHED: # This depends on how you setup your circuit
button = 2
elif ...
# wait 10ms % for debounce
time.sleep(0.01)
# wait until button is released:
pressed = True
while pressed:
B1 = GPIO.input(...)
B2 = ...
pressed = ...
# Check if button is the expected one
if not (expectedButton == button):
# oh no, exit function
return "failure"
# do some dancing
success()
return "success"
Instructors full program (2023): Simon Says.py