reverse geocache with multiple sequential locations

Hi,

I’m working on a reverse geocache box like the one built by Mikal Hart Building a Puzzle Box | Arduiniana.

I am not sure how to implement multiple locations into this project however.
I would like the box to go from a target of DEST_LATITUDE and DEST_LONGITUDE to DEST_LATITUDE2 and DEST_LONGITUDE2.

From my limited understanding, every time the box boots up it goes through the setup() and loop() functions. How can I make the Arduino “remember” that DEST_(lat and long)1 have been completed and to target destination 2 in the loop().

Here is the code so far:

#include <PWMServo.h>
#include <NewSoftSerial.h>
#include <TinyGPS.h>
#include <EEPROM.h>
#include <LiquidCrystal.h>

void PowerOff();

#if 0 // Change this to 1 if you have the version 1.0 shield

/* Pin assignments for the version 1.0 shield */
static const int GPSrx = 2, GPStx = 3;
static const int LCD_Enable = 11, LCD_RS = 10, LCD_RW = 7;
static const int LCD_DB4 = 19, LCD_DB5 = 17, LCD_DB6 = 18, LCD_DB7 = 16;
static const int pololu_switch_off = 15; // Pololu switch control
static const int servo_control = 9;
static const int LED_pin = 12;

#else

/* 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
static const int LCD_DB4 = 16, LCD_DB5 = 17, LCD_DB6 = 18, LCD_DB7 = 19;
static const int pololu_switch_off = 12; // Pololu switch control
static const int servo_control = 9; // Servo control
static const int LED_pin = 2; // The button LED

#endif

/* These values should be adjusted according to your needs */
static const int CLOSED_ANGLE = 90; // degrees
static const int OPEN_ANGLE = 165; // degrees
static const float DEST_LATITUDE =  50.803456;
static const float DEST_LONGITUDE = -114.803456;
static const float DEST_LATITUDE2 =  51.803456;
static const float DEST_LONGITUDE2 = -115.803456;
static const float DEST_LATITUDE3 =  52.803456;
static const float DEST_LONGITUDE3 = -116.803456;


static const int RADIUS = 2000; // meters

/* Fixed values should not need changing */
static const int DEF_ATTEMPT_MAX = 50;
static const int EEPROM_OFFSET = 100;

/* The basic objects needed */
NewSoftSerial nss(GPSrx, GPStx);
LiquidCrystal lcd(LCD_RS, LCD_RW, LCD_Enable, LCD_DB4, LCD_DB5, LCD_DB6, LCD_DB7);
TinyGPS tinygps; 
int attempt_counter;
PWMServo servo;

/* A helper function to display messages of a specified duration */
void Msg(LiquidCrystal &lcd, const char *top, const char *bottom, unsigned long del)
{
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print(top);
  lcd.setCursor(0, 1);
  lcd.print(bottom);
  delay(del);
}

/* The Arduino setup() function */
void setup()
{
  /* turn on button 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.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;

  /* increment it with each run */
  ++attempt_counter;

  /* Greeting */
  Msg(lcd, "Hello", "", 2000);

  /* Game over? */
  if (attempt_counter >= DEF_ATTEMPT_MAX)
  {
    Msg(lcd, "Sorry!", "No more", 2000);
    Msg(lcd, "attempts", "allowed!", 2000);
    PowerOff();
  }

  /* Print out the attempt counter */
  Msg(lcd, "This is", "attempt", 2000);
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print(attempt_counter);
  lcd.print(" of "); 
  lcd.print(DEF_ATTEMPT_MAX);
  delay(2000);

  /* Save the new attempt counter */
  EEPROM.write(EEPROM_OFFSET, attempt_counter);

  Msg(lcd, "Seeking", "Signal..", 0);
}

/* The Arduino loop() function */
void loop()
{

  /* Has a valid NMEA sentence been parsed? */
  if (nss.available() && tinygps.encode(nss.read()))
  {
    float lat, lon;
    unsigned long fix_age;
    
    int year;
    byte month, day, hour, minute, second, hundredths;
    tinygps.crack_datetime(&year,&month,&day,&hour,&minute,&second,&hundredths);
    
    if((year <= 2011)&&(month <= 11)&&(day <= 3))
    {
      lcd.clear();
      lcd.setCursor(0,0);
      lcd.print("Try");
      lcd.setCursor(0,1);
      lcd.print("Again");
      delay(4000);
      lcd.clear();
      lcd.setCursor(0,0);
      lcd.print("November");
      lcd.setCursor(0,1);
      lcd.print("3");
      
      delay(10000);
      PowerOff();
    }  

    /* Have we established our location? */
    tinygps.f_get_position(&lat, &lon, &fix_age);
    if (fix_age != TinyGPS::GPS_INVALID_AGE)
    {
      /* Calculate the distance to the destination */
      float distance_meters = TinyGPS::distance_between(lat, lon, DEST_LATITUDE, DEST_LONGITUDE);

      /* Are we close?? */
      if (distance_meters <= RADIUS)
      {
        Msg(lcd, "Access", "granted!", 2000);
        servo.write(OPEN_ANGLE);
      }

      /* Nope.  Print the distance. */
      else
      {
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("Distance");
        lcd.setCursor(0, 1);
        if (distance_meters < 1000)
        {
          lcd.print((int)distance_meters);
          lcd.print(" m.");
        }

        else
        {
          lcd.print((int)(distance_meters / 1000));
          lcd.print(" km.");
        }
        delay(4000);
        Msg(lcd, "Access", "Denied!", 2000);
      }

      PowerOff();
    }
  }

  /* Turn off after 5 minutes */
  if (millis() >= 300000)
    PowerOff();
}

/* Called to shut off the system using the Pololu switch */
void PowerOff()
{
  Msg(lcd, "Powering", "Off!", 2000);
  lcd.clear(); 
  
  /* Bring Pololu switch control pin HIGH to turn off */
  digitalWrite(pololu_switch_off, HIGH);

  /* This is the back door.  If we get here, then the battery power */
  /* 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 

  /* Reset the attempt counter */
  EEPROM.write(EEPROM_OFFSET, 0); 
  
  /* Leave the latch open for 10 seconds */
  delay(10000); 

  /* And then seal it back up */
  servo.write(CLOSED_ANGLE); 

  /* Exit the program for real */
  exit(1);
} 


/*
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-
COMMERCIALLY, so long as appropriate credit is given and
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 
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 
Hart's Reverse Geocache(tm) puzzle.
 
"Reverse Geocache" is a trademark of Mikal Hart.

For supporting libraries and more information see 

  http://arduiniana.org.
*/

From my limited understanding, every time the box boots up it goes through the setup() and loop() functions. How can I make the Arduino "remember" that DEST_(lat and long)1 have been completed and to target destination 2 in the loop().

It goes through setup() once and loop() infinitely.

You need to store data that you want to persist (Hey, you found point 1!) in EEPROM, in loop() when that data is created. In setup(), you need to read data that has been persisted in EEPROM, so you know what to do in loop().