diff options
Diffstat (limited to 'Puzzle_Box')
-rw-r--r-- | Puzzle_Box/Puzzle_Box.h | 52 | ||||
-rw-r--r-- | Puzzle_Box/Puzzle_Box.pde | 257 | ||||
-rw-r--r-- | Puzzle_Box/notes.txt | 56 |
3 files changed, 236 insertions, 129 deletions
diff --git a/Puzzle_Box/Puzzle_Box.h b/Puzzle_Box/Puzzle_Box.h index bd5b2fb..8a310fa 100644 --- a/Puzzle_Box/Puzzle_Box.h +++ b/Puzzle_Box/Puzzle_Box.h @@ -1,6 +1,3 @@ - - - /* Pin assignments for the version 1.1 shield */ static const int GPSrx = 4, GPStx = 3; // GPS static const int LCD_Enable = 6, LCD_RS = 5, LCD_RW = 7; // LCD @@ -15,14 +12,21 @@ void Msg(LiquidCrystal &lcd, const char *top, const char *bottom, unsigned long void drawEye(int location); void stepEyeAnimation(); void toggleEye(bool on); -void doMainStage(); -void doButtonStage(); + +void doIdle(); +void displayMessage(); +void doLatLong(); +void doHeading(); +void doEastOf(); + bool doUpdateDistance(); void doCheckOverrideSerial(); void doCheckAccess(); void PowerOff(); float toRandomUnit(int choice, float dist); -void showQuote(int quote); + +float toRandomUnit(int choice, float dist); +char* getUnitLabel(int choice); /* Fixed values should not need changing */ static const int DEF_ATTEMPT_MAX = 50; @@ -32,6 +36,37 @@ static const int EEPROM_OFFSET = 100; static const int MAIN_STAGE = 1; static const int BUTTON_STAGE = 2; +static const char MESSAGE = 3; +static const char LATLONG = 4; +static const char HEADING = 5; +static const char EASTOF = 6; +static const char OPEN = 7; + +static const byte STATES[] = { + 0, + MESSAGE, // Daniel!? Is it you? + MESSAGE, // Finally, you found me; Adventure time + LATLONG, + MESSAGE, // What's that? + HEADING, + MESSAGE, // Well that was fun, lets go back to camp + EASTOF, + MESSAGE, // Oh, btw, got you a gift + OPEN + }; + +// LATLONG +static const float LATLONG_LATITUDE = 46.09681; +static const float LATLONG_LONGITUDE = -121.65900; + +// HEADING +// 46.092838, -121.649211 +static const float HEADING_LATITUDE = 46.092838; +static const float HEADING_LONGITUDE = -121.649211; + +// EASTOF +static const float EASTOF_LONGITUDE = -121.62730; + /* Random Units */ static const int NUMBER_OF_UNITS = 4; @@ -45,9 +80,4 @@ static const int MAX_EYE_STEPS = 13; /* These values should be adjusted according to your needs */ static const int CLOSED_ANGLE = 80; // degrees static const int OPEN_ANGLE = 200; // degrees - -static const float DEST_LATITUDE = 47.272697; -static const float DEST_LONGITUDE = -122.021201; static const int RADIUS = 100; // meters - - diff --git a/Puzzle_Box/Puzzle_Box.pde b/Puzzle_Box/Puzzle_Box.pde index 61c8589..5ada15a 100644 --- a/Puzzle_Box/Puzzle_Box.pde +++ b/Puzzle_Box/Puzzle_Box.pde @@ -1,7 +1,7 @@ /* puzzle_box_sample.pde - Sample Arduino Puzzle Box sketch for MAKE. COPYRIGHT (c) 2008-2011 MIKAL HART. All Rights Reserved. - + This software is licensed under the terms of the Creative Commons "Attribution Non-Commercial Share Alike" license, version 3.0, which grants the limited right to use or modify it NON- @@ -10,21 +10,21 @@ derivative works are licensed under the IDENTICAL TERMS. For license details see http://creativecommons.org/licenses/by-nc-sa/3.0/ - + This source code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -This code is written to accompany the January, 2011 MAKE article + +This code is written to accompany the January, 2011 MAKE article entitled "Reverse Geocache Puzzle Box". - -This sketch illustrates how one might implement a basic puzzle box -that incorporates rudimentary aspects of the technology in Mikal + +This sketch illustrates how one might implement a basic puzzle box +that incorporates rudimentary aspects of the technology in Mikal Hart's Reverse Geocache(tm) puzzle. - + "Reverse Geocache" is a trademark of Mikal Hart. -For supporting libraries and more information see +For supporting libraries and more information see http://arduiniana.org. */ @@ -42,13 +42,14 @@ For supporting libraries and more information see /* Hardware Objects */ NewSoftSerial nss(GPSrx, GPStx); LiquidCrystal lcd(LCD_RS, LCD_RW, LCD_Enable, LCD_DB4, LCD_DB5, LCD_DB6, LCD_DB7); -TinyGPS tinygps; +TinyGPS tinygps; PWMServo servo; /* Running Information */ -int currentStage = MAIN_STAGE; -int attempt_counter; -int currentEyeAnimationStep = 0; +byte currentStage = MAIN_STAGE; +byte attempt_counter; +byte currentMessageId; +byte currentEyeAnimationStep = 0; long lastLoopTime = 0; long lastAniTime = 0; @@ -58,73 +59,95 @@ int currentUnit = 0; /* The Arduino setup() function */ -void setup() -{ - /*Turn on switch LED*/ - pinMode(LED_pin, OUTPUT); - digitalWrite(LED_pin,HIGH); - - /* attach servo motor */ - servo.attach(servo_control); - - /* establish a debug session with a host computer */ - Serial.begin(115200); - - /* establish communications with the GPS module */ - nss.begin(4800); - - /* establish communication with 8x2 LCD */ - lcd.createChar(0, eye1); - lcd.createChar(1, eye2); - lcd.createChar(2, eye3); - lcd.createChar(3, eye4); - lcd.createChar(4, eye5); - lcd.createChar(5, eye6); - lcd.createChar(6, eye7); - lcd.createChar(7, eye8); - lcd.begin(8, 2); // this for an 8x2 LCD -- adjust as needed - - /* Make sure Pololu switch pin is OUTPUT and LOW */ - pinMode(pololu_switch_off, OUTPUT); - digitalWrite(pololu_switch_off, LOW); - - /* make sure motorized latch is closed */ - servo.write(CLOSED_ANGLE); - - /* read the attempt counter from the EEPROM */ - attempt_counter = EEPROM.read(EEPROM_OFFSET); - if (attempt_counter == 0xFF) // brand new EEPROM? - attempt_counter = 0; - - - lastLoopTime = millis(); - - pinMode(BUTTON_PIN, INPUT); - digitalWrite(BUTTON_PIN, HIGH); - - randomSeed(analogRead(2)); +void setup() { + /*Turn on switch LED*/ + pinMode(LED_pin, OUTPUT); + digitalWrite(LED_pin,HIGH); + + /* attach servo motor */ + servo.attach(servo_control); + + /* establish a debug session with a host computer */ + Serial.begin(115200); + + /* establish communications with the GPS module */ + nss.begin(4800); + + /* establish communication with 8x2 LCD */ + lcd.createChar(0, eye1); + lcd.createChar(1, eye2); + lcd.createChar(2, eye3); + lcd.createChar(3, eye4); + lcd.createChar(4, eye5); + lcd.createChar(5, eye6); + lcd.createChar(6, eye7); + lcd.createChar(7, eye8); + lcd.begin(8, 2); // this for an 8x2 LCD -- adjust as needed + + /* Make sure Pololu switch pin is OUTPUT and LOW */ + pinMode(pololu_switch_off, OUTPUT); + digitalWrite(pololu_switch_off, LOW); + + /* make sure motorized latch is closed */ + servo.write(CLOSED_ANGLE); + + /* read the attempt counter from the EEPROM */ + attempt_counter = EEPROM.read(EEPROM_OFFSET); + currentMessageId = EEPROM.read(EEPROM_OFFSET + 1); + currentStage = EEPROM.read(EEPROM_OFFSET + 2); + + if (attempt_counter == 0xFF) { + // brand new EEPROM? + attempt_counter = 0; + currentMessageId = 0; + currentStage = 0; + } + + lastLoopTime = millis(); + + pinMode(BUTTON_PIN, INPUT); + digitalWrite(BUTTON_PIN, HIGH); + + randomSeed(analogRead(2)); } /* The Arduino loop() function */ -void loop() -{ +void loop() { // Check for a stage transition int buttonState = digitalRead(BUTTON_PIN); if (buttonState == LOW ) { - currentStage = BUTTON_STAGE; - } - - // Find our stage - switch (currentStage) { - case MAIN_STAGE: - doMainStage(); - break; + currentStage++; + + // Find our stage + switch (currentStage) { + case MESSAGE: + displayMessage(); + break; + + case LATLONG: + doLatLong(); + break; - case BUTTON_STAGE: - doButtonStage(); - break; + case HEADING: + doHeading(); + break; + case EASTOF: + doEastOf(); + break; + + case OPEN: + servo.write(OPEN_ANGLE); // and open the box + break; + + default: + // Dunno + break; + } + + } else { + doIdle(); } // Find the current distance just to be ready @@ -132,19 +155,19 @@ void loop() im_ready = true; } - // Check for override login attempts doCheckOverrideSerial(); /* Turn off after 5 minutes */ - if (millis() >= 300000) + if (millis() >= 300000) { PowerOff(); + } } /** * This is what we do while idle... */ -void doMainStage() { +void doIdle() { /* Timeline * 0 E On (500 ms) * 500 E Off (200 ms) @@ -188,7 +211,7 @@ void doMainStage() { } else { // On toggleEye(true); - + // Reset timer lastLoopTime = millis(); } @@ -197,18 +220,18 @@ void doMainStage() { /** * This is what we do when the button has been pressed. */ -void doButtonStage() { +void doLatLong() { // Plan to go back to the main stage currentStage = MAIN_STAGE; - // Screen on please. + // Screen on please. toggleEye(true); /* increment it with each run */ ++attempt_counter; // TODO: Witty Saying - //showQuote(4); + //showQuote(4); /* Greeting */ Msg(lcd, "Hello", "Craig!", 1500); @@ -229,7 +252,7 @@ void doButtonStage() { lcd.clear(); lcd.setCursor(0, 0); lcd.print(attempt_counter); - lcd.print(" of "); + lcd.print(" of "); lcd.print(DEF_ATTEMPT_MAX); delay(2000); @@ -247,10 +270,19 @@ void doButtonStage() { /* Save the new attempt counter */ EEPROM.write(EEPROM_OFFSET, attempt_counter); + EEPROM.write(EEPROM_OFFSET + 1, currentMessageId); + EEPROM.write(EEPROM_OFFSET + 2, currentStage); doCheckAccess(); } +void doHeading() { + +} + +void doEastOf() { + +} /** * This function updates the distance, if possible. @@ -269,7 +301,7 @@ bool doUpdateDistance() { if (fix_age != TinyGPS::GPS_INVALID_AGE) { /* Calculate the distance to the destination */ - currentDistance = TinyGPS::distance_between(lat, lon, DEST_LATITUDE, DEST_LONGITUDE); + currentDistance = TinyGPS::distance_between(lat, lon, LATLONG_LATITUDE, LATLONG_LONGITUDE); return true; } } @@ -299,11 +331,11 @@ void doCheckAccess() { lcd.clear(); lcd.setCursor(0, 0); lcd.print((long)toRandomUnit(currentUnit, currentDistance)); - lcd.setCursor(0, 1); + lcd.setCursor(0, 1); lcd.print(getUnitLabel(currentUnit)); - currentUnit = (currentUnit + 1) % NUMBER_OF_UNITS; - + currentUnit = (currentUnit + 1) % NUMBER_OF_UNITS; + delay(4000); Msg(lcd, "Access", "Denied!", 2000); } @@ -316,12 +348,12 @@ void doCheckAccess() { void PowerOff() { Msg(lcd, "Powering", "Off!", 2000); - lcd.clear(); - + lcd.clear(); + /*Turn off switch LED*/ pinMode(LED_pin, OUTPUT); digitalWrite(LED_pin,LOW); - + /* Bring Pololu switch control pin HIGH to turn off */ digitalWrite(pololu_switch_off, HIGH); @@ -329,20 +361,22 @@ void PowerOff() /* is being bypassed by the USB port. We'll wait a couple of */ /* minutes and then grant access. */ delay(120000); - servo.write(OPEN_ANGLE); // and open the box + servo.write(OPEN_ANGLE); // and open the box /* Reset the attempt counter */ - EEPROM.write(EEPROM_OFFSET, 0); - + EEPROM.write(EEPROM_OFFSET, 0); + EEPROM.write(EEPROM_OFFSET + 1, 0); + EEPROM.write(EEPROM_OFFSET + 2, 0); + /* Leave the latch open for 10 seconds */ - delay(10000); + delay(10000); /* And then seal it back up */ - servo.write(CLOSED_ANGLE); + servo.write(CLOSED_ANGLE); /* Exit the program for real */ exit(1); -} +} /* A helper function to display messages of a specified duration */ void Msg(LiquidCrystal &lcd, const char *top, const char *bottom, unsigned long del) @@ -363,12 +397,12 @@ void drawEye(int location) lcd.clear(); location = location + 2; - + for (int i = 0; i < 4; i++) { lcd.setCursor(location + i, 0); lcd.write(i); } - + for (int i = 0; i < 4; i++) { lcd.setCursor(location + i, 1); lcd.write(i + 4); @@ -377,7 +411,7 @@ void drawEye(int location) void stepEyeAnimation() { long delta = millis() - lastAniTime; - + if (delta >= 200) { drawEye(eyeAnimationSteps[currentEyeAnimationStep]); currentEyeAnimationStep++; @@ -391,11 +425,11 @@ void toggleEye(bool on) { if (on) { lcd.display(); digitalWrite(LED_pin, HIGH); - + } else { lcd.noDisplay(); digitalWrite(LED_pin, LOW); - } + } } /** @@ -406,22 +440,22 @@ float toRandomUnit(int choice, float dist) { switch (choice) { // meters case 0: - return dist; + return dist; // feet case 1: - return dist * 3.2808; + return dist * 3.2808; // cubits case 2: - return dist * 2.18; + return dist * 2.18; // hands case 3: - return dist * 9.84252; + return dist * 9.84252; - default: - return -1; + default: + return -1; } } @@ -451,13 +485,14 @@ char* getUnitLabel(int choice) { } } -void showQuote(int id) { - int pairs = messages[id].pairs; +void displayMessage() { + int id = currentMessageId++; + int pairs = messages[id].pairs; - for (int i = 0; i < pairs; i++) { - Msg(lcd, - messages[id].lines[i].line1, - messages[id].lines[i].line2, - 1000); - } + for (int i = 0; i < pairs; i++) { + Msg(lcd, + messages[id].lines[i].line1, + messages[id].lines[i].line2, + 1000); + } } diff --git a/Puzzle_Box/notes.txt b/Puzzle_Box/notes.txt index f2bb8ef..ff0cb0e 100644 --- a/Puzzle_Box/notes.txt +++ b/Puzzle_Box/notes.txt @@ -1,11 +1,53 @@ -* Turns on +######## +######## +Daniel!? +Is it u? -* Eyes shift -* Blink -* Rnd Blink/shift +Finally! -Once the button has been pressed: - * Witty comment - * Give distance in a random unit +You +Found me +Let's go +on an + +Adven- +ture + + +######## +######## + +We're +almost + +Hey! +What's + +Over +There + +######## +######## + +That was +fun! + +But now +Im tired + +Back to +Camp? + +######## +######## + +Ah, +Campfire + +Oh, hey, +I got + +You a +Gift |