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 */