Another fun little project to practice my soldering skills and become more familiar with the Arduino.
Parts list:
- Arduino Uno (SparkFun)
- 4 push buttons (SparkFun)
- Red/Green/Blue/Yellow LEDs (SparkFun or RadioShack)
- PC Board Piezo Buzzer (SparkFun or RadioShack)
- 4x 330 ohm resistors
- 4x 10k ohm resistors
- wire
- PC board (I really like these) or breadboard
Schematic
The buttons are wired to pins 5-8 with one node connected to +5V and the other to ground via a 10k ohm pull-down resistor. The LEDs to pins 10-13, with 330 ohm current limiting resistor. The piezo buzzer is connected directly to pin 9 and ground. For the wires going to the Arduino pins, I just wired one end to the board and left the other end hanging, so it is not permanently attached to the Arduino.
Code
For more information about working with the piezo buzzer and an Arduino, check out CIRC06 at ardx.org
// Whether we're in "listen" or "playback" mode boolean listen; // Change this value to increase or decrease the number of rounds // played before winning the game const int num_rounds = 9; const int speakerPin = 9; // "A" note frequency const int a = 1136; // how long to play a note const int timestep = 500; char buttons[] = { 'y', 'b', 'r', 'g' }; int button_pins[] = { 5, 6, 7, 8 }; int led_pins[] = { 10, 11, 12, 13 }; // The frequency of all other notes is based off the "A" note // See: http://en.wikipedia.org/wiki/Simon_(game)#Gameplay int notes[] = { a * 1.25 * 1.25, a * 1.25, a, a * 0.75 }; // The note we play for failure const int fail_note = a * 4; // an array of the buttons for this game int play_buttons[num_rounds]; // which round are we currently playing? int currentRound; // what button are we on for the current round int current_button; // Set up the LEDs and buzzer as output, // and the buttons as input void setup() { pinMode(speakerPin, OUTPUT); for (int i=0; i<4; i++) { pinMode(button_pins[i], INPUT); pinMode(led_pins[i], OUTPUT); } initialize(); } void loop() { if (listen) { int buttonPress = readButtons(); // Check whether a button was pressed if (buttonPress != -1) { // make the button sound and light up the LED, to provide feedback playButton(buttonPress, timestep/2); // They hit the appropriate button if (buttonPress == play_buttons[current_button]) { delay(timestep); // They just played the final button for the final round if (current_button == num_rounds) { win(); return; } // They just played the final button for this round // Reset the round and switch to "playback" mode if (current_button == currentRound) { current_button = 0; currentRound++; listen = false; return; } // They're still in the middle of this round // Increment the current button and wait for next input current_button++; } else { // they didn't hit the correct button! fail(); return; } } // end listen } else { // play all buttons for the round if (currentRound == num_rounds) { win(); return; } else { // playback all the buttons for this round for (int i=0; i<=currentRound; i++) { playButton(play_buttons[i]); delay(timestep/2); } // switch to "listen" mode listen = true; } } } // During initialization, randomly choose arrays of buttons // for each round, then play a button pattern to let the user know // that the game has been loaded void initialize() { delay(timestep*2); randomSeed(analogRead(0)); for (int i=0; i<num_rounds; i++) { play_buttons[i] = (int)random(0, 4); } listen = false; currentRound = 0; current_button = 0; spin_colors(); spin_colors(); delay(timestep*2); } // Play the "failure" tone and restart the game void fail() { playTone(fail_note, timestep * 4); delay(timestep*2); initialize(); } // Play the "win" button pattern and restart the game void win() { for (int i=0; i<4; i++) { spin_colors(); } delay(timestep*2); initialize(); } void spin_colors() { for (int i=0; i<4; i++) { playButton(i, timestep/4); delay(timestep/4); } } void playButton(int color) { playButton(color, timestep); } // Turn on the LED and play the button's tone void playButton(int color, int duration) { digitalWrite(led_pins[color], HIGH); playTone(notes[color], duration); digitalWrite(led_pins[color], LOW); } // Play the buzzer at the tone's frequency void playTone(int tone, int duration) { for (long i = 0; i < duration * 1000L; i += tone * 2) { digitalWrite(speakerPin, HIGH); delayMicroseconds(tone); digitalWrite(speakerPin, LOW); delayMicroseconds(tone); } } // Iterate over all the buttons and check if one was pressed int readButtons() { for (int i=0; i<4; i++) { if (digitalRead(button_pins[i]) == HIGH) { return i; } } return -1; }