Using the Arduino we have combined a number of scavenged things from around the lab to build a geocache that will only unlock after playing (and winning) a good ‘ole fashioned game of Simon.
Here’s a video of the completed project:
Below are some notes and pictures of the process.
[print_gllr id=604 columns=3]
This was a fun project and we are looking into getting an actual body for this made and we can run up a few PCB’s for them and have a professional looking commercially available one to offer. If you have interest in this let us know.
This is the code we used for the logic:
/*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 tied to ground. Internal pull down resistors
will be in use. Logis is reversed.
*/
#include <MemoryFree.h>
#include <Servo.h>
#include “pitches.h”
int speakerpin = 13; // speaker ID
int note[] = {NOTE_C4, NOTE_C4, NOTE_G4, NOTE_C5, NOTE_G4, NOTE_C5}; // notes to be played for start and successful turn
int duration[] = {100, 100, 100, 300, 100, 300}; // pause between notes
int button[] = {2, 3, 4, 5}; //The four button input pins
int ledpin[] = {6, 7, 8, 15}; // LED pins
int casePin = 19;
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];
int servPin = 9;
Servo cacheServo;
int openLock = 10;
int pos = 0;
void setup()
{
pinMode(casePin, INPUT);
// servo code for setup
pinMode(9, OUTPUT);
cacheServo.attach(servPin);
cacheServo.write(175);
delay(300);
cacheServo.detach();
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 y=0; y<=99; y++)
{ //For statement to loop through the output and input functions
loop();
input();
}
}
void loop()
{
//set lock switch LOW
digitalWrite(casePin, HIGH);
//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 ++) {
tone(speakerpin,note[thisNote],duration[thisNote]);
delay(duration[thisNote]);
}
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
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++)
{
for(int y=0; y<4; y++)
{
if (randomArray[x] == 1 && ledpin[y] == 6)
{ //if statements to display the stored values in the array
digitalWrite(ledpin[y], HIGH);
tone(speakerpin, NOTE_G3, 100);
delay(400);
digitalWrite(ledpin[y], LOW);
delay(100);
}
if (randomArray[x] == 2 && ledpin[y] == 7)
{
digitalWrite(ledpin[y], HIGH);
tone(speakerpin, NOTE_A3, 100);
delay(400);
digitalWrite(ledpin[y], LOW);
delay(100);
}
if (randomArray[x] == 3 && ledpin[y] == 8)
{
digitalWrite(ledpin[y], HIGH);
tone(speakerpin, NOTE_B3, 100);
delay(400);
digitalWrite(ledpin[y], LOW);
delay(100);
}
if (randomArray[x] == 4 && ledpin[y] == 15)
{
digitalWrite(ledpin[y], HIGH);
tone(speakerpin, NOTE_C4, 100);
delay(400);
digitalWrite(ledpin[y], LOW);
delay(100);
}
}
}
}
}
void finishLockBox() {
// servo closes lock when lid contacts are made
pos = 175;
delay(5000);
cacheServo.attach(servPin);
cacheServo.write(pos);
delay(500);
turn = -1;
cacheServo.detach();
return;
}
void successOpenLock() {
digitalWrite(casePin, HIGH);
// use servo to open lock
pos = 15;
cacheServo.attach(servPin);
cacheServo.write(pos);
delay(500);
cacheServo.detach();
int i = 0;
while (true) {
if (i >= 50) {
if (digitalRead(casePin) == LOW) {
finishLockBox();
return;
}
}
digitalWrite(ledpin[0], HIGH);
delay(100);
digitalWrite(ledpin[0], LOW);
digitalWrite(ledpin[1], HIGH);
delay(100);
digitalWrite(ledpin[1], LOW);
digitalWrite(ledpin[2], HIGH);
delay(100);
digitalWrite(ledpin[2], LOW);
digitalWrite(ledpin[3], HIGH);
delay(100);
digitalWrite(ledpin[3], LOW);
i++;
}
}
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);
tone(speakerpin, NOTE_G3, 100);
delay(200);
digitalWrite(ledpin[0], LOW);
inputArray[x] = 1;
delay(50);
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);
tone(speakerpin, NOTE_A3, 100);
delay(200);
digitalWrite(ledpin[1], LOW);
inputArray[x] = 2;
delay(50);
Serial.print(” “);
Serial.print(2);
if (inputArray[x] != randomArray[x]) {
fail();
}
x++;
}
if (buttonstate == LOW && button[y] == 4)
{
digitalWrite(ledpin[2], HIGH);
tone(speakerpin, NOTE_B3, 100);
delay(200);
digitalWrite(ledpin[2], LOW);
inputArray[x] = 3;
delay(50);
Serial.print(” “);
Serial.print(3);
if (inputArray[x] != randomArray[x]) {
fail();
}
x++;
}
if (buttonstate == LOW && button[y] == 5)
{
digitalWrite(ledpin[3], HIGH);
tone(speakerpin, NOTE_C4, 100);
delay(200);
digitalWrite(ledpin[3], LOW);
inputArray[x] = 4;
delay(50);
Serial.print(” “);
Serial.print(4);
if (inputArray[x] != randomArray[x])
{
fail();
}
x++;
}
}
}
delay(500);
Serial.println(turn);
Serial.println(openLock);
if (turn >= openLock) {
successOpenLock();
}
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);
tone(speakerpin, NOTE_G3, 100);
delay(200);
digitalWrite(ledpin[0], LOW);
digitalWrite(ledpin[1], LOW);
digitalWrite(ledpin[2], LOW);
digitalWrite(ledpin[3], LOW);
tone(speakerpin, NOTE_C3, 100);
delay(200);
}
delay(500);
turn = -1; //Resets turn value so the game starts over without need for a reset button