Mystery Box The Freefall Deck
2017-03-27 | By Adafruit Industries
License: See Original Project
Courtesy of Adafruit
Guide by John Park
Overview
The Freefall Deck
The setup: You're running an escape room, or a magic trick, or a uniquely themed Wild West baby shower. You've cast your participants/game players/soccer moms & dads as Old West gamblers.
The puzzle: A clue leads them to a sealed deck of poker cards and two rules to follow:
- Unless otherwise instructed, hang on to this deck of cards -- in time it'll deliver an important message.
- Should the dealer suspect you've marked the cards, there's gonna be trouble, so keep it sealed and pristine!
The payoff: Later, the players/gamblers find a new clue that instructs them to "toss the deck to hear the key". Being highly clever, they try literally throwing the deck into the air and -- BEHOLD! -- when the deck reaches a state of freefall, the distinctive beeping "dits" and "dahs" of a Morse code message begin to emanate from within the pack of cards. They catch the deck and begin to transcribe the message, an important solution to the puzzle.
Thus is unlocked the mystery of The Freefall Deck!
Parts and Materials
The Circuit Playground is a powerful, compact, and capable device, making it ideal for building magic tricks, mystery boxes for escape rooms, and other wondrous effect. We'll use its built in accelerometer to detect the state of freefall and its on-board speaker to send the Morse code message.
We'll also use a small battery, a deck of Bicycle playing cards, and some wood, cardboard, or acrylic to make the cutout deck insert to hold the electronics inside the card box. Some hot glue will allow us to reseal the box and wrapper.
Optionally, you can use a small scale and calipers to precisely match the weight and thickness of the original cards. This is probably bonkers.
Sneakily Opening the Box
Part of the effectiveness of this gag is because the deck of cards appears completely standard and unopened, therefore it's surprising to have it react to being tossed or dropped and to hear sounds coming from within it!
To pull this off we need to get into the deck without ruining the cellophane or the seal on the box. We'll also need to match the feel of the deck -- it should weigh and feel the same as normal cards. Finally, we must re-seal the box and cellophane.
Unsealing the Cards
To unseal the deck we'll first use a small knife or thin piece of metal such as a feeler gauge to slide open the folded cellophane at the bottom of the deck. Go slowly to avoid tearing the thin plastic -- you want to pry and lift more than cut.
Next, carefully slice through the glue that holds the bottom flap of the cardboard box. Avoid bending the cardboard -- a sure sign of tampering!
Remove the existing cards and set them aside. You'll save a few to place back in the box in order to fill out the thickness properly, the rest you can potentially use in setting up a different puzzle.
Next, we'll set up the electronics by programming the Circuit Playground.
Coding Circuit Playground
Prep the Circuit Playground
Before you get started, make sure you've been through the basic tutorials on using the Circuit Playground. You'll need to have installed the Arduino IDE, added the Circuit Playground board to Arduino, and added the Circuit Playground library. This excellent guide, Introducing Circuit Playground and Circuit Playground lesson #0 will show you how to do all of that and get you going.
Plug your Circuit Playground into your computer now, and launch the Arduino IDE. Double check that you've selected the board and port as in the Lesson #0 tutorial and are ready to upload code.
Freefall Deck Logic
The Freefall Deck sketch is quite simple, it can only do two things: check the state of it's accelerometer, and beep a pre-coded Morse message when the accelerometer reaches a state of freefall.
//Circuit Playground Freefall Deck
//created by John Park for Adafruit Industries
//a sealed deck of cards is tossed in the air or dropped, at which point it reveals a Morse code message
//Freefall detection by Phil Burgess
//Morse table by Usman Muzaffar
////////////////////////////////////////
#include "Adafruit_CircuitPlayground.h"
volatile boolean interruptHappened = false;
//*******************************************************//
//Morse code playback variables
//Adjust PITCH to your liking and DOT for speed faster/slower
const int PITCH = 600; // Morse code audio is sent at 600-800 Hz. 680 is quite nice
const int DOT = 200; //time duration in millis, change this to adjust transmission speed
const int DASH = 3 * DOT; //Morse standard dash is 3x longer than dot
const int GAP = DOT; //Morse inter-element gap within a character is same length as dot
const int INTER_LETTER = 3 * DOT; //Morse short gap between letters is 3x dot length
const int INTER_WORD = 7 * DOT; //Morse medium gap between words is 7x dot length
//*******************************************************//
void setup() {
CircuitPlayground.begin();
CircuitPlayground.strip.clear();
CircuitPlayground.strip.show();
// Bypass library and brute-force LIS3DH registers for freefall detect.
// From ST App Note AN3308 w/changes to threshold & duration.
writeReg8(LIS3DH_REG_CTRL1 , 0xA7); // Sensor on, enable X,Y,Z, 100 Hz
writeReg8(LIS3DH_REG_CTRL2 , 0x00); // Disable high-pass filter
writeReg8(LIS3DH_REG_CTRL3 , 0x40); // Enable I1_INT1 interrupt gen
writeReg8(LIS3DH_REG_CTRL4 , 0x00); // 2G
writeReg8(LIS3DH_REG_CTRL5 , 0x00); // Interrupt not latched
writeReg8(LIS3DH_REG_INT1THS, 0x0A); // ~160 mG threshold
writeReg8(LIS3DH_REG_INT1DUR, 0xFF); // Duration
writeReg8(LIS3DH_REG_INT1CFG, 0x95); // Configure free-fall recognition
pinMode(7, INPUT_PULLUP); // LIS3DH INT1 is connected to D7
attachInterrupt(digitalPinToInterrupt(7), interruptHandler, FALLING);
}
void writeReg8(uint8_t reg, uint8_t value) {
SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE0));
digitalWrite(CPLAY_LIS3DH_CS, LOW);
SPI.transfer(reg & 0x7F);
SPI.transfer(value);
digitalWrite(CPLAY_LIS3DH_CS, HIGH);
SPI.endTransaction();
}
void interruptHandler() {
interruptHappened = true;
}
void loop() {
if (interruptHappened) { //Accelerometer has detected free fall, do something here
//*******************************************************//
//Place your message here.
//Each letter or number on one line.
//Spaces between words are denoted with a slash / symbol.
//Only use A-Z 0-9
//Other characters will cause trouble!
playMorseLetter('/');//good to have a slight delay at the beginning
playMorseLetter('O');
playMorseLetter('N');
playMorseLetter('/');
playMorseLetter('P');
playMorseLetter('A');
playMorseLetter('G');
playMorseLetter('E');
playMorseLetter('/');
playMorseLetter('X');
//*******************************************************//
interruptHappened = false;
}
}
void playMorseLetter(char letter) {
// Morse table by Usman Muzaffar
// Adapted from: http://stackoverflow.com/a/28058216
// Define two tables of strings one for letters and one for numbers,
// that return the Morse encoding. By using two separate tables, we
// can just offset the ASCII value of either a number or letter as
// the index to look up the Morse encoding.
static const char *ALPHA_TABLE[] = {
".-", //A
"-...", //B
"-.-.", //C
"-..", //D
".", //E
"..-.", //F
"--.", //G
"....", //H
"..", //I
".---", //J
"-.-", //K
".-..", //L
"--", //M
"-.", //N
"---", //O
".--.", //P
"--.-", //Q
".-.", //R
"...", //S
"-", //T
"..-", //U
"...-", //V
".--", //W
"-..-", //X
"-.--", //Y
"--..", //Z
};
static const char *NUM_TABLE[] = {
"-----", //0
".----", //1
"..---", //2
"...--", //3
"....-", //4
".....", //5
"-....", //6
"--...", //7
"---..", //8
"----.", //9
};
if(letter == '/'){// use "/" as space between words
delay(INTER_WORD);
return;
}
// Look up the morseCode string for this letter
// by finding the right table.
char* morseCode;
if (isalpha(letter)) {
morseCode = ALPHA_TABLE[letter - 'A'];
} else {
morseCode = NUM_TABLE[letter - '0'];
}
for (int i = 0; i < strlen(morseCode); i ){
int duration = morseCode[i] == '-' ? DASH : DOT;
CircuitPlayground.playTone(PITCH, duration);
delay(GAP);
}
delay(INTER_LETTER);
}
Download the Code
You can click "Copy Code" in the code above, then paste it into a new sketch in Arduino. Save the file as CircuitPlaygroundFreefallDeck.ino in your Arduino sketch directory, then upload it to your Circuit Playground.
To test it out, drop the powered Circuit Playground from one hand to another. Thanks to the physics and programming prowess of our own Phil Burgess, the Circuit Playground will detect a state of freefall and begin beeping the coded message.
Adjust the Code
If you'd like to change the message, look for this section in the code:
//*******************************************************//
//Place your message here.
//Each letter or number on one line.
//Spaces between words are denoted with a slash / symbol.
//Only use A-Z 0-9
//Other characters will cause trouble!
playMorseLetter('/');//good to have a slight delay at the beginning
playMorseLetter('O');
playMorseLetter('N');
playMorseLetter('/');
playMorseLetter('P');
playMorseLetter('A');
playMorseLetter('G');
playMorseLetter('E');
playMorseLetter('/');
playMorseLetter('X');
//*******************************************************//
Place any message you like by replacing the letters in the single quotes on each line with letters A-Z or numbers 0-9. Use a slash / symbol to represent the spaces between words.
It's a good idea to keep your messages short and easy to transcribe. One thing you may want to adjust is the speed of the message transmission. Do this by changing the variable DOT in the code. It is currently set to 200 milliseconds, a fairly moderate rate, but you can certainly increase that number to slow things down further.
Assembling the Deck
Building the Card Insert
Remove the Circuit Playground from the USB cable and plug in the lipo battery. You can wrap it in some tissue paper or foam, and slip it back into the deck with a few cards in front and back -- this will work just fine. However! The weight and feel will be pretty suspicious. Too light, and too squishy!
So, instead, I recommend cutting out some card stock or cardboard to accommodate the electronics, similar to a hollowed out book. Or, you can take some thin plywood to the bandsaw or scrollsaw or a hand coping saw to create a similar insert.
I designed an insert to be cut from 3mm acrylic on the laser cutter. You can download the file and use it on a laser cutter, mill, or even print out on an inkjet or laser printer as a template for cutting cardboard or other materials.
Measured with calipers, the thickness of these five layers comes up just shy of a regular deck of cards, so I shimmed it by adding eight cards to the insert, four on top and four on the bottom.
The additional cards also bring the weight up to nearly identical between the "gimmicked" deck and that of a regular deck of cards.
Re-Sealing the Box
You'll now reverse the process. When you're ready to use the Freefall Deck (you'll have plenty of battery life, so this can be set up hours before needed) insert the electronics, insert, and any extra cards for padding into the box.
Now, you can use a thin bead of hot glue to close the cardboard flap, and then do the same for the cellophane.
Next, take the Freefall Deck for a spin.
Using the Freefall Deck
The deck is fairly immune to inspection -- and it doesn't tend to trigger from being handled, only from a toss in the air or a drop. Try throwing and catching it, dropping it from one hand to another, or letting it go a short distance above a table or other surface.
A gambler's poker cards are just one example of how to theme this effect. If you like, you can use the gag inside any kind of object you like -- a sealed wooden box, inside a stuffed animal, hidden in the heel of a boot -- you can get creative with it!
Have questions or comments? Continue the conversation on TechForum, DigiKey's online community and technical resource.
Visit TechForum