loading

An updated 'Simple Simon' project.

Specifically, easier to work with software implementation.

Step 1: 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.

<p>hello</p><p>i have it working..thanks for that, i want to use this game as a lock..</p><p>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</p>
<p>OK. You would need to add code like that below after the line &quot;Serial.print(turn);&quot; </p><p>For the coded needed to operate your servo find a project which uses that same hardware-electronics to use as an example.</p><p>You may want to use the version 'FastEasy_Simon_Says.ino' of a Simon type game found in <a href="https://www.instructables.com/id/Fast-Easy-Simon/" rel="nofollow">https://www.instructables.com/id/Fast-Easy-Simon/</a> , as among other differences it waits for an input before proceeding and starts off with a pattern of 4 instead of 1.</p><p><em>if (turn==6) {<br> // !! Here place the code needed to operate the servo latch !!<br> bool btnPushed = false;<br> while (! btnPushed) { // wait for a key-press before starting all over<br> for (int y = 0; y &lt; 4; y++)<br> { if (digitalRead(button[y]) == LOW) //Checking for button push<br> btnPushed = true; }<br> }<br> turn = -1; //Reset turn value so the game starts over<br> exit;<br> }</em></p>
<p>Referrence above to 'FastEasy_Simon_Says.ino'</p><p>Should be: 'FastEasy_Simon_Sings.ino'</p>
<p>i did try for a full day to put a servo in...</p><p>im a beginner with arduino is it possible that you write it into the arduino code?</p><p>this is the code.. thanks 1000 times.</p><p>i want the servo on pin 7..</p><p>#include &lt;Tone.h&gt;</p><p>/*Simon Says game. Now with sound effects.</p><p>Originaly made by Robert Spann</p><p>Code trimmed and sound effects added by digimike</p><p>Ron Miller (aka RonM9) Jun 2015: Removed fixed pin<br>assignment dependences and simplified code</p><p>RRM Oct 2015: allowed for faster button inputs</p><p>Buttons are to be set on there designated pins without pull<br>down resistors</p><p>and connected to ground rather then +5.</p><p>*/</p><p>#include &quot;Tone.h&quot;</p><p>Tone speaker;</p><p>byte speakerPin = 12; // speaker was on pin 13</p><p>int starttune[] = {NOTE_C4, NOTE_F4, NOTE_C4, NOTE_F4,<br>NOTE_C4, NOTE_F4, NOTE_C4, NOTE_F4, NOTE_G4, NOTE_F4, NOTE_E4, NOTE_F4,<br>NOTE_G4};</p><p>int duration2[] = {100, 200, 100, 200, 100, 400, 100, 100,<br>100, 100, 200, 100, 500};</p><p>int cheer[] = {NOTE_C4, NOTE_C4, NOTE_G4, NOTE_C5, NOTE_G4,<br>NOTE_C5};</p><p>int btnNote[] = {NOTE_G3, NOTE_A3, NOTE_B3, NOTE_C4};</p><p>int duration[] = {100, 100, 100, 300, 100, 300};</p><p>//boolean button[] = {2, 3, 4, 5}; //The four button input<br>pins</p><p>//boolean ledpin[] = {8, 9, 10, 11}; // LED pins</p><p>int button[] = {8, 9, 10, 11}; //The four button input pins<br>oranje draad</p><p>int ledpin[] = {2, 3, 4, 5}; <br>// LED pins geel draad</p><p>int turn = 0; // turn<br>counter</p><p>int buttonstate = 0; <br>// button state checker</p><p>int randomArray[100]; //Intentionally long to store up to<br>100 inputs (doubtful anyone will get this far)</p><p>int inputArray[100];</p><p>// ===================================================</p><p>void setup()</p><p>{</p><p> int note;</p><p> Serial.begin(9600);</p><p> <br>speaker.begin(speakerPin);</p><p> for (int x = 0; x<br>&lt; 4; x++) // LED pins are outputs</p><p> {</p><p> pinMode(ledpin[x],<br>OUTPUT);</p><p> pinMode(button[x],<br>INPUT); // button pins are inputs</p><p> <br>digitalWrite(button[x], HIGH); //<br>enable internal pullup; buttons start in high position; logic reversed</p><p> }</p><p> <br>randomSeed(analogRead(0)); //Added to generate &quot;more randomness&quot;<br>with the randomArray for the output function</p><p> for (int thisNote =<br>0; thisNote &lt; 13; thisNote ++) {</p><p> // play the next<br>note:</p><p> note =<br>starttune[thisNote];</p><p> <br>speaker.play(note);</p><p> if (note ==<br>NOTE_C4) digitalWrite(ledpin[0],<br>HIGH);</p><p> else if (note ==<br>NOTE_F4) digitalWrite(ledpin[1], HIGH);</p><p> else if (note ==<br>NOTE_G4) digitalWrite(ledpin[2], HIGH);</p><p> else if (note ==<br>NOTE_E4) digitalWrite(ledpin[3], HIGH);</p><p> // hold the note:</p><p> <br>delay(duration2[thisNote]);</p><p> // stop for the<br>next note:</p><p> speaker.stop();</p><p> allLEDs(LOW);</p><p> delay(25);</p><p> }</p><p> delay(1000);</p><p>}</p><p>// ========================================================</p><p>void loop() // This<br>'loop' is automatically ran repeatedly</p><p>{</p><p> for (int level = 0;<br>level &lt;= 99; level++)</p><p> {</p><p> allLEDs(HIGH);</p><p> for (int thisNote<br>= 0; thisNote &lt; 6; thisNote ++) {</p><p> // play the next<br>note:</p><p> <br>speaker.play(cheer[thisNote]);</p><p> // hold the<br>note:</p><p> <br>delay(duration[thisNote]);</p><p> // stop for the<br>next note:</p><p> speaker.stop();</p><p> delay(25);</p><p> }</p><p> allLEDs(LOW);</p><p> delay(1000);</p><p> <br>Serial.print(&quot;\n Turn: &quot;); <br>// Some serial output to follow along</p><p> <br>Serial.print(turn);</p><p> // fill up the<br>array to be matched by the player</p><p> randomArray[turn]<br>= random(1, 5); //Assigning a random number (1-4) to the randomArray[turn<br>count]</p><p> <br>Serial.print(&quot; Rand#:<br>&quot;);</p><p> <br>Serial.println(randomArray[turn]);</p><p> for (int x = 0; x<br>&lt;= turn; x++)</p><p> {</p><p> <br>Serial.print(randomArray[x]);</p><p> byte btn =<br>randomArray[x]; // logical button/led #<br>(1-4)</p><p> <br>digitalWrite(ledpin[btn - 1], HIGH);</p><p> <br>speaker.play(btnNote[btn - 1], 100);</p><p> delay(400);</p><p> <br>digitalWrite(ledpin[btn - 1], LOW);</p><p> delay(100);</p><p> }</p><p> input();</p><p> }</p><p>}</p><p>// ===================================================</p><p>// local<br>functions</p><p>void input() { //Function for allowing user input and<br>checking input against the generated array</p><p> bool btnPushed;</p><p> for (int x = 0; x<br>&lt;= turn; x++)</p><p> { // for each one in<br>the current sequence wait for a button to be pushed </p><p> // if it is the<br>correct one we keep looping through the sequence</p><p> btnPushed = false;</p><p> while (!<br>btnPushed) {</p><p> for (int y = 0;<br>y &lt; 4; y++)</p><p> {</p><p> buttonstate =<br>digitalRead(button[y]);</p><p> byte btn = y +<br>1; // logical button # (1-4)</p><p> if<br>(buttonstate == LOW) //Checking for<br>button push</p><p> {</p><p> btnPushed =<br>true;</p><p> <br>digitalWrite(ledpin[y], HIGH);</p><p> <br>speaker.play(btnNote[btn - 1], 100);</p><p> <br>delay(100); // insures minimum<br>LED illumination</p><p> <br>inputArray[x] = btn;</p><p> <br>Serial.print(&quot; btn pushed:<br>&quot;);</p><p> <br>Serial.print(btn);</p><p>// was a poor way to allow for button release: delay(250);</p><p> <br>wait_BtnRelease();</p><p> <br>digitalWrite(ledpin[y], LOW);</p><p> if<br>(inputArray[x] != randomArray[x]) { //Checks value input by user and checks it<br>against</p><p> <br>fail(); <br>//the value in the same spot on the generated array</p><p> //The fail<br>function is called if it does not match</p><p> exit;</p><p> }</p><p> }</p><p> }</p><p> } // end while</p><p> }</p><p> delay(500);</p><p> turn++; //Increments<br>the turn count, also the last action before starting the output function over<br>again</p><p>}</p><p>// ------------------------------------------------------</p><p>void fail() { //Function used if the player fails to match<br>the sequence</p><p> for (int y = 0; y<br>&lt;= 2; y++)</p><p> { //Flashes lights<br>for failure</p><p> allLEDs(HIGH);</p><p> <br>speaker.play(NOTE_G3, 300);</p><p> delay(200);</p><p> allLEDs(LOW);</p><p> <br>speaker.play(NOTE_C3, 300);</p><p> delay(200);</p><p> }</p><p> delay(500);</p><p> turn = -1; //Resets<br>turn value so the game starts over without need for a reset button</p><p>}</p><p>// ------------------------------------------------------</p><p>void allLEDs(byte state) {</p><p> <br>digitalWrite(ledpin[0], state);</p><p> digitalWrite(ledpin[1],<br>state);</p><p> <br>digitalWrite(ledpin[2], state);</p><p> <br>digitalWrite(ledpin[3], state);</p><p>}</p><p>void wait_BtnRelease() {</p><p> bool<br>btnStillDown=true;</p><p> while<br>(btnStillDown) {</p><p> btnStillDown =<br>false;</p><p> for (int y = 0;<br>y &lt; 4; y++)</p><p> {</p><p> buttonstate =<br>digitalRead(button[y]);</p><p> if<br>(buttonstate == LOW) //Checking for<br>button push</p><p> btnStillDown<br>= true;</p><p> }</p><p> }</p><p>}</p>
<p>Patrick, did you ever get your project working?</p><p>Since our last communication I have added a section to this instructable, titled 'By popular demand'. You may find this a little more helpful &amp;/or interesting.</p>
<p>Hi...i am trying to add same servo function like <a href="https://www.instructables.com/member/patrickevelien" rel="nofollow">patrickevelien</a>. 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 <em>if (turn==6) { nothing happend. When I put here for example </em>allLEDs(HIGH); , this works. Can you give me some advice please?</p><p>/*Simon Says game. Now with sound effects.</p><p>Originaly made by Robert Spann</p><p>Code trimmed and sound effects added by digimike</p><p>Ron Miller (aka RonM9) Jun 2015: Removed fixed pin assignment dependences and simplified code</p><p>RRM Oct 2015: allowed for faster button inputs</p><p>Buttons are to be set on there designated pins without pull down resistors</p><p>and connected to ground rather then +5.</p><p>*/</p><p>#include &lt;Tone.h&gt;</p><p>Tone speaker;</p><p>#include &lt;ServoTimer2.h&gt;</p><p>ServoTimer2 a;</p><p>byte speakerPin = 12; // speaker was on pin 13</p><p>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};</p><p>int duration2[] = {100, 200, 100, 200, 100, 400, 100, 100, 100, 100, 200, 100, 500};</p><p>int cheer[] = {NOTE_C4, NOTE_C4, NOTE_G4, NOTE_C5, NOTE_G4, NOTE_C5};</p><p>int btnNote[] = {NOTE_G3, NOTE_A3, NOTE_B3, NOTE_C4};</p><p>int duration[] = {100, 100, 100, 300, 100, 300};</p><p>//boolean button[] = {2, 3, 4, 5}; //The four button input pins</p><p>//boolean ledpin[] = {8, 9, 10, 11}; // LED pins</p><p>int button[] = {5, 6, 7, 8}; //The four button input pins</p><p>int ledpin[] = {2, 3, 17, 16}; // LED pins</p><p>int turn = 0; // turn counter</p><p>int buttonstate = 0; // button state checker</p><p>int randomArray[100]; //Intentionally long to store up to 100 inputs (doubtful anyone will get this far)</p><p>int inputArray[100];</p><p>// ===================================================</p><p>void setup()</p><p>{</p><p> a.attach(9);</p><p> a.write(2000);</p><p> delay(2000);</p><p> a.write(1000);</p><p> delay(2000);</p><p> int note;</p><p> Serial.begin(9600);</p><p> speaker.begin(speakerPin);</p><p> for (int x = 0; x &lt; 4; x++) // LED pins are outputs</p><p> {</p><p> pinMode(ledpin[x], OUTPUT);</p><p> pinMode(button[x], INPUT); // button pins are inputs</p><p> digitalWrite(button[x], HIGH); // enable internal pullup; buttons start in high position; logic reversed</p><p> }</p><p> randomSeed(analogRead(0)); //Added to generate &quot;more randomness&quot; with the randomArray for the output function</p><p> for (int thisNote = 0; thisNote &lt; 13; thisNote ++) {</p><p> // play the next note:</p><p> note = starttune[thisNote];</p><p> speaker.play(note);</p><p> if (note == NOTE_C4) digitalWrite(ledpin[0], HIGH);</p><p> else if (note == NOTE_F4) digitalWrite(ledpin[1], HIGH);</p><p> else if (note == NOTE_G4) digitalWrite(ledpin[2], HIGH);</p><p> else if (note == NOTE_E4) digitalWrite(ledpin[3], HIGH);</p><p> // hold the note:</p><p> delay(duration2[thisNote]);</p><p> // stop for the next note:</p><p> speaker.stop();</p><p> allLEDs(LOW);</p><p> delay(25);</p><p> }</p><p> delay(1000);</p><p>}</p><p>// ========================================================</p><p>void loop() // This 'loop' is automatically ran repeatedly</p><p>{</p><p> for (int level = 0; level &lt;= 99; level++)</p><p> {</p><p> allLEDs(HIGH);</p><p> for (int thisNote = 0; thisNote &lt; 6; thisNote ++) {</p><p> // play the next note:</p><p> speaker.play(cheer[thisNote]);</p><p> // hold the note:</p><p> delay(duration[thisNote]);</p><p> // stop for the next note:</p><p> speaker.stop();</p><p> delay(25);</p><p> }</p><p> allLEDs(LOW);</p><p> delay(1000);</p><p> Serial.print(&quot;\n Turn: &quot;); // Some serial output to follow along</p><p> Serial.print(turn);</p><p> // fill up the array to be matched by the player</p><p> if (turn==2) {</p><p>// HERE ADD SERVO OPEN/CLOSE</p><p>bool btnPushed = false;</p><p>while (! btnPushed) { // wait for a key-press before starting all over</p><p>for (int y = 0; y &lt; 4; y++)</p><p>{ if (digitalRead(button[y]) == LOW) //Checking for button push</p><p>btnPushed = true; }</p><p>}</p><p>turn = -1; //Reset turn value so the game starts over</p><p>exit;</p><p>}</p><p> randomArray[turn] = random(1, 5); //Assigning a random number (1-4) to the randomArray[turn count]</p><p> Serial.print(&quot; Rand#: &quot;);</p><p> Serial.println(randomArray[turn]);</p><p> for (int x = 0; x &lt;= turn; x++)</p><p> {</p><p> Serial.print(randomArray[x]);</p><p> byte btn = randomArray[x]; // logical button/led # (1-4)</p><p> digitalWrite(ledpin[btn - 1], HIGH);</p><p> speaker.play(btnNote[btn - 1], 100);</p><p> delay(400);</p><p> digitalWrite(ledpin[btn - 1], LOW);</p><p> delay(100);</p><p> }</p><p> input();</p><p> }</p><p>}</p><p>// ===================================================</p><p>// local functions</p><p>void input() { //Function for allowing user input and checking input against the generated array</p><p> bool btnPushed;</p><p> for (int x = 0; x &lt;= turn; x++)</p><p> { // for each one in the current sequence wait for a button to be pushed </p><p> // if it is the correct one we keep looping through the sequence</p><p> btnPushed = false;</p><p> while (! btnPushed) {</p><p> for (int y = 0; y &lt; 4; y++)</p><p> {</p><p> buttonstate = digitalRead(button[y]);</p><p> byte btn = y + 1; // logical button # (1-4)</p><p> if (buttonstate == LOW) //Checking for button push</p><p> {</p><p> btnPushed = true;</p><p> digitalWrite(ledpin[y], HIGH);</p><p> speaker.play(btnNote[btn - 1], 100);</p><p> delay(100); // insures minimum LED illumination</p><p> inputArray[x] = btn;</p><p> Serial.print(&quot; btn pushed: &quot;);</p><p> Serial.print(btn);</p><p>// was a poor way to allow for button release: delay(250);</p><p> wait_BtnRelease(); // much better this way</p><p> digitalWrite(ledpin[y], LOW);</p><p> if (inputArray[x] != randomArray[x]) { //Checks value input by user and checks it against</p><p> fail(); //the value in the same spot on the generated array</p><p> //The fail function is called if it does not match</p><p> exit;</p><p> }</p><p> }</p><p> }</p><p> } // end while</p><p> }</p><p> delay(500);</p><p> turn++; //Increments the turn count, also the last action before starting the output function over again</p><p>}</p><p>// ------------------------------------------------------</p><p>void fail() { //Function used if the player fails to match the sequence</p><p> for (int y = 0; y &lt;= 2; y++)</p><p> { //Flashes lights for failure</p><p> allLEDs(HIGH);</p><p> speaker.play(NOTE_G3, 300);</p><p> delay(200);</p><p> allLEDs(LOW);</p><p> speaker.play(NOTE_C3, 300);</p><p> delay(200);</p><p> }</p><p> delay(500);</p><p> turn = -1; //Resets turn value so the game starts over without need for a reset button</p><p>}</p><p>// ------------------------------------------------------</p><p>void allLEDs(byte state) {</p><p> digitalWrite(ledpin[0], state);</p><p> digitalWrite(ledpin[1], state);</p><p> digitalWrite(ledpin[2], state);</p><p> digitalWrite(ledpin[3], state);</p><p>}</p><p>void wait_BtnRelease() {</p><p> bool btnStillDown;</p><p> int debounce=0; // need depends on button used. mine caused some double trips</p><p> while (debounce&lt;2) {</p><p> delay(5);</p><p> btnStillDown = false;</p><p> for (int y = 0; y &lt; 4; y++)</p><p> {</p><p> buttonstate = digitalRead(button[y]);</p><p> if (buttonstate == LOW) //Checking for button push</p><p> btnStillDown = true;</p><p> }</p><p> if (btnStillDown) debounce=0;</p><p> else debounce++;</p><p> }</p><p>}</p>
<p>Thanks for your interest in this instructable.</p><p>It looks like you have not placed the needed servo control code where this line is located: <em>// HERE ADD SERVO ...</em></p><p>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.</p><p>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.</p><p>Looking forward to hearing about your success.</p>
<p>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</p><p> #include &lt;Tone.h&gt;</p><p> ^</p><p>compilation terminated.</p><p>exit status 1</p><p>Error compiling.</p><p> This report would have more information with</p><p> &quot;Show verbose output during compilation&quot;</p><p> enabled in File &gt; Preferences.</p><p><br>Can you help me with this? TIA =)</p>
<p>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 <a href="https://www.arduino.cc/en/Main/Software" rel="nofollow">latest IDE</a> to get this sketch as well as the ToneTest sketch to build.</p>

About This Instructable

3,118views

10favorites

License:

Bio: Professional Software, Hardware, Systems Engineer for more than 40 years. Amateur Radio HAM (KI7NEW)
More by RonM9:2-bit Communicators (RFM69) Dual Power for Your Portable Micro-Controller Project 3D printed case, Inline LED display console + reflection on 3D printing 
Add instructable to: