Arduino Simon Says
Intro: Arduino Simon Says
First we will cover how to set up the components on a breadboard. Then we will cover the Code used and how it all works. Then i'll show you how you can modify the code to customize the game to your liking.
Materials Needed:
- Arduino (I used a Nove)
- Bread Board
- Jumper Wires
- 4 different colored LEDs
- 4 100 Ohm Resistors
- 4 Push Buttons
- Small Speaker
STEP 1: Hardware Setup
First you'll want to lay out your buttons on the bottom section of your Breadboard. We'll tie one lead of the buttons directly to ground. The other lead will be wired to the Arduino's Digital pins 2, 3, 4, and 5. I ran a wire to the top half of the board to keep the wires running from the board to the Arduino out of the way.
Now we want to lay out the LEDs above the buttons. We'll plug the LEDs in with the switches so the Cathode is on the same strip as the side of the button that is tied to ground. Well arrange it so the Anode plugs in off to the side of the button. Now we'll take out 100 Ohm resistor and put it inline with the Anodeto the top section of the breadboard. Now we can connect a wire from the resistor to the Arduino. The LEDs will be using Digital pins 8, 9, 10, and 11. So make sure the buttons and LED are lined up as follows:
- Button on pin 2 with LED on pin 8
- Button on pin 3 with LED on pin 9
- Button on pin 4 with LED on pin 10
- Button on pin 5 with LED on pin 11
STEP 2: The Sketch
The sketch was originally made by Robert Spann back in 2009. I used an earlier version of his sketch since i didn't like the way he integrated sound in later versions of the sketch. To give the game sound i decided to use the Tone.h Library. The Library hasn't been updated since the release of Arduino 1.0, so i went ahead and updated it to be compatible with Arduino 1.0. In doing so i cut out any backwards compatibility with older IDEs. So if your running an older version of the IDE then used the link in the next step to download the original library. I've attached a copy of the updated library on this page. So be sure to download it and place it in your Arduino/Libraries folder or the sketch will not compile under Arduino 1.0.
Here is the Sketch. A file of the sketch is also attached. If there are any questions about it please let me know.
/*Simon Says game. Now with sound effects.
Originaly made by Robert Spann
Code trimmed and sound effects added by digimike
Buttons are to be set on there designated pins without pull down resistors
and connected to ground rather then +5.
*/
#include
Tone speakerpin;
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 note[] = {NOTE_C4, NOTE_C4, NOTE_G4, NOTE_C5, NOTE_G4, NOTE_C5};
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 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()
{
Serial.begin(9600);
speakerpin.begin(12); // speaker is on pin 13
for(int x=0; x<4; x++) // LED pins are outputs
{
pinMode(ledpin[x], OUTPUT);
}
for(int x=0; x<4; x++)
{
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:
speakerpin.play(starttune[thisNote]);
// hold the note:
if (thisNote==0 || thisNote==2 || thisNote==4 || thisNote== 6)
{
digitalWrite(ledpin[0], HIGH);
}
if (thisNote==1 || thisNote==3 || thisNote==5 || thisNote== 7 || thisNote==9 || thisNote==11)
{
digitalWrite(ledpin[1], HIGH);
}
if (thisNote==8 || thisNote==12)
{
digitalWrite(ledpin[2], HIGH);
}
if (thisNote==10)
{
digitalWrite(ledpin[3], HIGH);
}
delay(duration2[thisNote]);
// stop for the next note:
speakerpin.stop();
digitalWrite(ledpin[0], LOW);
digitalWrite(ledpin[1], LOW);
digitalWrite(ledpin[2], LOW);
digitalWrite(ledpin[3], LOW);
delay(25);
}
delay(1000);
}
void loop()
{
for (int y=0; y<=99; y++)
{
//function for generating the array to be matched by the player
digitalWrite(ledpin[0], HIGH);
digitalWrite(ledpin[1], HIGH);
digitalWrite(ledpin[2], HIGH);
digitalWrite(ledpin[3], HIGH);
for (int thisNote = 0; thisNote < 6; thisNote ++) {
// play the next note:
speakerpin.play(note[thisNote]);
// hold the note:
delay(duration[thisNote]);
// stop for the next note:
speakerpin.stop();
delay(25);
}
digitalWrite(ledpin[0], LOW);
digitalWrite(ledpin[1], LOW);
digitalWrite(ledpin[2], LOW);
digitalWrite(ledpin[3], LOW);
delay(1000);
for (int y=turn; y <= turn; y++)
{ //Limited by the turn variable
Serial.println(""); //Some serial output to follow along
Serial.print("Turn: ");
Serial.print(y);
Serial.println("");
randomArray[y] = random(1, 5); //Assigning a random number (1-4) to the randomArray[y], y being the turn count
for (int x=0; x <= turn; x++)
{
Serial.print(randomArray[x]);
for(int y=0; y<4; y++)
{
if (randomArray[x] == 1 && ledpin[y] == 8)
{ //if statements to display the stored values in the array
digitalWrite(ledpin[y], HIGH);
speakerpin.play(NOTE_G3, 100);
delay(400);
digitalWrite(ledpin[y], LOW);
delay(100);
}
if (randomArray[x] == 2 && ledpin[y] == 9)
{
digitalWrite(ledpin[y], HIGH);
speakerpin.play(NOTE_A3, 100);
delay(400);
digitalWrite(ledpin[y], LOW);
delay(100);
}
if (randomArray[x] == 3 && ledpin[y] == 10)
{
digitalWrite(ledpin[y], HIGH);
speakerpin.play(NOTE_B3, 100);
delay(400);
digitalWrite(ledpin[y], LOW);
delay(100);
}
if (randomArray[x] == 4 && ledpin[y] == 11)
{
digitalWrite(ledpin[y], HIGH);
speakerpin.play(NOTE_C4, 100);
delay(400);
digitalWrite(ledpin[y], LOW);
delay(100);
}
}
}
}
input();
}
}
void input() { //Function for allowing user input and checking input against the generated array
for (int x=0; x <= turn;)
{ //Statement controlled by turn count
for(int y=0; y<4; y++)
{
buttonstate = digitalRead(button[y]);
if (buttonstate == LOW && button[y] == 2)
{ //Checking for button push
digitalWrite(ledpin[0], HIGH);
speakerpin.play(NOTE_G3, 100);
delay(200);
digitalWrite(ledpin[0], LOW);
inputArray[x] = 1;
delay(250);
Serial.print(" ");
Serial.print(1);
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
x++;
}
if (buttonstate == LOW && button[y] == 3)
{
digitalWrite(ledpin[1], HIGH);
speakerpin.play(NOTE_A3, 100);
delay(200);
digitalWrite(ledpin[1], LOW);
inputArray[x] = 2;
delay(250);
Serial.print(" ");
Serial.print(2);
if (inputArray[x] != randomArray[x]) {
fail();
}
x++;
}
if (buttonstate == LOW && button[y] == 4)
{
digitalWrite(ledpin[2], HIGH);
speakerpin.play(NOTE_B3, 100);
delay(200);
digitalWrite(ledpin[2], LOW);
inputArray[x] = 3;
delay(250);
Serial.print(" ");
Serial.print(3);
if (inputArray[x] != randomArray[x]) {
fail();
}
x++;
}
if (buttonstate == LOW && button[y] == 5)
{
digitalWrite(ledpin[3], HIGH);
speakerpin.play(NOTE_C4, 100);
delay(200);
digitalWrite(ledpin[3], LOW);
inputArray[x] = 4;
delay(250);
Serial.print(" ");
Serial.print(4);
if (inputArray[x] != randomArray[x])
{
fail();
}
x++;
}
}
}
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
digitalWrite(ledpin[0], HIGH);
digitalWrite(ledpin[1], HIGH);
digitalWrite(ledpin[2], HIGH);
digitalWrite(ledpin[3], HIGH);
speakerpin.play(NOTE_G3, 300);
delay(200);
digitalWrite(ledpin[0], LOW);
digitalWrite(ledpin[1], LOW);
digitalWrite(ledpin[2], LOW);
digitalWrite(ledpin[3], LOW);
speakerpin.play(NOTE_C3, 300);
delay(200);
}
delay(500);
turn = -1; //Resets turn value so the game starts over without need for a reset button
}
STEP 3: Sketch Mods
http://code.google.com/p/rogue-code/wiki/ToneLibraryDocumentation
Basically how the sounds work is the Library creates a square wave of the specified frequency. You define what notes you want played in the start of the sketch. You also need to define how long each note will be played. The picture shows what notes the library is able to generate.
In this case we define a couple of tunes, starttune[ ] and note[ ]. We also define the duration of each tune as duration[ ] and duration2[ ]. Starttune [ ] tune is the Mexican Hat Dance melody and the note [ ] tune is the charge melody.
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 note[] = {NOTE_C4, NOTE_C4, NOTE_G4, NOTE_C5, NOTE_G4, NOTE_C5};
int duration[] = {100, 100, 100, 300, 100, 300};
To play these tunes we jump down to this section.
for (int thisNote = 0; thisNote < 13; thisNote ++) {
// play the next note:
speakerpin.play(starttune[thisNote]);
// hold the note:
if (thisNote==0 || thisNote==2 || thisNote==4 || thisNote== 6)
{
digitalWrite(ledpin[0], HIGH);
}
if (thisNote==1 || thisNote==3 || thisNote==5 || thisNote== 7 || thisNote==9 || thisNote==11)
{
digitalWrite(ledpin[1], HIGH);
}
if (thisNote==8 || thisNote==12)
{
digitalWrite(ledpin[2], HIGH);
}
if (thisNote==10)
{
digitalWrite(ledpin[3], HIGH);
}
delay(duration2[thisNote]);
// stop for the next note:
speakerpin.stop();
digitalWrite(ledpin[0], LOW);
digitalWrite(ledpin[1], LOW);
digitalWrite(ledpin[2], LOW);
digitalWrite(ledpin[3], LOW);
delay(25);
}
We use a For() statement to run a loop through the tune we want to play. In the "for (int thisNote = 0; thisNote < 13; thisNote ++) {" line the number 13 referes to the number of notes in the tune. The code starts at the first note and generates the tone for the specified duration. While its doing that the code is lighting a corresponding LED depending on what note it is at in the sequence. So you can go in and change which LED is lighted under what note to make the lights dance as you see fit. The delay placed after turning off the LEDs controls the tempo of the music. In this case when the 13th note has been played the program moves on.
The main body of the sketch (void loop()) is where the program reads the randomly generated array and starts blinking the LEDS and playing a note. Any notes you redefine there need to be duplicated in the void input() so the same note is played back when you hit the buttons.
The tone played when you miss the sequence i kept as a simple 2 note tone that looped a couple of times. You will find that in the void fail() section of the sketch.
STEP 4: Final Results
Here is a video of the game in action.
More to Come:
- LCD Display
- 1 and 2 player options
- Schematics
- Taking the atmega328p off the Arduino and onto its own PCB
- Enclosure
100 Comments
ThéoR16 4 years ago
AlexisR34 7 years ago
Arduino:1.6.8 (Windows 10), Tarjeta:"Arduino/Genuino Uno"
C:\Users\Alexis\AppData\Local\Temp\Rar$DIa0.635\Ejercicio24-Simon\Ejercicio24-Simon.ino:14:20: fatal error: wiring.h: No such file or directory
#include <wiring.h>
^
compilation terminated.
exit status 1
Error compilación en tarjeta Arduino/Genuino Uno.
Este reporte podría tener más información con
"Mostrar salida detallada durante la compilación"
opción habilitada en Archivo -> Preferencias.
Gökhan Türkeli 7 years ago
Hello,
I made the connections, copy/pasted the tone folder under libraries folder, uploaded the code into arduino uno(chinese clone) but nothing happened.
I checked the connections multiple times. I even asked someone else to check the connections but no fault is found.
There is only one warning when I upload the code:
simon_says_audio_ino:15:31: warning: narrowing conversion of '2' from 'int' to 'boolean' inside { } [-Wnarrowing]
This error repeats for every pin(2,3,4,5,8,9,10,11). Serial monitor gives this:
Turn: 0
2
What am I doing wrong?
MichaelC576 7 years ago
Change from "Boolean" to "int" on lines 15 & 16
Gökhan Türkeli 7 years ago
Yes, it worked! I made it. Kids loved it.
MichaelC576 7 years ago
Hello,
I've been trying for hours to get this to work, tried 3 different rewires, rotated switches. The code compiles fine, Serial starts and I get the tone through the speaker but no LEDs or input from buttons in Serial. I checked all the comments and tried them but no luck. So i'm finally posting for help, I have two pics up I'm almost certain it's wiring but I can't find any of the problems. Any help would be greatly appreciated, thank you
Gökhan Türkeli 7 years ago
Well, I couldn't do my version so I may not be the one to answer your question as it should be but if you look at the 1st step/last photo, there is an extra cable for pin 13.
So if you add that final connection it may work. Or it may not. I couldn't manage what was my problem either:)
MichaelC576 7 years ago
Thanks for the try but unfortunately that is just the ground connection I already established, but I have solved it!
Change from "Boolean" to "int" on lines 15 & 16 worked for me
LED PROBLEMS with Arduino Starter Kit SOLVED:
I spent 3 days trying to get this to work and have finally solved it. My big problem was my breadboard wouldn't hold my components and poor connections prevented my LEDs from working. I am using the official arduino starter kit (which is one of the best by the way) and it turns out the metal plates underneath the connect points bend from overuse.
Solution: http://forum.arduino.cc/index.php?topic=163989.0
Also spacing out components as much as possible on the breadboard helped too
I also bought new buttons: https://www.sparkfun.com/products/10302
but I am fairly certain the breadboard trick will work with anyone having LED problems
Its refreshing to know I can blame this one on the tech and not myself!
Thanks for a great tutorial!
DaniyalM5 8 years ago
i have a program while compiling...please help me bro....the error is shown below
sketch\Tone.cpp:26:20: fatal error: wiring.h: No such file or directory
#include <wiring.h>
^
compilation terminated.
exit status 1
Error compiling.
This report would have more information with
"Show verbose output during compilation"
enabled in File > Preferences.
mpilchfamily 8 years ago
Read through all the other comments. This question has been answered several times already. Bottom line you don't have the tone library installed correctly.
fgonzalez14 11 years ago
oswaldobossio 8 years ago
C:\Program Files (x86)\Arduino\libraries
collinsarthur 8 years ago
Superb...
Karin Hodel 8 years ago
Hello.
Also the LEDs are not working. When I try each LED and Button separately then they work. In the program only the speaker is working.
What could be the problem?
I work with an Arduino UNO.
Thanks for your help
mpilchfamily 8 years ago
You're asking the same question many others have had and the answers are outlined in the instructable and reiterated in the below replies.
Karin Hodel 8 years ago
Yes i know.
But because the LEDs and the buttons are working when i use another sketch I thougt that maybe there is another problem.
mpilchfamily 8 years ago
As evident by the examples shown below the code works. So chances are it's user error in wiring. make sure you have things wired to the correct pins. Beyond that there isn't much more help i can give.
Karin Hodel 8 years ago
Thanks.
I gonna try again.
KrishY1 8 years ago
i've tried to do this but why is it the LED is not working,..after uploading the program, only the speaker is working,..need help thanks!!!
mpilchfamily 8 years ago
Most common issue is the buttons are not connected correctly, so at least one button is connected as if it's being pressed constantly. Causing the system to cycle from the intro music, to the first sequence, then it plays the invalid button press and then plays the fail music and starts over again.