Reverse Geocache Box coding problem

I made a Reverse Geocache Box based off of Mikal Hart’s design (http://archive.makezine.com/25/puzzlebox/) for an electronics course at my school. I also based my design off of Tyler Cooper’s Adafruit guide (http://learn.adafruit.com/reverse-geocache-engagement-box/overview) since we both used an Adafruit Ultimate GPS receiver.

I’m having an issue serially transmitting the GPS data from the GPS reciever to the TinyGPS library that processes the data to calculate the distance that the box is from its destination coordinates. It seems that the speed (baud rate?) of the serial data transmission on the “send” end is too slow so the tinygps.encode() function doesn’t recognize any complete data sentences, which is required in order to determine the GPS receiver’s latitude and longitude. Attached is my code, I’ve changed the destination coordinates to the Empire State Building in order to hide my real location. I would like the tinygps.encode() function to determine distance (in meters) between the box and its destination coordinates so this data can be displayed on the LCD for the user. Everything else with the box such as the servo, the pushbutton, sleep mode, etc. seems to work great.

Please help?

Also, I am still sort of a beginner at writing code so please go easy on me. There are likely easier ways to do what I’m trying to do.

ReverseGeocacheBoxForum.ino (9.22 KB)

Does it work as expected if you don't power down the GPS when you sleep? After a cold start the GPS may take much longer to get a fix. You may need to wait much longer to get a fix after waking from sleep.

  if (mySerial.available() > 0)
  {
    Serial.write(mySerial.read());                         // send raw GPS data to serial monitor
    
    if (tinygps.encode(mySerial.read()))

You read two consecutive characters from mySerial but "mySerial.available() > 0" only guarantees you that there is at least one. I think what you may have intended here was something like this:

    char c = mySerial.read();
    Serial.write(c);
    if (tinygps.encode(c))

Pete

Yes, it works whether cold start or not. I know that I am getting a fix (there is an indicator LED on the GPS receiver) and I’ve been able to view the GPS data on the serial monitor.

I’ve revised my code and I’m about to go try the box outside. Just to make sure, I need to put char c = mySerial.read(); in my initialization section before void setup(), correct?

And now parse_gps(); should look like this?

void parse_gps()                                           // interpret GPS data if fix is found
{
    Serial.write(c);                                       // send raw GPS data to serial monitor
    if (tinygps.encode(c))
    { 
      float lat, lon;                                      // float latitude and longitude from GPS
      unsigned long fix_age;
      
      tinygps.f_get_position(&lat, &lon, &fix_age);        // get latitude, longitude, and fix age
      if (fix_age != TinyGPS::GPS_INVALID_AGE)             // tests whether GPS data is new or old
      {
        float distance_meters = TinyGPS::distance_between(lat, lon, dest_latitude, dest_longitude);  
        if (distance_meters <= radius)                     // find distance between current coordinates and destination
        {                                                  // unlock box if the distance is within the target radius
          lcd.clear();                                     // clear LCD
          lcd.print(" Access granted ");                   // display "Access granted"
          servolock.write(open_angle);                     // move servo to 'unlock' position
          delay(5000);                                     // display message for 5 seconds
          sleep();                                         // activate sleep function
        }
        else
        {                                                  // distance to destination is outside of target radius
          lcd.clear();                                     // clear LCD
          lcd.print("   Distance:    ");                   // display "Distance:"
          lcd.setCursor(0, 1);                             // second line of LCD
          lcd.print("    ");                               // display spacer
          lcd.print((int)distance_meters);                 // display integer value of distance to destination in meters
          lcd.print(" meters");                            // display "meters"
          delay(5000);                                     // display message for 5 seconds
          lcd.clear();                                     // clear LCD        
          lcd.print(" Access denied  ");                   // display "Access denied"
          delay(5000);                                     // display message for 5 seconds
          sleep();                                         // activate sleep function
        }
      }
    }
    else
    {
      lcd.setCursor(0, 0);
      lcd.print(" Searching for  ");
      lcd.setCursor(0, 1);
      lcd.print("  GPS signal    ");                         // display "Searching for GPS signal" on LCD
      delay(1000);                                           // display message for 1 second
      sleep_counter++;                                       // increment sleep counter
    }
}

Thanks to both of you for your input! I’m open to any more comments or tips.