Introduction: Improved 'Simon Says' Code

Picture of Improved 'Simon Says' Code

An updated 'Simple Simon' project.

Specifically, easier to work with software implementation.

Step 1: Getting Started

Picture of Getting Started

I started with the instructable at 'Simple-Simon-Says-Game'

Refer to it for general hardware implementation.

As I already had done a project of my own which had 4 buttons, 4 LEDs and a speaker, I used that hardware (seen above). There is an LCD display under a tape, as it is not used by this project.

It uses an Nano 3.0 and I used different pin assignments for the peripherals.

By the way, you may also be interested in a hardware simplified version I did Instructables.com/id/Fast-Easy-Simon

Step 2: Adapting to New Hardware

The Simon_Says sketch did not work for me as the code relied on fix pin assignments. Further the code was hard to follow and had some bugs.

So I created this updated version.

  • Fixed the miss use of type 'boolean' for pin numbers
  • Modified the code so that it will work for any LED & button pin assignments.
  • The logic flow was overly complicated and in spots too repetitive, causing it to be hard to understand and debug. So I simplified it for the most part.
  • Along with other improvements like the fact that I changed the 'Tone' class object's name from 'speakerpin' to 'speaker' and created a byte variable 'speakerpin' for its pin # assignment.
  • Oct 2015: allowed for fast button input sequences

A download link for my updated sketch is included here. You should find it easy to get going with your own hardware by simply changing pin assignments near the beginning of the code. Download and have fun with it.

Step 3: By Popular Demand

As there has been queries about how to use the software with a servo to operate a latch when a successful set of Simon pattern matching is done. I am including here versions of 'Simon_Says' as well as the similar 'Simon_Sings' which I adapted to be suitable for further modification with appropriate servo code. I have placed '@TODO' comments in the code of each showing where to put one's servo code.

The exact coding will be dependent on the hardware implementation and the servo library one uses. I do not have answers for servo particular issues. For that, I recommend reviewing the likes of the following:
video: How to control servos
instructables.com/id/Arduino-Servo-Motors/
instructables.com/id/Access-control-with-Arduino-Keypad-4x4-Servo/
For those needing further servo related help, I recommend a post to the servo related instructable with the most similarities to their servo implementation.

Comments

patrickevelien (author)2015-10-18

hello

i have it working..thanks for that, i want to use this game as a lock..

so when the player has it 6 times good i want to open a servo motor but i dont know how to do it.. can you please help me? thanks

RonM9 (author)patrickevelien2015-10-18

OK. You would need to add code like that below after the line "Serial.print(turn);"

For the coded needed to operate your servo find a project which uses that same hardware-electronics to use as an example.

You may want to use the version 'FastEasy_Simon_Says.ino' of a Simon type game found in https://www.instructables.com/id/Fast-Easy-Simon/ , as among other differences it waits for an input before proceeding and starts off with a pattern of 4 instead of 1.

if (turn==6) {
// !! Here place the code needed to operate the servo latch !!
bool btnPushed = false;
while (! btnPushed) { // wait for a key-press before starting all over
for (int y = 0; y < 4; y++)
{ if (digitalRead(button[y]) == LOW) //Checking for button push
btnPushed = true; }
}
turn = -1; //Reset turn value so the game starts over
exit;
}

RonM9 (author)RonM92015-10-18

Referrence above to 'FastEasy_Simon_Says.ino'

Should be: 'FastEasy_Simon_Sings.ino'

patrickevelien (author)RonM92015-10-20

i did try for a full day to put a servo in...

im a beginner with arduino is it possible that you write it into the arduino code?

this is the code.. thanks 1000 times.

i want the servo on pin 7..

#include <Tone.h>

/*Simon Says game. Now with sound effects.

Originaly made by Robert Spann

Code trimmed and sound effects added by digimike

Ron Miller (aka RonM9) Jun 2015: Removed fixed pin
assignment dependences and simplified code

RRM Oct 2015: allowed for faster button inputs

Buttons are to be set on there designated pins without pull
down resistors

and connected to ground rather then +5.

*/

#include "Tone.h"

Tone speaker;

byte speakerPin = 12; // speaker was on pin 13

int starttune[] = {NOTE_C4, NOTE_F4, NOTE_C4, NOTE_F4,
NOTE_C4, NOTE_F4, NOTE_C4, NOTE_F4, NOTE_G4, NOTE_F4, NOTE_E4, NOTE_F4,
NOTE_G4};

int duration2[] = {100, 200, 100, 200, 100, 400, 100, 100,
100, 100, 200, 100, 500};

int cheer[] = {NOTE_C4, NOTE_C4, NOTE_G4, NOTE_C5, NOTE_G4,
NOTE_C5};

