From b6b6bdcf8256c635caeaa53c227e2444ed36c5b4 Mon Sep 17 00:00:00 2001 From: Jesse Morgan Date: Tue, 12 Aug 2014 08:27:34 -0700 Subject: Getting the box ready for Daniel. This is a first pass at cleaning up the code and getting the libraries to build with Arduino 1.0. I've started reworking the code for the new adventure. Dialog notes are in notes.txt. I've also added a Makefile to build from the command line. --- Puzzle_Box/Puzzle_Box.h | 52 ++++++++-- Puzzle_Box/Puzzle_Box.pde | 257 ++++++++++++++++++++++++++-------------------- Puzzle_Box/notes.txt | 56 ++++++++-- 3 files changed, 236 insertions(+), 129 deletions(-) (limited to 'Puzzle_Box') 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 -- cgit v1.2.3