Click here to Skip to main content
Click here to Skip to main content

Arduino Platform - SIMON Game Implementation

By , 27 Oct 2009
 

Arduino Simon Schematic

Introduction

Having been a CodeProject member for several years, and not having got round to ever publishing an article, left me feeling a bit disappointed in myself. I have thought many a time on what kind of article I can produce. Then after coming across some great articles by jeffb42 here on CodeProject, my problem was solved.

I started playing with the Arduino hardware platform about two months ago, after looking for something suitable for a couple of projects I had in mind for use in the house. In order to get to the stage of being able to make use of the device, I had to first get to know its capabilities.

This article will be looking at how to overcame the problem of running a SIMON game clone using the Arduino platform, as this demonstrates methods of dealing with the main application Loop constraint and code reuse on this hardware platform.

For those of you not familiar with SIMON, this was an early electronics game from the 70's, where the user basically had to repeat back a sequence to the console to progress to the next level. In my implementation of the game, the user can play the Progressive Mode, where the game re-uses the previous level as the start of the next level before adding a random step at the end, or Random Mode, where every level of the game produces a new random sequence, each step longer than the previous.

jeffb42's Introduction to Arduino and Interfacing with LCD articles provide more details on the Arduino platform specifics, and on my website, I have various examples of some of the IO basics, so there is no need to repeat this here.

Background

The challenge to building this game on the Arduino is the way in which the platform works. Within the source code, there are three areas in which to place code: the initialisation area, the setup method, and the loop method. These are executed in that order.

//initialisation section
// Library references and variable/constant declarations contained here

void setup()
{
    //This method runs once
    //Hardware allocation done here e.g. input/output pin directions
}

void loop()
{
    //This method will run until power is removed or a new program is 
    //uploaded to the platform
}

The challenge is being able to make the code operate in such a way that a game can be played over and over again, in either of the two modes, without ever leaving a never ending loop.

Using the Code

The schematic of the hardware requirements is included in the download file, as well as the source code. If you own the necessary components, you can build the game and upload the code to the Arduino to make it work. Alternatively, if you are just starting out with the platform or something similar, the code may provide you with ideas on how to achieve similar goals in your own projects.

The Game Structure

We need to be able to keep the game code running within an endless loop, and one method to achieve this is by using flags. Boolean variables which are either True or False is one of the easiest ways to achieve this. Looking at how the game works, there are a few basic flags that are required. They hold the state of the game, i.e., has it started, has it been played, and if the game is now over. A couple of other variables are also required to keep track of what the sequence of steps generated is and what level the user is currently on. These requirements as well as the hardware pin allocations are identified in the initialisation section of the code:

#include <LiquidCrystal.h>

//initialise the library with the numbers of the interface pins
LiquidCrystal lcd(13,12,11,10,9,8);

int userInput = 0;      //Analog pin for user input from buttons
int led1 = 2;           //LED 1
int led2 = 3;           //LED 2
int led3 = 4;           //LED 3
int led4 = 5;           //LED 4
int speaker = 6;        //Speaker

//Game Stats
boolean started = false;    //Has the game started yet
boolean gameover = false;   //Has the game ended
int level = 0;              //What level is the user on (Score at end = level -1)

int gameMode = 0;           //Which game mode is being used
                            // 1 = Progressive
                            // 2 = Random
                            
boolean soundEnabled = true;  //Is the sound enabled or not
                            
int lastLevelSeq[50];        //The sequence for the steps used
                             //in progressive mode previous level
                             //Also used by game over to replay correct sequence back
                             //Nobody can get passed 50, surely!

The next section of the code is the setup() method. This is where the hardware pins are initialised.