int btnNote[] = {NOTE_G3, NOTE_A3, NOTE_B3, NOTE_C4};

int duration[] = {100, 100, 100, 300, 100, 300};

//boolean button[] = {2, 3, 4, 5}; //The four button input
pins

//boolean ledpin[] = {8, 9, 10, 11}; // LED pins

int button[] = {8, 9, 10, 11}; //The four button input pins
oranje draad

int ledpin[] = {2, 3, 4, 5};
// LED pins geel draad

int turn = 0; // turn
counter

int buttonstate = 0;
// button state checker

int randomArray[100]; //Intentionally long to store up to
100 inputs (doubtful anyone will get this far)

int inputArray[100];

// ===================================================

void setup()

{

int note;

Serial.begin(9600);


speaker.begin(speakerPin);

for (int x = 0; x
< 4; x++) // LED pins are outputs

{

pinMode(ledpin[x],
OUTPUT);

pinMode(button[x],
INPUT); // button pins are inputs


digitalWrite(button[x], HIGH); //
enable internal pullup; buttons start in high position; logic reversed

}


randomSeed(analogRead(0)); //Added to generate "more randomness"
with the randomArray for the output function

for (int thisNote =
0; thisNote < 13; thisNote ++) {

// play the next
note:

note =
starttune[thisNote];


speaker.play(note);

if (note ==
NOTE_C4) digitalWrite(ledpin[0],
HIGH);

else if (note ==
NOTE_F4) digitalWrite(ledpin[1], HIGH);

else if (note ==
NOTE_G4) digitalWrite(ledpin[2], HIGH);

else if (note ==
NOTE_E4) digitalWrite(ledpin[3], HIGH);

// hold the note:


delay(duration2[thisNote]);

// stop for the
next note:

speaker.stop();

allLEDs(LOW);

delay(25);

}

delay(1000);

}

// ========================================================

void loop() // This
'loop' is automatically ran repeatedly

{

for (int level = 0;
level <= 99; level++)

{

allLEDs(HIGH);

for (int thisNote
= 0; thisNote < 6; thisNote ++) {

// play the next
note:


speaker.play(cheer[thisNote]);

// hold the
note:


delay(duration[thisNote]);

// stop for the
next note:

speaker.stop();

delay(25);

}

allLEDs(LOW);

delay(1000);


Serial.print("\n Turn: ");
// Some serial output to follow along


Serial.print(turn);

// fill up the
array to be matched by the player

randomArray[turn]
= random(1, 5); //Assigning a random number (1-4) to the randomArray[turn
count]


Serial.print(" Rand#:
");


Serial.println(randomArray[turn]);

for (int x = 0; x
<= turn; x++)

{


Serial.print(randomArray[x]);

byte btn =
randomArray[x]; // logical button/led #
(1-4)


digitalWrite(ledpin[btn - 1], HIGH);


speaker.play(btnNote[btn - 1], 100);

delay(400);


digitalWrite(ledpin[btn - 1], LOW);

delay(100);

}

input();

}

}

// ===================================================

// local
functions

