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.

Simons Says Python Program
Submit you Schematic / Circuit Diagram

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:

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.

Simon Says Rubric 2022

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.

State Machine Simon Says.pptx

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