Introduction: Audio Treasure Hunt

About: My name is Jason Poel Smith. In my free time, I am an Inventor, Maker, Hacker, Tinker, and all around Mad Genius

Everyone loves treasure hunts. Running around on a quest to find your present makes any gift better. So just for fun, I designed my own variation of the game. I combined an Arduino microcontroller with an Adafruit Wave Shield to make an audio treasure hunt box.

The treasure hunters are given a code. When they enter the code into the box, it will play a short audio clip that gives them a clue as to where they should go next. When they arrive at this location, they will find another code, which they will enter and get another clue. This continues until eventually they arrive at the final location and find their present.

Step 1: Watch the Video

Here is a video walkthrough of the project.

Step 2: Materials

Here are the materials and tools that you will need to complete this project.

Materials:

Arduino Microcontroller

Adafruit Wave Shield Kit

8 ohm Speaker

9 Volt Battery

Arduino Battery Connector (9 Volt Battery Connector and 2.1mm DC Power Connector)

Insulated Project Enclosure

Six Buttons (normally open momentary)

Header Pin Connector Wires (or other jumper wires)

SD Card

Heat Shrink Tubing

Tools:

Soldering Iron and Solder

Wire Cutters

Wire Strippers

Step 3: Assemble the Wave Shield

The Wave Shield is an add-on to the Arduino that allows it to play sound files. It can be purchased at http://www.adafruit.com/product/94. This comes as a kit that you have to put together yourself. So the first step is assembling the Wave Shield. There is a very good tutorial on how to do this on the Adafruit website here:

https://learn.adafruit.com/adafruit-wave-shield-au...

First find and identify all the parts. The part numbers may not match up exactly. Be very careful to correctly identify the two 8 pin IC chips. Then solder them onto the circuit board. To make it easier, start with the parts that are the most difficult to solder such as the SD card holder. You will have more room to work around before the other parts are installed. Continue soldering on parts until they are all installed.

The wave shield connects to the Arduino board with header pins on the bottom side of the wave board. These pins fit into the pin sockets on the Arduino. Adjacent to the pin holes where these header pins are mounted is a second set of holes that are connected to them. These let you connect external components to the pins on the Arduino. You can solder wires directly to these holes or you can use header pins for removable connections. The kit comes with eight additional header pin connectors. Two of these I soldered to the 5V and GND pin holes. The remaining six I connected to the analog input pins.

The kit does not come with a speaker. So you need to provide your own. The wire from the speaker can be attached to the two open pin holes that are adjacent to the headphone connector.

Step 4: Download and Install the Wave Library

In order to make the wave shield work, you need to install the waveHC library. You can download a copy of it here: https://code.google.com/p/wavehc/downloads/list.

Download the zip file. Then unzip/extract the files. Copy the WaveHC folder into the libraries directory of your Arduino program folder.

You can find a detailed tutorial on the library and how to use it here: https://learn.adafruit.com/adafruit-wave-shield-au...

Step 5: The Arduino Code

// Here is copy of the Arduino Code. You can either download the attached code file, or you can copy and paste this text into a new sketch.

//Then connect the Arduino board to your computer and upload the code.

#include
#include #include #include "WaveUtil.h" #include "WaveHC.h"

SdReader card; // This object holds the information for the card FatVolume vol; // This holds the information for the partition on the card FatReader root; // This holds the information for the filesystem on the card FatReader f; // This holds the information for the file we're play

WaveHC wave; // This is the only wave (audio) object, since we will only play one at a time

#define DEBOUNCE 100 // button debouncer

// this handy function will return the number of bytes currently free in RAM, great for debugging! int freeRam(void) { extern int __bss_end; extern int *__brkval; int free_memory; if((int)__brkval == 0) { free_memory = ((int)&free_memory) - ((int)&__bss_end); } else { free_memory = ((int)&free_memory) - ((int)__brkval); } return free_memory; }

void sdErrorCheck(void) { if (!card.errorCode()) return; putstring("\n\rSD I/O error: "); Serial.print(card.errorCode(), HEX); putstring(", "); Serial.println(card.errorData(), HEX); while(1); }

//<------------------------------------------------------------------------------ Void Setup void setup() { // set up serial port Serial.begin(9600); putstring_nl("WaveHC with 6 buttons"); putstring("Free RAM: "); // This can help with debugging, running out of RAM is bad Serial.println(freeRam()); // if this is under 150 bytes it may spell trouble! // Set the output pins for the DAC control. This pins are defined in the library pinMode(2, OUTPUT); pinMode(3, OUTPUT); pinMode(4, OUTPUT); pinMode(5, OUTPUT); // pin13 LED pinMode(13, OUTPUT); // enable pull-up resistors on switch pins (analog inputs) digitalWrite(14, HIGH); digitalWrite(15, HIGH); digitalWrite(16, HIGH); digitalWrite(17, HIGH); digitalWrite(18, HIGH); digitalWrite(19, HIGH); // if (!card.init(true)) { //play with 4 MHz spi if 8MHz isn't working for you if (!card.init()) { //play with 8 MHz spi (default faster!) putstring_nl("Card init. failed!"); // Something went wrong, lets print out why sdErrorCheck(); while(1); // then 'halt' - do nothing! } // enable optimize read - some cards may timeout. Disable if you're having problems card.partialBlockRead(true); // Now we will look for a FAT partition! uint8_t part; for (part = 0; part < 5; part++) { // we have up to 5 slots to look in if (vol.init(card, part)) break; // we found one, lets bail } if (part == 5) { // if we ended up not finding one :( putstring_nl("No valid FAT partition!"); sdErrorCheck(); // Something went wrong, lets print out why while(1); // then 'halt' - do nothing! } // Lets tell the user about what we found putstring("Using partition "); Serial.print(part, DEC); putstring(", type is FAT"); Serial.println(vol.fatType(),DEC); // FAT16 or FAT32? // Try to open the root directory if (!root.openRoot(vol)) { putstring_nl("Can't open root dir!"); // Something went wrong, while(1); // then 'halt' - do nothing! } // Whew! We got past the tough parts. putstring_nl("Ready!"); }

//<------------------------------------------------------------------------------------- Void Loop

void loop() { //putstring("."); // uncomment this to see if the loop isnt running int secretCodeOne[6] = {1, 2, 3, 4, 5, 6}; int secretCodeTwo[6] = {1, 1, 2, 2, 3, 3}; int secretCodeThree[6] = {2, 4, 6, 1, 3, 5}; int secretCodeFour[6] = {1, 2, 3, 5, 5, 5}; int secretCodeFive[6] = {1, 2, 3, 3, 2, 1}; int secretCodeSix[6] = {1, 2, 3, 4, 5, 1};

int enteredCode[6] = {0, 0, 0, 0, 0, 0}; int correctKeys = 0; int success = 0; byte pressed; //stores values of button pressed int i = 0; //loop iteration

for (i=0;i<6;i++) //stores pressed values in an array { do { pressed = check_switches(); } while (pressed < 1); enteredCode[i] = pressed; //stores pressed values in an array delay(500); Serial.println(enteredCode[i]); //print button pressed }

for (i=0;i<6;i++) //Check Code One { if (enteredCode[i] == secretCodeOne[i]) { correctKeys = correctKeys +1; //counts number of correct keys } } if (correctKeys == 6) //if the entered code matches code one, play track one { Serial.println("Code One Correct"); playcomplete("1.WAV"); success = 1; } correctKeys = 0; //reset correct key counter

for (i=0;i<6;i++) //Check Code Two { if (enteredCode[i] == secretCodeTwo[i]) { correctKeys = correctKeys +1; //counts number of correct keys } } if (correctKeys == 6) //if the entered code matches code one, play track one { Serial.println("Code Two Correct"); playcomplete("2.WAV"); success = 1; } correctKeys = 0; //reset correct key counter

for (i=0;i<6;i++) //Check Code Three { if (enteredCode[i] == secretCodeThree[i]) { correctKeys = correctKeys +1; //counts number of correct keys } } if (correctKeys == 6) //if the entered code matches code one, play track one { Serial.println("Code Three Correct"); playcomplete("3.WAV"); success = 1; } correctKeys = 0; //reset correct key counter

for (i=0;i<6;i++) //Check Code Four { if (enteredCode[i] == secretCodeFour[i]) { correctKeys = correctKeys +1; //counts number of correct keys } } if (correctKeys == 6) //if the entered code matches code one, play track one { Serial.println("Code Four Correct"); playcomplete("4.WAV"); success = 1; } correctKeys = 0; //reset correct key counter

for (i=0;i<6;i++) //Check Code Five { if (enteredCode[i] == secretCodeFive[i]) { correctKeys = correctKeys +1; //counts number of correct keys } } if (correctKeys == 6) //if the entered code matches code one, play track one { Serial.println("Code Five Correct"); playcomplete("5.WAV"); success = 1; } correctKeys = 0; //reset correct key counter

for (i=0;i<6;i++) //Check Code Six { if (enteredCode[i] == secretCodeSix[i]) { correctKeys = correctKeys +1; //counts number of correct keys } } if (correctKeys == 6) //if the entered code matches code one, play track one { Serial.println("Code Six Correct"); playcomplete("6.WAV"); success = 1; } correctKeys = 0; //reset correct key counter

if(success == 1) { Serial.println("You Got a Code Correct"); success = 0; } else { playcomplete("0.WAV"); Serial.println("You Fail"); } }

byte check_switches() { static byte previous[6]; static long time[6]; byte reading; byte pressed; byte index; pressed = 0;

for (byte index = 0; index < 6; ++index) { reading = digitalRead(14 + index); if (reading == LOW && previous[index] == HIGH && millis() - time[index] > DEBOUNCE) { // switch pressed time[index] = millis(); pressed = index + 1; break; } previous[index] = reading; } // return switch number (1 - 6) return (pressed); }

// Plays a full file from beginning to end with no pause. void playcomplete(char *name) { // call our helper to find and play this name playfile(name); while (wave.isplaying) { // do nothing while its playing } // now its done playing }

void playfile(char *name) { // see if the wave object is currently doing something if (wave.isplaying) {// already playing something, so stop it! wave.stop(); // stop it } // look in the root directory and open the file if (!f.open(root, name)) { putstring("Couldn't open file "); Serial.print(name); return; } // OK read the file and turn it into a wave object if (!wave.create(f)) { putstring_nl("Not a valid WAV"); return; } // ok time to play! start playback wave.play(); }

Step 6: Changing the Message Codes and Adding New Ones

I have six patterns set up in the example code. These are stored in arrays labeled "secretCodeOne", "secretCodeTwo", etc. You can add more to make the treasure hunt as long as you want.

Start by adding more arrays. These are initialized at the first of the void loop. Then add another "for" loop to check the pattern. This should include a reference to additional audio clips.

Step 7: Record the Audio Files

Next you need to record the audio tracks that will be the clues in the treasure hunt.

So first you need to decide on what kind of clues you want to use. You have a lot of options. You can keep it simple and just say the location of the next clue code. Or you can make it more difficult by having each clue be a riddle. You can find some good example riddles here. You can also quote lines from books that they have read and have them find that passage in the book or the objects that they are talking. Another fun option is to record various sounds around the house and they will have to go find the objects that make those sounds. The possibilities are endless. Just use your imagination.

Make one extra sound track that will play if they enter the code incorrectly. This can just be a buzzer or you saying "wrong."

You want each track to be a separate file. I have attached a few example files.

Step 8: Convert the Audio Files to the .WAV Format

The Wave shield can only play audio files in the .WAV format. So if your sound recorder saves the files in a different format, you will need to convert them to .WAV.

If you have itunes you can use this tutorial to convert them: https://learn.adafruit.com/adafruit-wave-shield-au...

You can also use online file converters such as this one: http://audio.online-convert.com/convert-to-wav

Regardless of which program you use, you need to convert the file to the .wav type. The bit resolution should be set to "16 bit". The sampling rate should be set to 22050 Hz (or 22.050 kHz). The audio channels should be set to "Mono."

Step 9: Load the Files Onto the SD Card and Install It

Next, copy the .wav files onto the SD card. You need the file names of the sound clips to match the file names in the code. The wave shield is a little picky about how the files can be named. So for simplicity, I named the files 0.wav, 1.wav, 2.wav,...etc. I made it so that 0.wav is the error message and the rest of the sound files are the clues in order. If you rename your sound files to match this, you won't have to change the code.

Once the files are on the SD card, plug the card into the wave shield.

Step 10: Drill Holes in the Housing for the Buttons

To avoid conflicts with other parts that will be mounted inside the housing, try to fit the speaker, the boards and the battery in place to see where there will be room for the buttons.

Once you have decided on a good location, drill holes in the side of the housing for each of the buttons. When you are done, you may wish to clean up the edges with a knife or file.

Step 11: Connect the Buttons to the Board

First you need to mount the buttons to the side of the housing. Unscrew the mounting nut from each button. Insert the button through the holes. Then tighten the nuts back on to hold them in place.

Now you can connect the buttons to the board. One terminal of each button will be connected to the analog input pins. The other terminal of each button will be connected to GND.

To connect the terminals to ground, I took a single wire with a female header pin connector on one end and I wired that to one terminal on the first button. Then I connected the other switches to that using a string of short jumper wires.

To connect the other side of each switch to the board, I used a six terminal header pin connector cable. The header pin block connected to the pins on the board. The wires were connected to the other side of the buttons. I highly recommend insulating each connection with heat shrink tubing.

Step 12: Mount All the Parts Inside the Housing

Now all you have to do is mount all the parts inside the housing. First slide in the speaker. Use glue to hold it in place if necessary. There is a lot of exposed metal on the back of the speaker. So I put a piece of paper over it so that it wouldn't accidentally cause a short with any of the connections on the board. Then carefully fit in the boards. This was a little tight with the housing that I used. I ended up removing the volume knob on the wave shield to make it fit better. Lastly connect the battery and fit that in place. Be sure to use a brand new battery. If the battery is too low, the system won't work properly. Now just close up the housing and your audio treasure hunt box is complete.

Step 13: Hide the Clue Codes at Each Location

The final part of the setup is to hide the clue codes at each location. You can write the code on a piece of paper or you can write directly on the objects. If you want you can even make it a little harder my giving the code number in the form of math problems.

Step 14: Give the Box to Your Treasure Hunter and Watch the Fun.

Wrap up the audio treasure hunt box as a regular gift. Include a note to get them started. Then just sit back and watch the fun.

On a Budget Contest

Participated in the
On a Budget Contest