void input() { //Function for allowing user input and
checking input against the generated array

bool btnPushed;

for (int x = 0; x
<= turn; x++)

{ // for each one in
the current sequence wait for a button to be pushed

// if it is the
correct one we keep looping through the sequence

btnPushed = false;

while (!
btnPushed) {

for (int y = 0;
y < 4; y++)

{

buttonstate =
digitalRead(button[y]);

byte btn = y +
1; // logical button # (1-4)

if
(buttonstate == LOW) //Checking for
button push

{

btnPushed =
true;


digitalWrite(ledpin[y], HIGH);


speaker.play(btnNote[btn - 1], 100);


delay(100); // insures minimum
LED illumination


inputArray[x] = btn;


Serial.print(" btn pushed:
");


Serial.print(btn);

// was a poor way to allow for button release: delay(250);


wait_BtnRelease();


digitalWrite(ledpin[y], LOW);

if
(inputArray[x] != randomArray[x]) { //Checks value input by user and checks it
against


fail();
//the value in the same spot on the generated array

//The fail
function is called if it does not match

exit;

}

}

}

} // end while

}

delay(500);

turn++; //Increments
the turn count, also the last action before starting the output function over
again

}

// ------------------------------------------------------

void fail() { //Function used if the player fails to match
the sequence

for (int y = 0; y
<= 2; y++)

{ //Flashes lights
for failure

allLEDs(HIGH);


speaker.play(NOTE_G3, 300);

delay(200);

allLEDs(LOW);


speaker.play(NOTE_C3, 300);

delay(200);

}

delay(500);

turn = -1; //Resets
turn value so the game starts over without need for a reset button

}

// ------------------------------------------------------

void allLEDs(byte state) {


digitalWrite(ledpin[0], state);

digitalWrite(ledpin[1],
state);


digitalWrite(ledpin[2], state);


digitalWrite(ledpin[3], state);

}

void wait_BtnRelease() {

bool
btnStillDown=true;

while
(btnStillDown) {

btnStillDown =
false;

for (int y = 0;
y < 4; y++)

{

buttonstate =
digitalRead(button[y]);

if
(buttonstate == LOW) //Checking for
button push

btnStillDown
= true;

}

}

}

RonM9 (author)patrickevelien2016-03-26

Patrick, did you ever get your project working?

Since our last communication I have added a section to this instructable, titled 'By popular demand'. You may find this a little more helpful &/or interesting.

OndřejT4 (author)RonM92016-03-26

Hi...i am trying to add same servo function like patrickevelien. When I put code to servo open/close right behind void setup(), servo operate correctly and after that game starts, But when I put code behind if (turn==6) { nothing happend. When I put here for example allLEDs(HIGH); , this works. Can you give me some advice please?

/*Simon Says game. Now with sound effects.

Originaly made by Robert Spann

Code trimmed and sound effects added by digimike

Ron Miller (aka RonM9) Jun 2015: Removed fixed pin assignment dependences and simplified code

RRM Oct 2015: allowed for faster button inputs

Buttons are to be set on there designated pins without pull down resistors

and connected to ground rather then +5.

*/

#include <Tone.h>

Tone speaker;

#include <ServoTimer2.h>

ServoTimer2 a;

byte speakerPin = 12; // speaker was on pin 13

int starttune[] = {NOTE_C4, NOTE_F4, NOTE_C4, NOTE_F4, NOTE_C4, NOTE_F4, NOTE_C4, NOTE_F4, NOTE_G4, NOTE_F4, NOTE_E4, NOTE_F4, NOTE_G4};

int duration2[] = {100, 200, 100, 200, 100, 400, 100, 100, 100, 100, 200, 100, 500};

int cheer[] = {NOTE_C4, NOTE_C4, NOTE_G4, NOTE_C5, NOTE_G4, NOTE_C5};

int btnNote[] = {NOTE_G3, NOTE_A3, NOTE_B3, NOTE_C4};

int duration[] = {100, 100, 100, 300, 100, 300};

//boolean button[] = {2, 3, 4, 5}; //The four button input pins

//boolean ledpin[] = {8, 9, 10, 11}; // LED pins

int button[] = {5, 6, 7, 8}; //The four button input pins

int ledpin[] = {2, 3, 17, 16}; // LED pins

int turn = 0; // turn counter

int buttonstate = 0; // button state checker

int randomArray[100]; //Intentionally long to store up to 100 inputs (doubtful anyone will get this far)

int inputArray[100];

// ===================================================

void setup()

{

a.attach(9);

a.write(2000);

delay(2000);

a.write(1000);

delay(2000);

int note;

Serial.begin(9600);

speaker.begin(speakerPin);

for (int x = 0; x < 4; x++) // LED pins are outputs

{

pinMode(ledpin[x], OUTPUT);

pinMode(button[x], INPUT); // button pins are inputs

digitalWrite(button[x], HIGH); // enable internal pullup; buttons start in high position; logic reversed

}

randomSeed(analogRead(0)); //Added to generate "more randomness" with the randomArray for the output function

for (int thisNote = 0; thisNote < 13; thisNote ++) {

// play the next note:

note = starttune[thisNote];

speaker.play(note);

if (note == NOTE_C4) digitalWrite(ledpin[0], HIGH);

else if (note == NOTE_F4) digitalWrite(ledpin[1], HIGH);

else if (note == NOTE_G4) digitalWrite(ledpin[2], HIGH);

else if (note == NOTE_E4) digitalWrite(ledpin[3], HIGH);

// hold the note:

delay(duration2[thisNote]);

// stop for the next note:

speaker.stop();

allLEDs(LOW);

delay(25);

}

delay(1000);

}

// ========================================================

void loop() // This 'loop' is automatically ran repeatedly

{

for (int level = 0; level <= 99; level++)

{

allLEDs(HIGH);

for (int thisNote = 0; thisNote < 6; thisNote ++) {

// play the next note:

speaker.play(cheer[thisNote]);

// hold the note:

delay(duration[thisNote]);

// stop for the next note:

speaker.stop();

delay(25);

}

allLEDs(LOW);

delay(1000);

Serial.print("\n Turn: "); // Some serial output to follow along

Serial.print(turn);

// fill up the array to be matched by the player

if (turn==2) {

// HERE ADD SERVO OPEN/CLOSE

bool btnPushed = false;

while (! btnPushed) { // wait for a key-press before starting all over

for (int y = 0; y < 4; y++)

{ if (digitalRead(button[y]) == LOW) //Checking for button push

btnPushed = true; }

}

turn = -1; //Reset turn value so the game starts over

exit;

}

randomArray[turn] = random(1, 5); //Assigning a random number (1-4) to the randomArray[turn count]

Serial.print(" Rand#: ");

Serial.println(randomArray[turn]);

for (int x = 0; x <= turn; x++)

{

Serial.print(randomArray[x]);

byte btn = randomArray[x]; // logical button/led # (1-4)

digitalWrite(ledpin[btn - 1], HIGH);

speaker.play(btnNote[btn - 1], 100);

delay(400);

digitalWrite(ledpin[btn - 1], LOW);

delay(100);

}

input();

}

}

// ===================================================

// local functions

void input() { //Function for allowing user input and checking input against the generated array

bool btnPushed;

for (int x = 0; x <= turn; x++)

{ // for each one in the current sequence wait for a button to be pushed

// if it is the correct one we keep looping through the sequence

btnPushed = false;

while (! btnPushed) {

for (int y = 0; y < 4; y++)

{

buttonstate = digitalRead(button[y]);

byte btn = y + 1; // logical button # (1-4)

if (buttonstate == LOW) //Checking for button push

{

btnPushed = true;

digitalWrite(ledpin[y], HIGH);

speaker.play(btnNote[btn - 1], 100);

delay(100); // insures minimum LED illumination

inputArray[x] = btn;

Serial.print(" btn pushed: ");

Serial.print(btn);

// was a poor way to allow for button release: delay(250);

wait_BtnRelease(); // much better this way

digitalWrite(ledpin[y], LOW);

if (inputArray[x] != randomArray[x]) { //Checks value input by user and checks it against

fail(); //the value in the same spot on the generated array

//The fail function is called if it does not match

exit;

}

}

}

} // end while

}

delay(500);

turn++; //Increments the turn count, also the last action before starting the output function over again

}

// ------------------------------------------------------

void fail() { //Function used if the player fails to match the sequence

for (int y = 0; y <= 2; y++)

{ //Flashes lights for failure

allLEDs(HIGH);

speaker.play(NOTE_G3, 300);

delay(200);

allLEDs(LOW);

speaker.play(NOTE_C3, 300);

delay(200);

}

delay(500);

turn = -1; //Resets turn value so the game starts over without need for a reset button

}

// ------------------------------------------------------

void allLEDs(byte state) {

digitalWrite(ledpin[0], state);

digitalWrite(ledpin[1], state);

digitalWrite(ledpin[2], state);

digitalWrite(ledpin[3], state);

}

void wait_BtnRelease() {

bool btnStillDown;

int debounce=0; // need depends on button used. mine caused some double trips

while (debounce<2) {

delay(5);

btnStillDown = false;

for (int y = 0; y < 4; y++)

{

buttonstate = digitalRead(button[y]);

if (buttonstate == LOW) //Checking for button push

btnStillDown = true;

}

if (btnStillDown) debounce=0;

else debounce++;

}

}

RonM9 (author)OndřejT42016-03-26

Thanks for your interest in this instructable.

It looks like you have not placed the needed servo control code where this line is located: // HERE ADD SERVO ...

I also noticed you are using a different servo library than what I see others using; and your initialization code in setup() looks odd to me.

I have added a version of the .ino code with the idea of being modified for use to operate a latch, with better comments regarding placement of servo support code. Please see the added section to this instructable, titled 'By popular demand'. I hope this gets you going in the right direction.

Looking forward to hearing about your success.

MiguelD13 (author)2016-01-18

C:\Users\user\Downloads\Compressed\Simon_Says\Tone\Tone\Simon_Says\Simon_Says.ino:9:18: fatal error: Tone.h: No such file or directory

#include <Tone.h>

^

compilation terminated.

exit status 1

Error compiling.

This report would have more information with

"Show verbose output during compilation"

enabled in File > Preferences.


Can you help me with this? TIA =)

RonM9 (author)MiguelD132016-01-18

It is not finding 'Tone.h'. So the compiler is looking in the wrong places, or the file is in the wrong place or it is missing. The Arduino IDE comes with an Examples/Tone/ToneTest sketch which uses Tone.h from Sketchbook/libraries/Tone. You probably need to reinstall the latest IDE to get this sketch as well as the ToneTest sketch to build.

About This Instructable

3,356views

10favorites

License:

Bio: Professional Software, Hardware, Systems Engineer for more than 40 years. Amateur Radio HAM (KI7NEW)
More by RonM9:Make G25 FAIRY Light BULBs for HalloweenSignal Code Communicators (RFM69)Dual Power for Your Portable Micro-Controller Project
Add instructable to: