understanding tinyGPS++

Here's a little overview to get you started:

NMEA GPS devices send "sentences" that contain various comma-separated fields. Each sentence starts with a '$' character and ends with a newline (CR/LF). Some sentences contain location and time, but not a date. Others have speed, but not altitude. So it usually takes several sentences before you have all the pieces that you want (see also this table).

These sentences are sent in a "batch", usually once per second. Then the GPS device is quiet until the next second begins. The GPS quiet time is a good time to do other time-consuming tasks in your sketch.

All GPS parsers convert these received characters into parsed values like ints (e.g., the current month) or floats (e.g., an altitude). Because the characters arrive slowly (for a 16MHz Arduino), it is very inefficient to wait for all of them to arrive. Some libraries do it anyway. :-/

Regarding specific libraries:

Adafruit_GPS gradually accumulates one sentence at a time (with a TIMER interrupt that reads the GPS characters), and then parses it all at once, when the newline arrives. This takes extra RAM for the sentence "buffer", and extra CPU time to copy and search through the buffer. It does not validate the checksum, so it may provide invalid data. It does not know anything about the entire batch of sentences or the GPS quiet time.

TinyGPS and TinyGPS++ "encode" one character at a time and let you know when a complete sentence has been parsed. It is a little more efficient, because it only buffers one field at a time, not the entire sentence. Unfortunately, the example programs are poorly structured and use a routine to wait for sentences to arrive. It does not know anything about the entire batch of sentences or the GPS quiet time.

My NeoGPS is smaller, faster and more accurate than all other libraries. It is the only library that merges multiple sentences (which contain various pieces) into one coherent fix structure. That structure remembers which pieces were really received and parsed into a structure member. There is one "valid" flag for each piece that you can test.

The typical NeoGPS program:

NMEAGPS  gps; // This parses the GPS characters
gps_fix  fix; // This holds on to the latest values

void setup()
{
  Serial.begin(9600);
  gpsPort.begin(9600);
}

void loop()
{
  while (gps.available( gpsPort )) {
    fix = gps.read();

    Serial.print( F("Location: ") );
    if (fix.valid.location) {
      Serial.print( fix.latitude(), 6 );
      Serial.print( ',' );
      Serial.print( fix.longitude(), 6 );
    }

    Serial.print( F(", Altitude: ") );
    if (fix.valid.altitude)
      Serial.print( fix.altitude() );

    Serial.println();
  }
}

This code does not "block" with a while loop or delay. loop runs over and over, until multiple sentences have been received and parsed into a new fix. NeoGPS is the only library that knows when a batch of sentences is complete and the GPS quiet time begins.

After "reading" the fix structure from the gps object, you can look at the valid flags and data members. All of the fix members have been completely received; testing fix.valid.location confirms that the lat/lon was received, and calling fix.latitude() simply returns the value that is stored in the structure.

One final advantage of NeoGPS is that you can configure it to parse and save only the fields that you care about. Everything else is quickly skipped, using no RAM and very little CPU time. It is very common for a NeoGPS program size to be thousands of bytes smaller, and use hundreds of bytes less RAM.

If you want to try it, it is also available from the Arduino IDE Library Manager, under the menu Sketch -> Include Library -> Manage Libraries. The above code is from the example NMEAsimple.ino. Even if you don't use the library, be sure to look at the examples for the proper program structure. The Troubleshooting page describes many typical problems, especially when using other libraries.

Cheers,
/dev