Reverse geocache code

Hi,

I'm having some trouble with the code for my reverse geocache box.
I wanted to modify Michal Hartman's orignial code found at www.arduiniana.org to handle multiple locations.

I'm using a variable stored to EEPROM to keep track of what stage of the puzzle the user is in.

The problem: It seems that once the user is at the first location, the box grants access immediately. So it seems to be skipping over the sequence counter.

I would really appreciate some guidance on what I'm doing wrong with this.

#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_uno = 50.904735;
static const float DEST_LONGITUDE_uno = -114.105814;
static const float DEST_LATITUDE_dos = 50.940625;
static const float DEST_LONGITUDE_dos = -114.087974;
static const float DEST_LATITUDE_tres = 50.904747;
static const float DEST_LONGITUDE_tres = -114.107639;
static const float DEST_LATITUDE_quatro = 50.903128;
static const float DEST_LONGITUDE_quatro = -114.104571;
static const float DEST_LATITUDE_cinque = 50.903128;
static const float DEST_LONGITUDE_cinque = -114.104571;

int stage;
float DEST_LATITUDE;
float DEST_LONGITUDE;

static const int RADIUS = 10; // 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;
    
  /* read the stage counter */
  stage = EEPROM.read(0);
  if (stage == 0xFF)
    stage = 1;

  /* 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 <= 12)&&(day <= 25))
    {
      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("December);
      lcd.setCursor(0,1);
      lcd.print("25");
      
      delay(10000);
      PowerOff();
    }  
    */
    
     /* Location 1 */
      if (stage == 1);
        {
          DEST_LATITUDE = DEST_LATITUDE_uno;
          DEST_LONGITUDE = DEST_LONGITUDE_uno;
        }
          
     /* Location 2 */
      if (stage == 2);
        {
          DEST_LATITUDE = DEST_LATITUDE_dos;
          DEST_LONGITUDE = DEST_LONGITUDE_dos;
        }
        
      /* Location 3 */
      if (stage == 3);
        {
          DEST_LATITUDE = DEST_LATITUDE_tres;
          DEST_LONGITUDE = DEST_LONGITUDE_tres;
        }
        
      if (stage == 4);
      {
        DEST_LATITUDE = DEST_LATITUDE_quatro;
        DEST_LONGITUDE = DEST_LONGITUDE_quatro;
      }
     /* 
      if ((stage == 5);
      {
        if ((year <= 2011)&&(month <= 12)&&(day <= 27));
            {
              lcd.clear();
              lcd.setCursor(0, 0);
              lcd.print("Not");
              lcd.setCursor(0, 1);
              lcd.print("Yet");
              delay(2000);
              PowerOff();
            }
            
        else
        {
          DEST_LATITUDE = DEST_LATITUDE_cinque;
          DEST_LONGITUDE = DEST_LONGITUDE_cinque; 
        }
      } 
      */
        
        
    /* 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)
      {
        stage++;
        EEPROM.write(0, stage);
        if (stage == 5);
          {
            Msg(lcd, "Access", "granted!", 2000);
            servo.write(OPEN_ANGLE);
          }
      }

      /* Nope.  Print the distance. */
      else
      {
        EEPROM.write(0, stage);
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("stage");
        lcd.clear();
        lcd.print(stage);
        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);
} 


/* I have removed the credits to meet the word limit for this post */

What does the serial debug output tell us?

Yup.

                if (stage == 5);

That semicolon is killing you! Get rid of it.

I also note that you have commented out the code which sets the location for stage 5.

Then there's this code (without the semicolon) which will grant access when you are at stage 4:

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

To grant access at stage 5 you need:

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

Pete