TinyGPS++

A *NEW* Full-featured GPS/NMEA Parser for Arduino

TinyGPS++ is a new Arduino library for parsing NMEA data streams provided by GPS modules.

Like its predecessor, TinyGPS, this library provides compact and easy-to-use methods for extracting position, date, time, altitude, speed, and course from consumer GPS devices. 

However, TinyGPS++’s programmer interface is considerably simpler to use than TinyGPS, and the new library can extract arbitrary data from any of the myriad NMEA sentences out there, even proprietary ones.

Download and Installation

To install this library, download here, unzip the archive into the Arduino “libraries” folder, and restart Arduino. You should rename the folder “TinyGPSPlus”.
Download

History

TinyGPS++ is the immediate inheritor of TinyGPS, a popular compact parser that is used in Arduino installations around the world.  TinyGPS++ is not quite as ‘tiny’ as its older sibling, but its powerful and extremely easy-to-use new object model and useful new feature set make it an attractive alternative.

Usage

Let’s say you have an Arduino hooked to an off-the-shelf GPS device and you want to display your altitude.  You would simply create a TinyGPS++ instance like this:

#include "TinyGPS++.h"
TinyGPSPlus gps;

Repeatedly feed it characters from your GPS device:

while (ss.available() > 0)
  gps.encode(ss.read());

Then query it for the desired information:

if (gps.altitude.isUpdated())
  Serial.println(gps.altitude.meters());

Differences from TinyGPS

Although TinyGPS++ shares much the same compact parsing engine with TinyGPS, its programmer interface is somewhat more intuitive.  As a simple example, here’s how easy it is to print out the current latitude, longitude, and altitude in TinyGPS++:

Serial.print("LAT=");  Serial.println(gps.location.lat(), 6);
Serial.print("LONG="); Serial.println(gps.location.lng(), 6);
Serial.print("ALT=");  Serial.println(gps.altitude.meters());

Both libraries extract basic position, altitude, course, time, and date, etc. from two common NMEA sentences, $GPGGA and $GPRMC. But there are a number of other interesting sentences out there, both NMEA-defined and vendor-proprietary, just waiting to be harvested.

Consider the obscure $GPRMB, for example, which provides “recommended minimum navigation information” if you have a destination waypoint defined.

$GPRMB,A,4.08,L,EGLL,EGLM,5130.02,N,00046.34,W,004.6,213.9,122.9,A*3D

With TinyGPS++ it is now possible to extract just the “L” in the third field (it means “steer Left!”). It’s easy with the new TinyGPSCustom watcher object:

TinyGPSCustom steerDirection(gps, "GPRMB", 3);
...
Serial.print(steerDirection.value()); // prints "L" or "R"

Naturally, this extra functionality comes at some cost.  TinyGPS++ consumes somewhat more memory than TinyGPS, and it’s interface is incompatible.  So how to decide whether to update?  Here’s a guide:

Consider TinyGPS++ over TinyGPS if:

  • Compatibility with existing code (using TinyGPS) isn’t necessary.
  • Your sketch is not close to reaching RAM or flash resource limits.
  • You are running on Due or processor which can take advantage of the higher precision of 64-bit “double” floating-point.
  • You prefer the more intuitive object model.
  • You need to query for NMEA data beyond the basic location, date, time, altitude, course, speed, satellites or hdop.

Feeding the Hungry Object

To get TinyGPS++ to work, you have to repeatedly funnel the characters to it from the GPS module using the encode() method. For example, if your GPS module is attached to pins 4(RX) and 3(TX), you might write code like this:

SoftwareSerial ss(4, 3);
void loop()
{
  while (ss.available() > 0)
    gps.encode(ss.read);
  ...

After the object has been “fed” you can query it to see if any data fields have been updated:

  if (gps.location.isUpdated())
  {
    Serial.print("LAT="); Serial.print(gps.location.lat(), 6);
    Serial.print("LNG="); Serial.println(gps.location.lng(), 6);
  }
} // end loop()

The TinyGPS++ Object Model

The main TinyGPS++ object contains several core sub-objects:

  • location – the latest position fix
  • date – the latest date fix (UT)
  • time – the latest time fix (UT)
  • speed – current ground speed
  • course – current ground course
  • altitude – latest altitude fix
  • satellites – the number of visible, participating satellites
  • hdop – horizontal diminution of precision

Each provides methods to examine its current value, sometimes in multiple formats and units. Here’s a complete list:

Serial.println(gps.location.lat(), 6); // Latitude in degrees (double)
Serial.println(gps.location.lng(), 6); // Longitude in degrees (double)
Serial.print(gps.location.rawLat().negative ? "-" : "+");
Serial.println(gps.location.rawLat().deg); // Raw latitude in whole degrees
Serial.println(gps.location.rawLat().billionths);// ... and billionths (u16/u32)
Serial.print(gps.location.rawLng().negative ? "-" : "+");
Serial.println(gps.location.rawLng().deg); // Raw longitude in whole degrees
Serial.println(gps.location.rawLng().billionths);// ... and billionths (u16/u32)
Serial.println(gps.date.value()); // Raw date in DDMMYY format (u32)
Serial.println(gps.date.year()); // Year (2000+) (u16)
Serial.println(gps.date.month()); // Month (1-12) (u8)
Serial.println(gps.date.day()); // Day (1-31) (u8)
Serial.println(gps.time.value()); // Raw time in HHMMSSCC format (u32)
Serial.println(gps.time.hour()); // Hour (0-23) (u8)
Serial.println(gps.time.minute()); // Minute (0-59) (u8)
Serial.println(gps.time.second()); // Second (0-59) (u8)
Serial.println(gps.time.centisecond()); // 100ths of a second (0-99) (u8)
Serial.println(gps.speed.value()); // Raw speed in 100ths of a knot (i32)
Serial.println(gps.speed.knots()); // Speed in knots (double)
Serial.println(gps.speed.mph()); // Speed in miles per hour (double)
Serial.println(gps.speed.mps()); // Speed in meters per second (double)
Serial.println(gps.speed.kmph()); // Speed in kilometers per hour (double)
Serial.println(gps.course.value()); // Raw course in 100ths of a degree (i32)
Serial.println(gps.course.deg()); // Course in degrees (double)
Serial.println(gps.altitude.value()); // Raw altitude in centimeters (i32)
Serial.println(gps.altitude.meters()); // Altitude in meters (double)
Serial.println(gps.altitude.miles()); // Altitude in miles (double)
Serial.println(gps.altitude.kilometers()); // Altitude in kilometers (double)
Serial.println(gps.altitude.feet()); // Altitude in feet (double)
Serial.println(gps.satellites.value()); // Number of satellites in use (u32)
Serial.println(gps.hdop.value()); // Horizontal Dim. of Precision (100ths-i32)

Validity, Update status, and Age

You can examine an object’s value at any time, but unless TinyGPS++ has recently been fed from the GPS, it should not be considered valid and up-to-date. The isValid() method will tell you whether the object contains any valid data and is safe to query.

Similarly, isUpdated() indicates whether the object’s value has been updated (not necessarily changed) since the last time you queried it.

Lastly, if you want to know how stale an object’s data is, call its age() method, which returns the number of milliseconds since its last update. If this returns a value greater than 1500 or so, it may be a sign of a problem like a lost fix.

Debugging

When a TinyGPS++ sketch fails, it’s usually because the object received an incomplete NMEA stream, or perhaps none at all.

Fortunately, it’s pretty easy to determine what’s going wrong using some built-in diagnostic methods:

  • charsProcessed() – the total number of characters received by the object
  • sentencesWithFix() – the number of $GPRMC or $GPGGA sentences that had a fix
  • failedChecksum() – the number of sentences of all types that failed the checksum test
  • passedChecksum() – the number of sentences of all types that passed the checksum test

If your sketch has been running a while but charsProcessed() is returning 0, you likely have a problem with your wiring or serial connection. (If data never arrives from the GPS unit, it stands to reason it’s not getting to TinyGPS++.) I often insert a little debug clause into my GPS sketches detects this condition then prints out the incoming stream:

// Debug: if we haven't seen lots of data in 5 seconds, something's wrong.
if (millis() > 5000 && gps.charsProcessed() < 10) // uh oh
{
  Serial.println("ERROR: not getting any GPS data!");
  // dump the stream to Serial
  Serial.println("GPS stream dump:");
  while (true) // infinite loop
    if (ss.available() > 0) // any data coming in?
      Serial.write(ss.read());
}

Another common failure is when the sentences sent to TinyGPS++ are incomplete. This usually happens when you retrieve the characters from the GPS so slowly or infrequently that some are lost. The symptom is easy to spot: checksum failure.

Explanation: Every NMEA sentence ends with a numeric field that represents a mathematical summing of all the characters in the sentence. It’s there to ensure data integrity. If this number doesn’t match the actual sum (perhaps because some characters went awry), TinyGPS++ simply discards the entire sentence and increments an internal “checksum failed” counter. You can read this counter with:

Serial.print("Sentences that failed checksum=");
Serial.println(gps.failedChecksum());

// Testing overflow in SoftwareSerial is sometimes useful too.
Serial.print("Soft Serial device overflowed? ");
Serial.println(ss.overflow() ? "YES!" : "No");

If the checksum counter is continually incrementing, you have a problem. (Hint: don’t use delay() in your sketch.)

Custom NMEA Sentence Extraction

One of the great new features of TinyGPS++ is the ability to extract arbitrary data from any NMEA or NMEA-like sentence. Read up on some of the interesting sentences there are out there, then check to make sure that your GPS receiver can generate them.

The idea behind custom extraction is that you tell TinyGPS++ the sentence name and the field number you are interested in, like this:

TinyGPSCustom magneticVariation(gps, "GPRMC", 10)

This instructs TinyGPS++ to keep an eye out for $GPRMC sentences, and extract the 10th comma-separated field each time one flows by. At this point, magneticVariation is a new object just like the built-in ones. You can query it just like the others:

if (magneticVariation.isUpdated())
{
  Serial.print("Magnetic variation is ");
  Serial.println(magneticVariation.value());
}

Establishing a fix

TinyGPS++ objects depend on their host sketch to feed them valid and current NMEA GPS data. To ensure their world-view is continually up-to-date, three things must happen:

  1. You must continually feed the object serial NMEA data with encode().
  2. The NMEA sentences must pass the checksum test.
  3. For built-in (non-custom) objects, the NMEA sentences must self-report themselves as valid. That is, if the $GPRMC sentence reports a validity of “V” (void) instead of “A” (active), or if the $GPGGA sentence reports fix type “0” (no fix), then the position and altitude information is discarded (though time and date are retained).

It may take several minutes for a device to establish a fix, especially it has traveled some distance or a long time has elapsed since its last use.

Distance and Course

If your application has some notion of a “waypoint” or destination, it is sometimes useful to be able to calculate the distance to that waypoint and the direction, or “course”, you must travel to get there. TinyGPS++ provides two methods to get this information, and a third (cardinal()) to display the course in friendly, human-readable compass directions.

const double EIFFEL_TOWER_LAT = 48.85826;
const double EIFFEL_TOWER_LNG = 2.294516;
double distanceKm =
  TinyGPSPlus.distanceBetween(
    gps.location.lat(),
    gps.location.lng(),
    EIFFEL_TOWER_LAT,
    EIFFEL_TOWER_LNG) / 1000.0;
double courseTo =
  TinyGPSPlus.courseTo(
    gps.location.lat(),
    gps.location.lng(),
    EIFFEL_TOWER_LAT,
    EIFFEL_TOWER_LNG);
Serial.print("Distance (km) to Eiffel Tower: ");
Serial.println(distanceKm);
Serial.print("Course to Eiffel Tower: ");
Serial.println(courseTo);
Serial.print("Human directions: ");
Serial.println(TinyGPSPlus.cardinal(courseTo));

Library Version

You can retrieve the version of the TinyGPS++ library by calling the static member libraryVersion().

Serial.println(TinyGPSPlus::libraryVersion());

Sample Sketches

TinyGPS++ ships with several sample sketch which range from the simple to the more elaborate. Start with BasicExample, which demonstrates library basics without even requiring a GPS device, then move onto FullExample and KitchenSink. Later, see if you can understand how to do custom extractions with some of the other examples.

Acknowledgements

Thanks go out to the many Arduino forum users for outstanding help in testing and popularizing TinyGPS, this library’s predecessor. Thanks especially to Maarten Lamers, who wrote the wiring library that originally gave me the idea of how to organize TinyGPS++.

All input is appreciated.

Mikal Hart

Page last updated on September 28, 2014 at 11:35 am
439 Responses → “TinyGPS++”

  1. Mikal

    10 years ago

    Thanks Alan. I’m glad to hear it (almost) works right out of the box on such a different core. You’ve inspired me to remove the reliance on those homespun Arduino functions like sq() and radians(). As you say, they are easy to roll yourself. Don’t have an easy way to remove my reliance on millis() though. Ideas?


  2. Mike

    10 years ago

    Love this, thank you so much!


  3. exemusBeta

    10 years ago

    Noticed that here uses the millis() function in the library. So is there a problem that can happen with overflow. I want to run the program for a long time(like a year). How should I avoid overflow?
    Thanks in advance !!!


  4. Mark

    10 years ago

    Mikal,

    Forgive my lack of programming knowledge… What changes do i need to make to get a distance value to cm level? Units are currently in Km and I guess use of unsigned long means no decimal places. If it helps, the distances I play with are less than 100Km so a value in the form 00.00001 would allow me to get down to 1cm and up to 99.99999Km

    Thanks for creating such great code. It helps me to learn by doing.

    Mark


  5. Mark

    10 years ago

    Mikal,

    Please disregard my earlier question. I did some reading and worked out that I should change the unsigned long to a float and the PrintInt to PrintFloat.

    Thanks again for a great routine.

    Mark


  6. Mikal

    10 years ago

    @Mike, :)


  7. Mikal

    10 years ago

    @exemus,

    Good news for you: as long as you are regularly sending the TinyGPS++ object data (i.e. at least once every 47 days), you won’t have any risk of overflow. The library only uses millis() to calculate how much time has elapsed between valid sentences, which is normally just a second at most.


  8. Mark

    10 years ago

    Mikal,

    Now that I have distance in a xx.xxxxxx format, I find that I no longer have a space between the distance and course values when viewed on the Serial Monitor. I suspect this is due to the section…

    static void printFloat(float val, bool valid, int len, int prec)
    {
    if (!valid)
    {
    while (len– > 1)
    Serial.print(‘*’);
    Serial.print(‘ ‘);
    }
    else
    {
    Serial.print(val, prec);
    int vi = abs((int)val);
    int flen = prec + (val = 1000 ? 4 : vi >= 100 ? 3 : vi >= 10 ? 2 : 1;
    for (int i=flen; i<len; ++i)
    Serial.print(' ');
    }
    smartDelay(0);
    }

    which I guess is working out the field length and adding spaces but I can't work out how. Any clues would be welcome.

    Thanks,

    Mark


  9. Doug

    10 years ago

    I just used for the frist time with a salvaged GPS module and setup worked on first attempt. Excellent library with really intuitive commands. Thanks very much for providing this to the community!
    (Sorry about the masked email address.)


  10. Mikal

    10 years ago

    Mark, is this one of the example sketches you’re running?


  11. Mikal

    10 years ago

    Thanks Doug. Glad you are finding the library useful.


  12. Larry

    10 years ago

    Mikal,

    I have a GY-GPS6MV2 with a UBLOX NEO-6M and tried the full example with a UNO R3. I get a HDOP between 70 and a little over 100. I have also run this GPS on a UBLOX program (u-center)and get an HDOP of 0.6 to 1.1. It appears to me that TinyGPS++ has increased the HDOP value. Why do the values differ by two orders of magnitude in TinyGPS++?

    This is an example of a string I captured using “RS232 data logger” and the HDOP value is 0.87 $GPGGA,021542.00,3756.24947,N,10452.17668,W,1,10,0.87,1900.2,M,-22.6,M,,*56


  13. Mikal

    10 years ago

    Hi Larry,

    HDOP is one of a handful of TinyGPS++ objects–others include speed, course, and altitude–that return integral values in 100th of units. The reason for this is to avoid having to work with floating point numbers if the user wants to avoid them, because floating point support uses lots of precious memory.

    For example, if you examine tinygps.speed.value(), you’ll get the speed in 100ths of a knot.

    However, for those other object types I give you the option of using float if you value the convenience. For example, if you look at tinygps.speed.knots() you’ll get a floating point number. I don’t offer this for HDOP though. Would you like to see something like tinygps.HDOP.units()?


  14. Tim

    10 years ago

    I have an iTead GPS receiver working with an UNO. I compared the time on the serial monitor with a GPS app on my Android phone and an internet time source, the time shown from the iTead is 9 seconds behind the other two sources. Can someone else compare times and see if it is just me seeing this?
    Thanks,
    Tim in Toccoa, GA


  15. Larry

    10 years ago

    Mikal,

    After digging through the .h and .cpp files I found where it said that HDOP was in 100ths though it took me a while to figure it out. I’m mainly interested in whether the value is 2 or less so it doesn’t make a difference if its in 100ths as then I can use values >= to 200.

    I notice that the “deviceExample” uses almost a third of the available memory and the “fullExample” uses almost half. Is that in part due to the size of the the tinygpsplus header and cpp files? I haven’t done any C programming for more than 10 years and am now brushing up on it by reading “New C Primer Plus” (old copy) and running some of the examples.

    I’m thinking that I would like to use the GPS and maybe an IMU, altimeter, and compass to design a autopilot for an UAV. I’m concerned that I may need every bit of computing power of the ATmega328p to do this and the TinyGPS++ header and cpp files may need to be more compact.

    Thanks for your reply to HDOP


  16. Another Tim

    10 years ago

    Mikal,

    just wanted to extend gratitude from this rather inexperienced Arduino user and/or programmer. Your library worked out of the box with my UNO R3 and a u-blox NEO-6M.

    I haven’t delved into the advanced examples yet. Baby steps!

    Regards,

    Tim


  17. Viegas

    10 years ago

    Hi, so I’m switching from TinyGPS to TinyGPS++ for a Cansat and I can’t find any examples of complete code. Can you provide me with a example of the full code for a GPS?


  18. Mikal

    10 years ago

    @Another Tim, thanks!


  19. Mikal

    10 years ago

    @Viegas, try the examples that ship with the library at File/Examples/TinyGPSPlus.


  20. Electrophile

    10 years ago

    Hi, Sorry for the delayed reply. Yes I’m trying DeviceExample.ino from the examples folder. I tried various baud rates, all the way from 1200 to 115200 but nothing worked. The Adafruit library worked right away though. I even tried the TinyGPS library (without the ++) and that did not work too. I’ll also try an AVR C library and see if that works.


  21. Mikal

    10 years ago

    @Electrophile, I haven’t seen your code, but my best guess is that you have your RX and TX lines reversed.


  22. Jeroen

    10 years ago

    This is sooooo good!
    Very very nice and intuitive library. Absolutely fantastic!


  23. Alf

    10 years ago

    Hello Mikal,
    First of all: I love your TinyGPSPlus library.
    In your documentation there seems to be a bug:
    Serial.println(gps.location.rawLatDegrees()); // Raw latitude in whole degrees
    Serial.println(gps.location.rawLatBillionths()); // … and billionths (i16/u32)
    Serial.println(gps.location.rawLngDegrees()); // Raw longitude in whole degrees
    Serial.println(gps.location.rawLngBillionths()); // … and billionths (i16/u32)

    I think in your kitchen sink demo there are the correct expressions.
    Hope that helps.

    Best regards,
    Alf


  24. Mikal

    10 years ago

    @Alf,

    It does help indeed! Thank you very much…!


  25. David Ball

    10 years ago

    Fantastic, so much faster to code than the tinyGPS library. It’s got pretty much all that’s needed brought to an easy to use set of variables.

    The temptation to use GPS in many more projects might be harder to control!

    Keep up the great work!


  26. David GM4JJJ

    10 years ago

    Many thanks, I used the TinyGPS++ library for my clock project with a UBLOX NEO-6M which has a built in RTC:

    A 4 digit LED clock built with an Arduino Uno and an inexpensive ublox NEO-6M GPS module GY-GPS6MV1 to set the time automatically and keep it in sync.

    The GPS module has a battery to keep its Realtime clock running even if the GPS signal is lost.

    The 4 digit, 7 segment LED display is common cathode, type number 5461AS.

    The clock will automatically change to and from Daylight Saving Time for the timezone chosen.

    The time can also be toggled to and from UTC and local time, by using an infrared remote controller.

    Most components needed are in the Sainsmart UNO R3 Starter Kit: http://www.sainsmart.com/starter-kits/uno-r3-smartkits/sainsmart-uno-r3-starter-kit-with-16-basic-arduino-projects.html

    Full details at:

    http://sourceforge.net/projects/arduinoledgpsclock/


  27. Brian

    10 years ago

    Might be a dumb question, but is there a way to use a function similar to the CustomFields to simply extract an entire valid NMEA sentence, like GPGGA?

    I made my own parser using CustomFields to display lat/long as HH MM.MMMM, but it would be easier to record the NMEA data if I could just grab the entire sentence and send it EEPROM or SD.

    Thanks!


  28. Brian

    10 years ago

    Sorry, the above should read: DD MM.MMMMM ;)


  29. Pedro Cruz

    10 years ago

    Hello

    Mikal

    How can i send tinygps to print out N S E W, to replace the – and +.

    best regards

    Pedro Cruz


  30. Mikal

    10 years ago

    Love it! Thanks for sharing @David GM4JJJ.


  31. Mikal

    10 years ago

    Hi @Pedro Cruz,

    I think I would just write a little code like this:

    if (gps.location.lat() < 0)
    {
      Serial.print(-gps.location.lat(), 6);
      Serial.println("S");
    }
    else
    {
      Serial.print(gps.location.lat(), 6);
      Serial.println("N");
    }
    

  32. Mikal

    10 years ago

    @Brian,

    For the sake of tininess, TinyGPS[++] purposely never stores entire NMEA sentences. However, keep in mind that TinyGPS[++] gets it data from your sketch. You have custody of the data before it is ever processed by the library. This is a frequently asked question, and my answer is the same: If you want to store and record sentences, simply create a ~100-character buffer and store the data into that as it arrives. Then when you get to the carriage return (\r) character, write it to the log and start again.


  33. Seth

    10 years ago

    I have two GPS modules. One is the Venus 6 Breakout from Sparkfun and the other is the UBlox 6M. They both work great when I use an Arduino Uno or Nano, but when I attempt to use it with a Teensy++ 2.0, I get nothing. I have multiples of each microprocessors and tested each one to verify the Teensy board wasn’t bad. I also attempted to use different pins and serial libraries on the Teensy, but that was also a dead end. Does anybody have any tips or ideas to why this is happening? I have to use the Teensy for the amount of memory and pins they have. The GPS modules have been connecting to satellites.


  34. Mikal

    10 years ago

    @Seth,

    Yep. Probably. Unlike Uno and Nano, not all pins on Teensy are compatible with SoftwareSerial. See http://www.pjrc.com/teensy/td_libs_NewSoftSerial.html for details. Otherwise, it might be that you have swapped RX and TX? I can vouch that TinyGPS[++] plus SoftwareSerial works fine on Teensy: I’ve done it many times.


  35. Seth

    10 years ago

    Thanks Mikal! I guess I overlooked that page because it had the old name for the softserial library name. Using the wrong pins turned out to be the case with the Teensy.


  36. Gijs

    10 years ago

    Hi Mikal,

    First off, many thanks for a great library!

    I have programmed a little gps datalogger but have run into something my limited programming knowledge can’t solve… I want my program to see if I have a gps-fix using a custom field:

    void setup(void) {
      ....
      TinyGPSCustom customDataFixed (gps, "GPGGA", 6);
    }
    void loop(void) {
      ....
      String fixedChar = customDataFixed.value();
      if (fixedSymbol == "1" &amp;&amp; gps.sentencesWithFix() &gt; lastSentencesWithFix) {
        fix = true; // we have a fix!
      }
      ...
    }
    

    Is there another way to check if I have a fix without having to convert my TinyGPSCustom field to a string? It adds about 2000 bytes to my sketch…


  37. Mikal

    10 years ago

    Hi Gijs–

    Thank you. Yep, try using either this arcane syntax:

    if (customDataFixed.value()[0] == '1' && gps.sentencesWithFix() > lastSentencesWithFix) {
    ...
    

    or if that seems too crazy, this:

    char *fixedChar = customDataFixed.value();
    if (fixedChar[0] == '1' && gps.sentencesWithFix() > lastSentencesWithFix) {
    ...
    

    Note the single ‘ quotes.


  38. Alan

    10 years ago

    Mikal,

    I’ve found a fairly limiting bug in your library. When a GPS is first powered up, if doesn’t have a fix, it will return NMEA strings with valid sentence makeup, but the values will be NULL.

    E.g.
    $GPGGA,,,,,,, …

    This is a problem is you want to wait until a valid time/date and here’s why.

    the code will watch for the ‘,,’ and doesn’t call the setTime(term) function because with a “,,” string, the term[0] will indeed be null… However, because the checksum at the end of this string full of commas will be valid, when it gets to the end of the string, it will go through the switch statement as if the string were valid and it will call the time and date commit…. which updates all the internals as if an actual date/time were set, which is wasn’t

    So there is no way to wait for a valid date/time as currently implemented. The valid, isupdated, all get updated even tho nothing was set.


  39. Alan

    10 years ago

    BTW, for millis()… I actually use the same as do most STM guys so I didn’t have to change a thing there :)


  40. Alan

    10 years ago

    a little more on the time/date topic above… this might be fixable if you check the value in parsedecimal for a valid string *before the call to atol*, and set valid based upon that instead of the commit

    Alan


  41. Mikal

    10 years ago

    Thanks for that Alan. I’ll enter an an issue on github. I don’t see this problem in my own installations, because the modules I mostly use don’t seem to send empty strings like that. What model GPS are you using?


  42. Alan

    10 years ago

    all of the UBLOX modules send like that when they have no information..

    e.g.$GPGSV,1,1,02,08,,,26,17,,,33*71
    $GPGLL,,,,,022553.00,V,N*49
    $GPRMC,022554.00,V,,,,,,,210414,,,N*7B
    $GPVTG,,,,,,,,,N*30
    $GPGGA,022554.00,,,,,0,00,99.99,,,,,,*62
    $GPGSA,A,1,,,,,,,,,,,,,99.99,99.99,99.99*30
    $GPGSV,1,1,02,08,,,27,17,,,32*71
    $GPGLL,,,,,022554.00,V,N*4E
    $GPRMC,022555.00,V,,,,,,,210414,,,N*7A
    $GPVTG,,,,,,,,,N*30
    $GPGGA,022555.00,,,,,0,00,99.99,,,,,,*63
    $GPGSA,A,1,,,,,,,,,,,,,99.99,99.99,99.99*30
    $GPGSV,1,1,02,08,,,26,17,,,32*70
    $GPGLL,,,,,022555.00,V,N*4F
    $GPRMC,022556.00,V,,,,,,,210414,,,N*79
    $GPVTG,,,,,,,,,N*30


  43. Kyniu

    10 years ago

    I have a problem with UBLOX NEO-6M. Using simple code from http://www.elecrow.com/wiki/index.php?title=GPS_shield I get correct data:

    $GPGGA,160133.00,5054.19463,N,02038.58806,E,2,05,1.80,291.6,M,37.3,M,,0000*59
    $GPGSA,A,3,25,04,29,12,14,,,,,,,,3.02,1.80,2.42*00
    $GPGSV,3,1,12,02,24,130,,04,30,084,19,12,76,294,45,14,34,295,41*78
    $GPGSV,32,1,15,0,$GPRMC,160134.00,A,5054.19478,N,02038.58832,E,0.089,,230414,,,D*7F
    $GPVTG,,T,,M,0.089,N,0.165,K,D*25
    $GPGGA,160134.00,5054.19478,N,02038.58832,E,2,06,1.80,291.1,M,37.3,M,,0000*57
    $GPGSA,A,3,25,24,04,29,12,14,,,,,,,3.02,1.80,2.42*06
    $GPGSV,3,1,12,02,24,130,,04,30,084,19,12,76,294,45,14,34,295,41*78
    $GPGSV,,2,1215,$GPRMC,160135.00,A,5054.19492,N,02038.58848,E,0.646,,230414,,,D*72
    $GPVTG,,T,,M,0.646,N,1.196,K,D*2D

    But with TinyGPS (debug code from above) I have a mess like this:

    $GPGGA,16032.054132N03.83,,,816256M3.M,005
    $GAA32,400,72,21,,17,.6.80
    $PS,,,202,21,43,8,027,9,41,42447
    $PS,,1,71,4,900,1,2,8152,,8234*0
    GGV3322,7233,,3300,32,2,533,7,7
    $PL,0.97,,23.83E102.0AD6
    $GPRMC,160327.00,A,5054.19357,N,02038.58298,E,0.123,,230414,,,D*7E
    $GPVTG,,T,,M,0.123,N,0.228,K,D*2E
    $GPGGA,160327.055.97N008528E2010,9.,,73M,000
    GGAA352,20,72,21,,17,.613*1
    GGV,,20,51960,0032,27,9,,43,9,07
    $PS321,71,41,00,1,2,81522,8234*3
    GGV,,22,72333,3300,32,2,593,7,7
    $GL55.95,,23.88E102.0AD6
    $GPRMC,160328.00,A,5054.19343,N,02038.58272,E,0.271,,230414,,,D*74
    $GPVTG,,T,,M,0.271,N,0.501,K,D*26
    $GPGGA,160328.055.33N008522,,810,9.,,73M00*9
    GGAA322,20,72,24,,17,.613*1
    PS,,,20,52,80,0031,26274,43,9,07
    GGV321,75061,00,1,2,85,22,8234*1
    GS,,,22,71,23,3301,32,33,93,7,7
    $PL55.94,,28522E102.0AD9

    Please help !!! What am I doing wrong?


  44. Mikal

    10 years ago

    @Kyniu,

    It looks like you are dropping characters. If you are using soft serial, check the overflow() flag to verify. If you are dropping, it’s because your processing loop is taking too long. Often this is simply because you are writing data to the serial console at too low a baud rate.


  45. Nancy

    10 years ago

    Is there any capability, or are you planning to add, the ability to upload a custom control string to the GPS? I’m using a SparkFun GPS Shield with an EM-406 engine and I’d like to change its baud rate to 9600 instead of the default 4800.
    A mirror to the “Custom NMEA Sentence Extraction” would be REALLY nice.


  46. Mikal

    10 years ago

    @Nancy,

    I doubt if I will be adding this feature any time soon. TinyGPS++ tries to be a device-agnostic parser. Remember, TinyGPS++ never takes control of the serial stream. At any time you can simply

    ss.print("<some device-specific string>");
    

    to the device.


  47. Kyniu

    10 years ago

    I know this is not a problem with TinyGPS library but have no idea where to ask for help. I have ublox NEO-6M receiver connected to Arduino Leonardo. And it looks that I overflow the buffer all the time. I wrote simple test code:

    #include
    #include

    SoftwareSerial SoftSerial(10, 11);

    TinyGPSPlus gps;

    void setup()
    {
    SoftSerial.begin(9600); // the SoftSerial baud rate
    Serial.begin(115200); // the Serial port of Arduino baud rate.
    }

    void loop()
    {
    if (SoftSerial.available() > 0)
    {
    gps.encode(SoftSerial.read());
    Serial.println(SoftSerial.overflow() ? “YES!” : “No”);
    }
    }

    And the result looks like this:

    (…)
    No
    No
    No
    No
    No
    YES!
    YES!
    YES!
    YES!
    YES!
    YES!
    YES!
    YES!
    (…)
    No
    No
    No
    No
    No
    YES!
    YES!
    YES!
    YES!
    YES!
    YES!
    YES!
    YES!
    (…)

    What is happening? Is NEO-6M realy sending too much data for Leonardo to handle it? According to NEO-6M datasheet I can not slow it down more then 9600. Would be very gratefull for any help.


  48. Alan

    10 years ago

    SoftSerial is really a poor implementation to deal with most anything serial related. All the logic handling serial timing, bit sending/receiving etc are all done in software and if *anything* is happening during that (other interrupts from timer, pwm, etc) it’s going to cause issues even at 9600 baud. If it were me, I’d look at some other way to connect to the gps such that you are using hardware based serial. You’ll just continue to have problems trying to use softserial.


  49. Alan

    10 years ago

    Ya know, I’ll try and pull you together a pull request. If interested I’ve added support for the polled PUBX protocol, it’s a one line protocol similar to NMEA that UBlox uses, you poll it with a command and it responds with ascii. Biggest problem is that I’ve modified the library to also support the UBX binary protocol as well… it’s inline so that either can work somewhat at the same time.

    Alan

1 Trackbacks For This Post
  1. Antenna tracker, first steps | kolin's

    […] or none, I made simple arduino program for parsing NMEA crap and encoding it in LTM packets. I used TinyGPS++ library for parsing NMEA and few lines from TauLabs […]

Leave a Reply