void setup()
{
  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
  pinMode(led3, OUTPUT);
  pinMode(led4, OUTPUT);
  pinMode(speaker, OUTPUT);
  
  //Set up the LCD Col and Row count
  lcd.begin(16,2);
  delay(100);
  lcd.clear();
  lcd.print("Welcome to");
  lcd.setCursor(0,1);
  lcd.print("Arduino SIMON");
  
  //...........rest of setup code snipped. see the download.

From here, the next thing that is executed is the loop() method, which is run endlessly, hence the requirement to keep track of the game status. Also, to keep the code shorter and more efficient, a number of helper methods are used to meet the reuse requirements mentioned at the start of the article.

//used to determine which button the user is pressing
getButtonPressed()
//Play a given sound
playTone(tone)
//This is the actual game level, it returns boolean true
//is user success or false if user failed
doLevel(level)
//Turn on a given led, or 0 to turn them all off
lightLed(led)
//This will play a sound and light the appropriate 
//led using the other helper methods
playStep(step)

The main loop() structure looks like the following (all the details have been stripped to leave the structure):

void loop()
{        
    while (started == false)
    {
      if (getButtonPressed() > 0)
      {
        //This part waits for the user to press a button to start the game
      }
    }
     
    while (gameMode == 0)
    {     
      switch (getButtonPressed())
      {
      case 1:
            //The user pressed button 1 for Progressive Mode
        break;
       
      case 2:
            //The user pressed button 2 for Random Mode
        break;
      
      case 4:
        soundEnabled = (!soundEnabled);
        //The user user is pressing Button 4 toggling the sound on and off
        break;  
      }
    }    
     
    while (gameover == false)
    {
      if (doLevel(level)==true)
        {
            //The user played a level and got it correct
        } 
       else
        {
            //Level Wrong, set game over
        }  
    }
    
    if (gameover == true)
    {
      //The game is now over, playback the correct sequence
    }
      
    //Wait for user
    while (gameover == true)
    {
       if (getButtonPressed() > 0)
        {
            //Wait for the user to press a button to go back to the start menu
        }        
    }     
}

The easiest way of coming up with a structure is to play the game in your head and write down in blocks each step that is required; from this, you can build a flow diagram and then the code structure.

Points of Interest

Given the limited number of digital IO pins available, the four buttons were actually linked through a resistor network onto an analog input pin. Each button pressed will change the value of the analog input; from this value, it is then possible to determine which button is pressed, using the getButtonPressed() method. Also, some variance may occur through fluctuations of the analog signal, and suitable resistor sizes must be used to give sufficient spacing of the input values:

/*
Read the analog input and determine which button is pressed
*/  
int getButtonPressed()
{
    // What is the pushbutton resistor matrix value
    int userValue = 0;
    userValue = analogRead(userInput);
    
    int buttonPressed = 0;
      
    if (userValue > 850)
    {
      buttonPressed = 0;
      //No Button Pressed
    }
    if (userValue < 850)
    { 
      buttonPressed = 4;
      // Maybe Button 4 still to check others
    }
    if (userValue < 800)
    {
      buttonPressed = 3;
      // Maybe Button 3 still to check others
    }
    if (userValue < 700)
    {
      buttonPressed = 2;
      // Maybe Button 2 still to check last one
    }
    if (userValue < 600)
    {
      buttonPressed = 1;
      // Done Checking buttons
    }
    return buttonPressed;  
}

Overall, as a first project on the Arduino for myself, this gave me a good challenge into coming up with a suitably structured code that met the game requirements.

History

  • 25th October 2009- First version of the article.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

DaveAuld
Engineer Apache North Sea Ltd.
United Kingdom United Kingdom
Member
I have been working in the Oil & Gas Industry for over 20 years now.
 
Core Discipline is Instrumentation and Control Systems.
 
Completed Bsc Honours Degree (B29 in Computing) with the Open University in 2012.
 
Currently, Offshore Installation Manager for the Forties Charlie Platform, which is located ~110Miles NE of Aberdeen, Scotland in the North Sea.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralMy vote of 5memberStephen Wiria5 May '11 - 0:12 
Nice article and video Dave!
GeneralRe: My vote of 5memberDaveAuld5 May '11 - 0:31 
Thanks.
 
I actually need to get my finger out and remake it for the V2 code.
 
I also had someone else create additional features for a V3 and V4 via my website, so maybe need to look at incorporating their suggestions and code mods.
Dave
Find Me On: Web|Facebook|Twitter|LinkedIn

Folding Stats: Team CodeProject

GeneralRe: My vote of 5memberStephen Wiria5 May '11 - 0:44 
I did create an experiment with Arduino 3 months ago, controlling Tamiya mini RC from Nokia N8. It was very rough.
Arduino Uno - N8[^]
It's so fun!
 
Can't wait to see more Arduino articles from you!
GeneralMy vote of 1memberaasser1 May '10 - 8:43 
Irrelevant
GeneralRe: My vote of 1mvpPete O'Hanlon7 May '10 - 0:45 
aasser wrote:
Irrelevant

 
As is your comment. Simply posting a stupid comment isn't going to help the author understand how to improve his article, so why did you do it?

"WPF has many lovers. It's a veritable porn star!" - Josh Smith

As Braveheart once said, "You can take our freedom but you'll never take our Hobnobs!" - Martin Hughes.

My blog | My articles | MoXAML PowerToys | Onyx



GeneralRe: My vote of 1memberdaveauld7 May '10 - 3:59 
Pete,
 
Cheers, it was a revenge attack following an answer i gave to one of his Q&A's relating to writing a bot to break captchas. He's done the same in my other article as well.
 
kids, you just got to love em.
Dave
 
Don't forget to rate messages!
Find Me On: Web|Facebook|Twitter|LinkedIn
Waving? dave.m.auld[at]googlewave.com


GeneralRe: My vote of 1mentorTrollslayer7 May '10 - 4:40 
Count the votes.
Join the cool kids - Come fold with us[^]

GeneralVideo suggestionmemberjeffb4211 Nov '09 - 6:08 
Hi Dave,
 
Nice article, and thanks for enjoying the articles I wrote. It's pretty cool to see the work one has done lead to inspire others.
 
Anyway, have you thought about making a video of your Simon game in action? You might consider creating a video, posting it to YouTube, and then updating your article with a link to the video, or embed the video directly (it's pretty easy to do). That would be a pretty cool demonstration of the project you made.
 
Nice job with the article BTW.
 
Jeff
GeneralRe: Video suggestionmemberdaveauld12 Nov '09 - 1:33 
There is a video on Youtube of the Version 1 code.
 
Version 1 was random levels only, and didn't have the progressive game mode.
 
The video is here[^]
 
Dare say i will have to get round to making a version 2 video at some point.
 
Dave
Who am I?:
Web|Facebook|Twitter|LinkedIn|Bebo

GeneralGood Stuffmembermichael presutti30 Oct '09 - 2:11 
Good article,
I recently picked up an Arduino board myself and having quite a bit of fun with it.
 
Looking forward to more posts.
GeneralRe: Good Stuffmemberdaveauld30 Oct '09 - 2:14 
Thanks,
 
When i get home from work in a week, i'm going to get back with interfacing a Logic3 Wireless Wii Nun-chuck to the arduino, so the next one might feature something to do with that, but who knows!
 
Cheers,
dave
 
Dave
Who am I?:
Web|Facebook|Twitter|LinkedIn|Bebo

QuestionWhat's up with the if's?memberjeroen de dauw29 Oct '09 - 2:23 
Hey,
 
Why are you not using a switch here, and reverse the order of checks? This seems a pretty weird approach to me.
 
    if (userValue < 850)
    { 
      buttonPressed = 4;
      // Maybe Button 4 still to check others
    }
    if (userValue < 800)
    {
      buttonPressed = 3;
      // Maybe Button 3 still to check others
    }
    if (userValue < 700)
    {
      buttonPressed = 2;
      // Maybe Button 2 still to check last one
    }
    if (userValue < 600)
    {
      buttonPressed = 1;
      // Done Checking buttons
    }
 
Cheers!
 
Jeroen De Dauw
---
Forums ; Blog ; Wiki
---
70 72 6F 67 72 61 6D 6D 69 6E 67 20 34 20 6C 69 66 65!

AnswerRe: What's up with the if's?memberdaveauld29 Oct '09 - 2:54 
Like many things, there are many ways to achieve the same goal.
 
Add the end of the day it is functional, clean and more importantly it works!
 
There is vey little to be gained by using a switch in terms of execution cycles, so was happy to do it this way. I probably just happened to write it using the if's to start with and just left it.
 
Dave
Who am I?:
Web|Facebook|Twitter|LinkedIn|Bebo

GeneralRe: What's up with the if's?memberjeroen de dauw29 Oct '09 - 3:21 
I'd reverse the order of the if's. But if it's only executed once, you're probably right.
 
Jeroen De Dauw
---
Forums ; Blog ; Wiki
---
70 72 6F 67 72 61 6D 6D 69 6E 67 20 34 20 6C 69 66 65!

GeneralRe: What's up with the if's?memberjeffb4211 Nov '09 - 5:59 
I haven't ran the code, but using the ifs instead of a switch might be because it's reading input from analog devices, and if for example button 4 is pressed it might register as 840, not 850. I agree with you about the reverse order though. Right now, if userValue is less than 600, buttonPressed gets assigned five times:
 

// userValue = 550
if (userValue > 850)
{
buttonPressed = 0;
//yes, buttonPressed is assigned 0
}
if (userValue < 850)
{
buttonPressed = 4;
//yes, buttonPressed is assigned 4
}
if (userValue < 800)
{
buttonPressed = 3;
//yes, buttonPressed is assigned 3
}
if (userValue < 700)
{
buttonPressed = 2;
//yes, buttonPressed is assigned 2
}
if (userValue < 600)
{
buttonPressed = 1;
//yes, buttonPressed is assigned 1
}

 

Not the end of the world, but I'd suggest reversing the order, and also changing it from a series of ifs to use if/else if.
 

Jeff
GeneralNice Workmembersam.hill28 Oct '09 - 10:29 
It's great to see more embedded projects like this!
GeneralRe: Nice Workmemberdaveauld28 Oct '09 - 10:33 
Thanks for the vote of confidence!
 
As this was my first article on CP, I wasn't sure on how much to include from a code point of view. Also, it can be difficult to put into words what is going through my head.
 
Anyway, hope i got the balance right in the content.
 
Just have to think about what I will do next Smile | :)
 
Dave
Who am I?:
Web|Facebook|Twitter|LinkedIn|Bebo

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web01 | 2.6.130523.1 | Last Updated 27 Oct 2009
Article Copyright 2009 by DaveAuld
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid