Introduction: Question Box Puzzle

This is a video game themed puzzle box based run on an Arduino Mega.  I just used what I had laying around, so if you wanted to build something like this yours will likely be different.  I wanted this tutorial to be more about the idea of the puzzle box and how to do a few general things instead of how to replicate my exact puzzle box.  I feel like I'm just starting on this project and there's a lot more that could be done with it.

The things I'll cover in this tutorial:
1. connecting a bunch of LEDs to a project
2. integrating a toy into a project
3. The coolness of Shapelock
4. Running motors, servos and steppers (using the motor shield)
5. Connecting an Xbee if you don't have room for the shield
6. Remote Controlling your application from a web application over Xbee
7. Connecting to I2C devices (LCD, Wiimote, another Arduino)
8. Connecting to a Parallax Knock sensor
9. Making sound with a speaker
10. Getting input from buttons
11. General Puzzle trickery


For the puzzles I thought I'd all for Myst type puzzles (you've been given a box, figure it out), and Mario style (generally you know what you're supposed to do, sometimes you even get a chance to practice parts of it before doing it for real).

The attached video shows a "level" where you have to put the Contra code in on buttons that look kind of like a NES controller.



Step 1: Stuff Used in This Project

One goal of this project, as it progressed, was to complete overengineer.  I think I did that.

1 -  Unfinished wooden box from a craft store
7 - small push buttons
1 - Arcade push button
1 - 5-way button
1 - Serial/I2C LCD
32 - LEDs
1 - resistor
1 - GPS
1 - Keypad
1 - Parallax Knock sensor
1 - Xbee
1 - speaker
4 - Nixie Tubes
1 - Nixie Tube Shield
1 - Adafruit Motor Shield
1 - Buzz Lighyear gun disc gun
1 - Stepper
1 - Servo
1 - Pack of Shape Lock
1 - Wiimote Nunchuck
1 - Xbee shield from SeeedStudio
1 - Arduino Uno
1 - Arduino Mega (Sparkfun free day goodness)
A few random screws
Lots of random wires
Lots of batteries

Step 2: LEDs

This project has 32 LED's each one connected to a different pin so I could control each one individually (other ways to do this without using as many pins are Charlieplexing, using shift resisters, using an LED controlling IC, or use something like a centipede shield). First, I drilled hikes in the box. Next, I put the LED's in the holes. After that I bent all the cathode leads so it touched the cathode lead of the LED next to it. Then I soldered them all together. Next I soldered a wire to each anode to connect it to the Arduino.

Step 3: "Coin" Shooter

I put coin in quotation marks because my box doesn't shoot out real coins, it shoots out foam discs.  I took a Buzz Lighyear game that came with a disc gun and pull out it's innerds and put it in my box.  Here's a "before" picture of the gun, and a picture of the innerds after I opened it up.  Opening it up is probably about what you'd expect, pull off all the screws and the side comes off.

Step 4: Taking the Gun Apart

To finish up the dissassembly I removed the other big outside plastic part around the shooting mechanims and the little piece on the front and back.  Now all that was left was the middle stuff that does all the work.  The way this particular gun works is there's a little motor that spins a big disc.  When someone pulls the trigger one of the foam dics is moved forward so it touches the spinning disc, which sends it flying.  This seemed like it would fit the bill.  when I went to put it in my box it was a little too wide, so I cut off part of one side with a dremel.  I also removed the trigger by remving the screw so I could attach it to a servo so the Arduino could control the trigger.

Step 5: Putting It in the Box

For a box I went and bought an unfinished wooden box at a local craft store.  I actually already had this beacuse I was thinking about making a reverse geo caching box out of it (I guess I'll have to get another one for that, good thing they're only a couple of bucks).  To mount the shooting mechanism I used Shapelock which I picked up from Maker Shed.  If you're not familiar with Shapelock, this stuff is awesome.  If you need to make a custom plastic piece and don't have a 3d printer, this may be the next best thing.  Basically you pour some in a microwave safe container of water and put it in the microwave.  When it melts you can still handle it (it's pretty hot, but workable).  You form it into whatever you want, let it cool and you've got a pretty hard plastic part.  You can drill it, saw it, or whatever, as long as you keep it below 160 degrees F (or something like that).  Anyway, Shapelock is what I used to make plastic brackets to mount the shooter.

Step 6: Running the Gun

I used an Adafruit motor shield to run the motor on the gun and the servo to trigger the shots. To use the motor shield I simply connected a battery pack (4 AA's in series) to the power terminals on the sheld. I connected the motor to motor input #4. I connected the servo to servo terminal 0 on the shield. I'll use motor terminals 1 and 2 later. I've attached a sketch below showing how it's used.  I was using an Arduino Mega 2560 and was having problems with running steppers with the library provided by Adafruit, until I figured out there was an update then it all started working correctly.

To run a servo with the motor shield, it's exactly like running a servo connected directly to an Arduino.  In fact all the motor shield does is give you a convenient 3 pin header to connect to.  GOTCHA - According to the FAQ Arduino Pin 9 goes to Servo Header 1 and Pin 10 goes to Servo Header 2.  On mine it was backwards (Pin 9 -> Servo Header 2, Pin 10 -> Servo Header 1).

To control a motor you basically set it up and tell it what port it's connected to, set the speed and direction and let it go.  If you don't connect external power to the shield motors won't work (even though steppers do). 

Check out the code attached to this step.

Note: obviously this could be done without the motor shield, but I had one around and was using an Arduino Mega, so I had plenty of pins.

Step 7: XBee

I love serial devices.  They're usually easy to hook up and work well with Arduinos.  An Xbee is pretty much like any other serial device.  All it really needs to run is power and a serial connection.  Since I was using the motor shield I couldn't use my Xbee shield, so I just soldered some angled headers on the Seeedstudio Xbee shield and connected to one of the additional Serial connectors on the Mega. 

Remember when you're connecting an serial IC

IC    Arduino
RX -> TX
TX  -> RX

When I soldered the headers on I could have done it two different ways.  I could have just soldered up a female header to fit on the pins that normally plug into the male pins that normally hook into the Arduino.  The second way is to solder on new male headers on side of the shield right next to the Xbee pins.  Doing it that way made it so I didn't have to figure out the pins (I was having a hard time finding documentation on it).  The problem doing it this way is that the Arduion is working on 5v and the Xbee shield is wanting 3.3v.  From what I hear it's 5v tolerant though, and for me it's working fine so far (it may reduce the life of the Xbee though).

Step 8: GPS and Other Low Voltage Serial Devices


My project also has a GPS connected. Rather than give specifics on my GPS module (especially since it's been discontinued by Sparkfun) Ive decided to just give general help on hooking up a GPS to an Arduino.  You'll want to look at the datasheet for your particular GPS before connecting.  The things you want to pay the most attention to are: what the pins are, and what voltage they take.  Many GPS units only tolerate 3.3v, and an Arduino works on 5v (note: there are Arduino's that work on 3.3v as well, like the Arduino Pro 3.3v).  The Arduino One (and the Duemilanove) has a 3.3v power output on it.  You should  be able to use that to feed power to the device.  You also need to protect the serial connection to the device.  To do this use a Logic Level Converter, like this one from Sparkfun .  This is really easy to connect, just:

Arduino     Logic Level Converter
5v -----------> HV
3.3v --------> LV
RX ----------> RXI
TX -----------> TXI
GND --------> GND


then to connect to the GPS unit (or any other 3.3v serial device)

Logic Level Converter     GPS
RXO ---------------------------> TX
TXO ----------------------------> RX

Direct Connections from Arduino To GPS

Arduino    GPS
3.3 v -------> Vin
GND ------> GND

Translating what's coming from the Arduino to use it for whatever you're trying to do you'll need to read the datasheet or other documents more.  If you're worried about getting all this working you may want to find a GPS unit where someone's worked out all the code and has a tutorial for it.  If I were going to get one today I'd probably go with this unit (and tutorial) http://www.sparkfun.com/tutorials/176

Step 9: Remote Control

One of the uses I had conjured up for the coin box is to turn it on when my kids finished chores and tape money or something to the discs.  I also thought something like this at work could be cool (it turns on every now and then and has a dollar attached to each of the foam discs or something).  To make this work the way I wanted I wanted to be able to control it from a computer, or my smart phone.  To make this work I built a small Sinatra app.  The computer hosting the Sinatra app has an Xbee shield on it that talks to the coin box over serial.

Step 10: Install Sinatra


Sinatra is a web "micro-framework".  This basically means it gives you what you need to make web applications without a lot of extra stuff.  Don't get me wrong, I love Rails, but for something small like this it seems like overkill. Sinatra is great for something like this.  This app is built to run in Windows, but the only thing that would need to change to run in Linux is some of the serial stuff.  First off, installing Ruby and Sinatra:

Download the newest Ruby 1.8 installer , I would prefer 1.9, but it looks like the serial libraries aren't being maintained and don't work with 1.9

Open a command prompt and type "gem install serialport" then type "gem install sinatra".  One quirk with Ruby 1.8 is that it has a problem with rack, which get's installed with Sinatra.  To fix this do "gem uninstall rack" (tell it to uninstall the binary, and uninstall even though other gems are dependent on it), then "gem install rack --version '1.2.0'.  You should have all the stuff installed you need to run the program.  I like to use thin to run my Ruby stuff, it's a pretty fast, easy to use Ruby web application server.  To make this happen type "gem install thin" in the command prompt.

Step 11: The Sinatra Application

Lets dissect the attached Sinatra app:

This get's the required libraries to do Sinatra and Serial
require 'serialport'
require 'sinatra'

This is where you configure the serial port number and speed
arduinoSerialPort = 'COM22'
arduinoSerialPortSpeed = 9600

This creates the serial port object.  It's not really important to understand what this means if you're not a programmer, but because we made sp equal to the SerialPort.new then sp.write is how we'll output stuff to the serial port
sp = SerialPort.new(arduinoSerialPort, arduinoSerialPortSpeed, 8, 1, SerialPort::NONE)

Normally in Sinatra you'd have a separate file in a separate directory with your template of your page.  I wanted to have this app all in the same file, so I made a really simple template below.  In the "routes" (the pages in URL) I replace the word BODY below with the HTML for that page I want to display.
htmlCode = "<html><head></head><body>BODY</body></html>"

Here's the first route.  get just means it's a get request, which is the type of request that happens when you type in a URL or click on a link.  The '/' means the homepage basically (so if I type in http://servername/ then I'll get to this code).  Everything between the "do" and the "end" is executed as part of this page.  Here all I do is have a body variable and I assign it a bunch of HTML for links to other pages.  There are three links below one to /shootstuff, one to /lightallleds, and one for /coinsound.  The last thing I do is replace the BODY in htmlCode (from above) with the HTML I defined here.  Whatever the last thing is in the route get's returned and rendered as the page.
get '/' do
   body = "<a href=\"/shootstuff\">Shoot Stuff</a><br />"
   body += "<a href=\"/lightallleds\">Light All LEDs</a><br />"
   body += "<a href=\"/coinsound\">Mario Coin Sound</a><br />"

   htmlCode.gsub("BODY", body)
end

Here's another route, this one's what you get if you hit http://servername/shootstuff.  The first thing it does is send a "1" over serial to my coin box.  Then it just has a link to go back to the last page.
get '/shootstuff' do
   sp.write "1"
   body = "<b>Stuff Should be shooting</b></br>"
   body += "<a href=\"/\">Return to Actions</a><br />"
   htmlCode.gsub("BODY", body)
end

Similar to the route above, this one fires when someone goes to http://servername/lightallleds.  It sends a 2 over serial and give a link back to the index page
get '/lightallleds' do
   sp.write "2"
   body = "<b>All LEDs Should Be Lit</b></br>"
   body += "<a href=\"/\">Return to Actions</a><br />"
   htmlCode.gsub("BODY", body)
end

This route is similar to the two above.  It fires when someone hits http://servername/coinsound, writes a "3" over serial and has a link back to the index page
get '/coinsound' do
   sp.write "3"
   body = "<b>Coin Sound Should Have Sounded</b></br>"
   body += "<a href=\"/\">Return to Actions</a><br />"
   htmlCode.gsub("BODY", body)
end

Step 12: Starting Up the Sinatra Application

Open a command prompt and cd to the directory where your script is.  Then type "ruby thenameofyourrubyfile.rb" replacing thenameofyourrubyfile with the name of the file you created that has the ruby code in it.  By default it will start up on port 4567.  If you want to hit it on that port open a browser and type http://servername:4567 .  If you don't want to do that, you can specify another port at startup.  Web servers run on port 80 for HTTP, so you'd start it up like this "ruby thenameofyourrubyfile.rb -p 80".  You should be able to see your app now.  If you don't have DNS and can't resolve the name of the server, then you can replace servername in the URLs above with the IP of the server. 

Step 13: I2C Devices

I love I2C, it allows you to connect multiple devices to only 2 pins on the Arduino.  It's a bus based protocol and it's pretty easy to find compatable devices.

In my puzzle box I used 3 I2C devices:

1. Web4robot Serial/I2C LCD
2. Wiimote Nunchuck
3. An Arduino Uno with a Nixie tube shield (I used this as the timer for the game).

I2C has two lines, SDA and SCL.  To connect I2C devices simply connect the SDA on the Arduino to all the SDA's on the devices and connect the SCL on the Arduino to all the SCL's on all the other devices.  To get good reliability it's good to connect a 1.5 K Ohm resistor between 5v and each of the lines (a pull-up resistor).

Arduino has a library called Wire that's used to communicate between I2C devices.  Each I2C bus should have one master and can have up to 128 devices total.  In my case I set up the Arduino Mega as the master, and everything was a slave (including the Arduino Uno that was running the Nixie tubes).

Care should be taken when connecting I2C devices to see what voltages they can tolerate.  Like serial devices, many I2C devices can only tolerate 3.3v, instead of 5v, which is what many Arduinos work off of.  You can use the same logic level converter I mentioned when I was talking about serial devices on I2C http://www.sparkfun.com/products/8745

A couple of really good I2C tutorial are:
http://hacknmod.com/hack/how-to-connect-multiple-arduino-microcontrollers-using-i2c/
http://www.arduino.cc/playground/Learning/I2C

Step 14: Web4Robot LCD

I have the 20 x 4 version.  It gives a nice amount of real estate to output stuff.  Not only does this LCD allow communication via serial and I2C, but it also has the ability to connect a keypad to it so you don't have use up pins on your Arduino for it.  You can also connect any other type of button instead of a keypad if you want.

Minimally to get this LCD working:
1. connect the SDA pin on the LCD to the SDA pin on the Arduino
2. connect the SCL pin on the LCD to the SCL pin on the Arduino
3. connect Power on the LCD to 5v on the Arduino
4. connect Gnd on the LCD to Gnd on the Arduio

I used this library to connect t the LCD http://www.arduino.cc/playground/Code/LCDi2c .  It works really well, all you need to do to start sending data over to it is:

Include the libraries
#include <Wire.h>
#include <LCDI2C.h>

Set up the options for your particular LCD
int g_rows = 4;
int g_cols = 20;

LCDI2C lcd = LCDI2C(g_rows,g_cols,0x4C,1);

In setup() you need to initialize the LCD (clears it, sets up the curser, etc)
lcd.init();

Now you're ready to use it
lcd.print("Stuff to print to the LCD")

Move the Curser Down a row
lcd.setCursor(1,0);

Clear the LCD
lcd.clear();

There are many other functions such as off() on(), cursor functions, the ability to draw graphs, etc.





Step 15: Wiimote Nunchuck

All the things that hook onto the bottom of a Wiimote (nunchuck, classic game controller, guitar hero guitar, motion plus, etc) all communicate over I2C.  This is nice because we can communicate with them pretty easily with an Arduino.

There are already many tutorials on connecting to and communicating with a Wiimote nunchuck.  I'll give some tips on the way I did it and reference these other tutorials

I used this breakout http://www.sparkfun.com/products/9281 so I didn't have to cut off the end of the nunchuck cord.  The PCB just slides into the end of the Wiimote nunchuck connector.  All you need to do is solder on headers and connect

Arduino       Nunchuck Breakout
5v -------------> PWR (I think 3.3v works as well, in fact it may be that it prefers 3.3v, but its 5v tolerant)
GND ---------> GND
SDA ----------> D
SCL ----------> C

After that you just use a library to communicate with it.  Here's the tutorial and the library:

http://todbot.com/blog/2008/02/18/wiichuck-wii-nunchuck-adapter-available/

nunchuck_init() — init a nunchuck connected to an Arduino
nunchuck_get_data() — get a data packet from the Nunchuck

Then you can get at the data packet using various helper functions like:
nunchuck_accelx() — get X-axis acceleration
nunchuck_zbutton() — get Z-button state

Here's another good tutorial:

http://www.windmeadow.com/node/42

Step 16: Second Arduino With I2C

On my puzzle box I have a second Arduino (an Arduino Uno) with a Nixie Tube shield on it that acts as a timer.  Here's the connections:

Arduino Mega     Arduino Uno
SDA -----------------> SDA
SCL -----------------> SCL
GND ----------------> GND
Vin -------------------> Vin (this may not be necessary . . . anyone know for sure).

The master (Arduino Mega) communicates the same way it normally does.  The slave (Arduino Uno) is set up like this in setup():

Wire.begin(4); // join i2c bus with address #4
Wire.onReceive(receiveEvent); // register event

then you just need to define the recieveEvent (this one is from the example that comes with the Arduino IDE (it's under Wire in Examples)

void receiveEvent(int howMany)
{
while(1 < Wire.available()) // loop through all but the last
{
char c = Wire.receive(); // receive byte as a character
Serial.print(c); // print the character
}
int x = Wire.receive(); // receive byte as an integer
Serial.println(x); // print the integer
}

For mine I just have the master send one thing that tells the timer to start.

Here is a really good tutorial on connecting multiple Arduinos

http://hacknmod.com/hack/how-to-connect-multiple-arduino-microcontrollers-using-i2c/

Step 17: Parallax Sound Impact Sensor

At Defcon this last year I picked up a kit that included the Parallax Sound Impact Sensor .  It's an interesting sensor and pretty easy to use.  The idea is it detects an abrupt sound (clap, knock, etc) and makes the output pin high.  To connect it you do:

Arduino      Impact Sensor
GND --------> GND
5v ------------> 5v
SIG ----------> Arduino Digital or Analog Pin of you Choice

The board has a little pot that you can adjust to tell it how loud the sound has to be to trigger the signal.

To read the signal you have a couple of choices.  You can read it like a button (check for high on the pin, then you know it's fired), or you can use one of the Arduino interrupts.  I wanted to use this to trigger hitting the bottom of the box to spit out a "coin".  I had mixed success with this because of how loud the little motor was that shot stuff out.

Interrupts are easy to do.  All you do is define the interrupt in setup like this:

attachInterrupt(0, smack, RISING);

0 means that it's on digital pin 2.  smack is the name of the function it will call when the interrupt happens.  You can also define when it will fire, I said RISING, which means it will fire whenever the voltage is going up (in other words the SIG pin just went high).

Then you just need to define smack

void smack()
{
   //do whatever you want here, I played the mario coin sound and shot out a coin
}



Step 18: Buttons

Button reading is a pretty simple thing to do on an Arduino.  Here's the basics:

To connect a button, I do this:
Arduino              Button
5v -------------> one of the button leads
button Pin -->  other button lead

Set the pin to input
pinMode(buttonPin, INPUT);

Do a digital read on the pin
int reading = digitalRead(buttonPin);

That's the basics, but to get an accurate reading, especially if you're trying to detect sequences you're going to want to do something like the debounce example included with the Arduino IDE.  Basically this checks to see if the same button is still pressed each time through the loop, if it's changed since the last read then it doesn't count the reading until the debounce delay has passed (a few milliseconds).  This is because button readings can be a little squirly in the transition from on to off and can look like multiple button presses.

Step 19: Playing Music

Playing music on an Arduino is also a piece of cake.  Here's the basics:

Arduino                               Speaker
GND -----------------------> one speaker lead/wire
digital or analog pin ---> other speaker lead/wire

A couple of revs ago the Arduino IDE started to include the tone library.  Here's the basics (this will play the coin sound from Mario Bros), this is taken from the example that comes with the IDE:

Include the pitches.h header file
#include "pitches.h"

// notes in the melody:
int melody[] = {
NOTE_B5, NOTE_E6};

// note durations: 4 = quarter note, 8 = eighth note, etc.:
int noteDurations[] = {
16, 2 };


void playSound() {
// iterate over the notes of the melody:
   for (int thisNote = 0; thisNote < 2; thisNote++) {

     // to calculate the note duration, take one second
     // divided by the note type.
     //e.g. quarter note = 1000 / 4, eighth note = 1000/8, etc.
     int noteDuration = 1000/noteDurations[thisNote];
     tone(8, melody[thisNote],noteDuration);

     // to distinguish the notes, set a minimum time between them.
     // the note's duration + 30% seems to work well:
     //int pauseBetweenNotes = noteDuration * 1.30;
     delay(noteDuration + 10);
     // stop the tone playing:
    noTone(8);
   }
}

Step 20: Puzzle Stuff

Now that you have a lot of inputs and outputs you can do a ton of stuff to combine them to make the puzzle, here are a few I've got:

Contra Code (Up Up Down Down Left Right Left Right B A)
I've got this working a couple of different ways.  On one side of my puzzle box I have buttons that look somewhat like a NES controller.  One way to have the user input the code is to use those buttons.  Many times in video games you think you see the solution, but really it's slightly off what you think.  If you notice the button on the left is different than the others.  It's actually a 5 way button from Parallax.  So, it moves slightly left, right, up and down.  The way this button is set it's looks like maybe I didn't have enough buttons, and since it doesn't stick out far you have to use your fingernail to make it work.  Like video games though when something seems a little different it's something you should pay attention to.

Discs giving devices to help with other puzzles or prizes
The way these discs are, you can connect pieces of paper, or other small things to the discs.  Ideas for prizes include things like cash, gift certificates, or other paper prizes.  Other small things may include wire (as described in the next section) that could be used to solve future puzzles.  Hints could also be included on the paper shot out on a disc.

Stepper Blocking Access to Flexible Resistor
Notice in the attached picture that there's a stepper with a piece of card board blocking access to a flexible resitor (there's a hole in the side of the box that would allow you to access it otherwise.  To solve the puzzle you have to realize that something moves the stepper (i.e. a reading from the wiimote nunchuck accelerometer, a reading from the GPS, button presses, a combination of all of them).  This one feels kind of like a Myst puzzle to me, hand them the box, they starting doing things and hear the stepper moving and then figure out what they need to do.  I like the idea of getting a piece of wire inside of one of the discs after solving one of the previous puzzles and using that to solve this one.

Sound Impact Sensor vs Buttons
One thing I really like about the sound impact sensor is that it's basically like a hidden button.  Getting someone to push figure out there's something inside detecting an impact can make things interesting.

Combining Multiple Reading
Getting people to do multple things at the same time can be fun.  Making them hold the box in a certain way and push a button that's awkward to push (or multiple buttons) can be fun

Location Stuff
This box can basically work like a reverse Geocache box.  It can try to get the person to a location.  Once they get there you could connect to the device via Xbee and send data over to the screen to help with other puzzles

game.life challenge

Participated in the
game.life challenge

MakerBot Challenge

Participated in the
MakerBot Challenge