Introduction: The Reverse Andycache (Android-powered Reverse Geocache)
For those that don't know, the Reverse Geocache puzzle is a puzzle box that opens only when the box is taken to a predefined location. You don't know what the location is, you have a limited number of attempts, and the box creator hates you enough to only tell you how far away you are (in the words of some French gentleman from Mikal Hart's story, “You are — how you say in English? — a BASTARD!").
I read about this back in 2009 and thought it was a cool idea, even purchasing some parts for the reverse geocache, but I never got around to making it.
Fast forward to 2013, and upon seeing those parts left alone in a lone Sparkfun box, I decided to revive the project.
Behold, introducing the Reverse Andycache!
My GPS module was out of order and I was lacking a screen, but I definitely wasn't lacking in the number of Android phones I had thanks to friends who graciously gifted old Android phones. So why not repurpose one of these phones for this project? After all, a smartphone has GPS and a screen that I can use for free!
Hence, the Reverse Andycache (short for Reverse Android-Geocache) was born. But here's what sets it apart from all other reverse geocaches: it is a multipurpose box. It is currently set up as a reverse geocache, but because of how it is controlled and operated, it can also be used for other purposes without ever touching the firmware on the box.
(To clarify, you only need a spare Android phone if the person you're giving this to doesn't have an Android phone. In my case, the recipient has an iPhone.)
The source code for my app can be found here.
As I will be entering the Make-to-Learn Youth Contest, here are my answers to the four questions:
What did you make?
I made a reverse geocache box that uses an Android phone as the UI as well as the GPS. The box itself has no screen or GPS, a departure from traditional designs. The phone and box communicate via Bluetooth, and all programming logic is done on the phone (with data stored securely on an EEPROM chip inside the box). Otherwise, it currently acts as a standard reverse geocache box.
The beauty of this design is that because all programming logic is done on the phone, the box is modular and can be repurposed for other things (for example, a lockbox, or perhaps a very good alarm system that would hide a regular alarm clock inside the box >:D) by simply writing another app that uses the box's functionality in a different way.
The Reverse Andycache required quite an extensive list of materials and tools, such as the IOIO Mint, some assorted electronics bits and pieces, a servo, an old phone, and tools such as a drill, saw, and soldering iron.
How did you make it?
I had been inspired by the original design back in 2009 but never really had time to work on a box of my own. So when I was thinking of creative ways to ask someone to my senior prom (as it's my senior year of high school), I eventually thought of making one of these.
The electronics and programming were 100% designed, built and coded by me (with a little programming help from Ytai Ben-Tsvi, creator of IOIO). The mounting, drilling and other physical tasks required some assistance from my mom and uncle, who have a garage full of tools and supplies.
Where did you make it?
I worked on the box mostly at home, with a little bit of work done in my hotel room in San Diego. Over 100 hours were put into writing the code (which is admittedly rather rough in quality, but that's expected for writing so much code in so little time), and about 20 hours were put into planning the electronics, wiring them up, and building the box.
I figured that because I was going to ask to prom a member of another FIRST robotics team, a project like this one would go perfectly.
What did you learn?
Never expect to finish a huge undertaking like this in less than a week :P
Fortunately, when you're coming up with something like this for a prom proposal, I found there are always people who are willing to help! Many thanks to my friends who provided materials, feedback, phones, or just thought it was awesome and wanted to help in whatever way possible.
I learned how to use the IOIO platform with Android (and Ytai has done an awesome job in making it easy to use in Android development) as well as how to use SMS messaging (to an extent), block location spoofing in apps, and how to use servos.
A few pitfalls that I noted:
-The Galaxy S series of devices have issues with locking onto GPS (confirmed using GPS Test/GPS Status apps). Flashing new ROMs seemed to solve the issue.
-IOIO is only capable of a maximum 127-byte read operation over I2C (I was trying to read 256). Ytai pointed this quirk out in the IOIO firmware. My code now only does 64-byte reads at most.
-Android 4.2.2 implements whitelisting for Android Debug Bridge, and my laptop's USB ports are non-functional. I ended up having to manually transplant my laptop's RSA key onto my phone to whitelist it for wireless ADB.
-Servo locking mechanism is one of the trickiest parts of the physical build: the mechanism needs to ensure the box stays locked, it needs to be physically strong and resist forced attempts to open, and it needs to be reliably controllable. I went through 4 different locking mechanism ideas before settling on this one.
-Making a board from scratch is always a pain. I'd try to have a PCB etched next time.
I'm proudest of having finished this project in such a short period of time given the demands of school, scholarship applications, robotics, etc. Writing over 1500 lines of code (the bulk of my app) in 3 days is no easy feat. And the finished appearance of my Reverse Andycache is aesthetically pleasing, always a bonus.
If I had to do it again, I would spend more time making a better UI (I personally think I suck in making functional UIs) as well as writing cleaner code. In addition, I'd try to get a better soldering iron and use that (it's always a pain to use firestarters, but I didn't really have any other option for this project).
Step 1: Gather Materials
This is a list of all the materials I used for this project. You can probably source these from cheaper places if you look.
Also, Adafruit has awesome customer service, I highly recommend buying from them!
-Decorative wooden box (from Michael's ~$15)
-IOIO Mint ($65)
-Hitec HS-55 servo ($10) (I'd also recommend getting an aluminium arm for the servo like this one)
-Illuminated LED on/off pushbutton ($6)
-Quick-connect wires ($5)
-Extra-long male headers ($3)
-Panel-mount USB-B to micro-B cable ($4)
-6000mAh Lithium-polymer battery ($40)
-Snap-action 3-wire block connector ($3)
-JST-PH wire extension ($2)
-8-pin DIP socket ($0.50)
-24LC256 I2C EEPROM ($2)
-3x 10k ohm resistors
-0.1uF decoupling capacitor
-Protoboard (I used a spare I had lying around)
You also need:
-Soldering iron + solder
-Dremel or other cutting tool
-A sheet of MDF
-Hot glue gun + glue
-Assorted fasteners and such
-Android phone for testing/debugging/deployment (should be running 4.0 or above if you're using my code)
-Computer with Android SDK set up (completely optional, but highly recommended)
How much I spent: ~$160 for box and electronics (does not include wire, MDF, fasteners, glue, tools, or phone)
Step 2: Prepare Box
You need to cut three holes:
One for the pushbutton.
One for the USB jack.
One for the servo locking mechanism.
Use a Dremel or drill or whatever floats your boat. Remember to measure twice, cut once.
Be careful with the last hole, because the servo needs to be mounted such that the servo arm will be able to rotate into the hole!
Additionally, you'll want to place some metal in all four corners of the lid of the box so that the magnets can attach to them (this is for the lid) this can be done using just some long screws, or you can use the metal L-brackets like I did.
Step 3: Make Cover
Grab that sheet of MDF (or whatever floats your boat) and some adhesive (I used rubber cement) as well as your Dremel and saw.
Saw it down to fit inside your box's lid.
Cut an access hole with your Dremel so you can take the cover off. Also cut a square hole the size of your HS-55 servo so it can fit through.
Then glue the magnets on.
Make sure the hole for the servo is centered and at the edge of the cover so that the servo arm can rotate into the slot you made in part 2.
Step 4: Wire Up Shield
Now take your protoboard, wire, soldering iron, solder, and electronics components.
You need to make a board with this schematic (look at pictures).
Solder one 16-pin header so that it corresponds with pins 1-16 on the IOIO and a 3-pin header so that it corresponds with the 5V/3.3V/GND pin on the IOIO (so that when you place the shield on your IOIO Mint, these pins are accessible).
Solder one more 3-pin header (for the servo) onto the board and wire up 5V to 5V, GND to GND, and the control wire to pin 6 on the IOIO with a 10k pullup to 5V. (Pin reassignments must be done in code, so make sure you get this right if you don't want to deal with Java!)
Also you need to wire up the battery, button and LEDs (see pictures). Grab that JST-PH extension wire, cut only the red wire in the middle, and then wire up the split ends to the switch. This is where the block connects + quick connect wires come in handy. You need to wire up the C1 and NC1 pins on the button. Then connect the ends of the extension to the LiPo and the IOIO Mint's battery header.
Then wire up the LED part of the pushbutton to the shield's 5V/GND (the LED can handle 5V without a resistor). This corresponds to the left and right pins of the pushbutton. I used the quick connect wires and soldered a 2-pin male header directly to the 5V/GND rails on the protoboard for easy connection.
Make sure you solder those quick connect wires: they have a tendency to come loose. Then hot glue the quick connects so that the contacts don't touch each other and short out.
Remember to connect your servo too.
I'd also tidy up the wires with some electrical tape to reduce clutter.
If you're using an external LiPo charger as part of your setup instead of an IOIO Mint, I would recommend using a voltage divider to also connect the battery to IOIO's pin 41 (use a voltage divider that cuts the voltage in half) as my code uses pin 41 to measure remaining battery capacity.
Step 5: Prepare IOIO for Deployment
Grab my Reverse Geocache code from Github, fine-tune any constants needed (check the source code for details), compile and install on your Android phone using ADB.
Alternately, you can grab a precompiled version from the Play Store, though I would advise against it if how you're using the box is going to differ significantly from mine.
Turn on the box, pair your phone to the IOIO in Bluetooth settings (device name IOIO, passcode 4545). Then open the app, use the Program function in the menu (passcode is 0000) and alter the parameters as you see fit. (Make sure you fill out everything) Click Flash to Box and the data will be written to the EEPROM in the box.
You'll probably have to fine tune the servo pulse widths, use this app and adjust the second bar, then update the constants in my source code accordingly. Alternatively, remount the servo arm so that the open/closed position pulse widths in my app match up with the desired servo arm positions.
Optional: publish a compiled version of the app on Google Play so that you can update the app without ever touching the phone (assuming auto-update is enabled) in case there is a software bug.
Step 6: Test the Box!
Test the box!
Take it outside, try opening it at your place, etc.
You can reset the puzzle by following the instructions in step 5 again (just use your new reset passcode this time).
Step 7: Give the Box!
If your recipient doesn't have an Android phone with GPS, then you'll have to provide them with one.
I'm using my SGS4G shown below.
Make sure the app is installed.
And please make sure you don't forget to put something inside! Giving an empty box would suck!
If you're going with my Play Store suggestion in step 5, make sure auto-update is enabled.
Step 8: Emergency: I've Locked Myself Out of the Box and I Can't Open It Again!
Chill. There are a few things you can do:
-Use a location spoofing app to spoof the target location (I will attempt to patch this exploit eventually)
-Use the programming menu inside the app to set the box to an unlocked state (you'll need the reset passcode)
-Use the IOIO Servo Control app and reset the servo position to the unlocked state (note: you'll still have to remember the reset passcode in order to change the puzzle paramaters)
-Unscrew hinges if they're outside the box and try to lift the lid
-If none of the above works, use a hammer
Step 9: Room for Improvement
There's always room for improvement.
So far, though, the only things I can think of are software related:
-Separate the programming menu from the main app and spin it off into a separate app (this is a work in progress; I will be pushing the changes to my Github as this is being done)
-Clean up the UI
-Work on being able to send text messages when an unlock attempt is made
Also, I would like to eventually reuse this box in other ways as well. Putting an alarm inside the box and having to do something on your phone to unlock the box to turn off the alarm sounds like a plan! (Since I generally just pull the battery from my phone anyway D:)
A few things about security:
-The box can always be unlocked by an attacker who is motivated enough. It's just a matter of sending the right command to the IOIO. This can be mitigated by encrypting commands and only allowing authorized apps to control the IOIO through a firmware rewrite on the IOIO, but this adds a much greater level of complexity. I don't really plan on fixing this.
-Location spoofing apps can fool the controller app. This can be fixed by blocking mock locations and refusing to run if any location spoofing app is installed. This has been fixed to an extent, but can still be bypassed using a rooted phone (not much I can do there).
-Hardware security is important, too: you can always try to break open the box using traditional means.