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. David

    9 years ago

    I am trying out the new library TinyGPS++ for a telemetry project, and I have begun with “BasicExample.” I wanted to see what would trigger errors, so tried changing one character at a time in various gpsStream fields, but I never got the “INVALID” msg; the only effect was that the string wouldn’t print. I realize a single character change would generate a checksum error, but that isn’t an error case in this demo… so what would be a printable string but an INVALID time for example?

    Also, is there a configuration option to parse the msg but ignore the CRC?


  2. Beat

    9 years ago

    Hi Mikal,
    I am not sure, but the validity of custom sentence is always true?
    $IIMWV,338.0,R,044.0,M,V*21 flags void.

    TinyGPSCustom wind_dir(gps, “IIMWV”, 1);
    TinyGPSCustom wind_speed(gps, “IIMWV”, 3);

    (wind_speed.isValid()) is always ok.
    Now i handle it as custom field itself.
    TinyGPSCustom wind_valid(gps, “IIMWV”, 5);


  3. Beat

    9 years ago

    Upps, found it in the for me not relevant “Establishing a fix” Section (Because i use no GPS)

    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).

    But Maybe this could be configurable too..?


  4. Gilles

    9 years ago

    Ni Mikal,
    I need a clarification :
    Arduino Uno doubles and/or floats have an accuracy of 6 or 7 digits and many people say that this is generating a large error.

    Do your library is doing something to alleviate the problem ?

    Thanks a lot for sharing your knowledge on this !


  5. TommiP

    9 years ago

    Hi all

    Does this work with 1.0.6 ?
    I’ve tried quite many times to install library to the Arduino libray folder and treid to copy .cpp and .h -files quity many place but it keep saying that “BasicExample:26: error: ‘TinyGPSPlus’ has not been declared”

    BR
    TommiP


  6. Pete B

    9 years ago

    Question. What’s the best way to determine that GPS has a fix with this code? I like the interface better with this, but the Adafruit GPS includes a fix variable that can be checked which allows me to loop for a while until a fix is obtained. Is there a good mechanism to understand when a fix is obtained?

    Thanks, this is really great stuff.


  7. flydr2

    9 years ago

    Thanks for all the hard work… I’ve managed to develop an autopilot for my experimental aircraft (Thorp T-18) using your library.

    I’m using an arduino due and it controls my trim tabs.. It works great but without your lib I would not have had it perfected to full navigation.. It would have followed only a compass.

    Now it take gps data from hard wired neo 6m and my Android tablet/cell phone via bluetooth as well Lowrance GPS…

    Thanks again!


  8. Costin

    9 years ago

    Hi,Mikal..
    I’m using an ATMEGA board with the gps on Serial1. I’m updating once a week a DS3231 clock, but there’s a strange problem. When the update occurs, the date and time transferred in the DS3231 are the ones from the last reset of the entire board, instead the actual ones.I’m using the isValid query before writing the DS3231.How can I flush the buffer after a reading so to get reals date and time or which function to use from GPS++ ?
    Cheers,
    Costin


  9. Jay Be

    9 years ago

    hi mikal,
    thanks for your great library!
    i’m using it with an u-blox neo-6m module and it works, BUT
    i dont get the GPGGA information like sats, hdop and altitude…

    if i’m using a terminal program with the gps module directly, i get all information from $GPGSV, $GPGLL, $GPRMC, $GPVTG, %GPGGA and $GPGSA.

    my baudrate is 9600. any suggestions?
    thanks!


  10. Mikal

    9 years ago

    @David–

    There isn’t any code that prints “INVALID” in the BasicExample. TinyGPSPlus::encode() returns true when it successfully parses a sentence with the correct checksum.

    No, there isn’t any provision for ignoring the checksum. Can you think of a time when it might be useful? Is there ever a scenario where you could get a bad checksum but still trust that the data is correct?


  11. Mikal

    9 years ago

    @Gilles, the accuracy of the built-in data types float and double is a function of the processor. There’s nothing that SW can do to alleviate that I’m afraid. If you need higher precision, you might check out processors which use 64-bit doubles instead of 32, like the Due…?


  12. Mikal

    9 years ago

    @TommiP,

    Yes, you should copy the files to a new folder called TinyGPSPlus in the Arduino/libraries folder. Then make sure you exit and re-enter the Arduino IDE before running the examples.


  13. Mikal

    9 years ago

    @Pete B, thanks for the nice words. I believe the Adafruit library uses the fact that the Adafruit Ultimate GPS module (great module by the way!) has an asynchronous “FIX” output. You could simply watch that signal. I don’t want TinyGPS++ to depend on a feature that isn’t present in all GPS devices, but there’s no reason you can watch it asynchronously.


  14. Mikal

    9 years ago

    @flydr2, Thanks! Very cool.


  15. Mikal

    9 years ago

    @Costin, a trick to reset the GPS object is:

    TinyGPSPlus gps;
    
    ...
    
    {
    ...
       gps = TinyGPSPlus(); // reset with new object.
    ...
    }
    

  16. Mikal

    9 years ago

    @Jay Be, are you running the examples? What is the refresh rate of the GPS? 10Hz?


  17. Jay Be

    9 years ago

    yes, i’m running the “FullExample” and just changed this two lines:

    static const int RXPin = 10, TXPin = 9;
    static const uint32_t GPSBaud = 9600;

    refresh rate is 1hz.
    i also get checksum errors between 1 and 6…
    thanks!


  18. Makis

    9 years ago

    Hi is it posible to use the GPS++ To Serial.println only the $GPRMC sentence? in raw format as it came from GPS.

    Thanks in advance!


  19. Diego

    9 years ago

    How can I can do to get into a string frame the entire $ GPRMC frame , ie complete. I do not want to get only one field , I want to get the full frame and store it in a string variable . Thank you very much .


  20. Mikal

    9 years ago

    @Makis, no the library (purposefully) does not store complete sentences. But you know, you are completely in control of the byte stream before you send it to TinyGPS++’s encode() method. Why not simply look for that yourself?


  21. Mikal

    9 years ago

    @Diego, since you control the stream of data before it gets sent to TinyGPS++, just capture all the characters up until the newline terminator, beginning each time you see the characters “$GPRMC”.


  22. Brian

    9 years ago

    Hi!

    The isValid() test seems a little odd if all the NMEA strings are checksum-verified. Does isValid() check for usable data versus empty fields?

    Also, I need to save some of the NMEA data to an SD card, are the currently validated NMEA strings stored anywhere so I don’t need to recreate them from the object data?


  23. Ron Koval

    9 years ago

    I have run your example program which extracts R and L from the $GPRMB sentence and it works just fine. I have tried to work with conditional statements with steerDirection.value() without any success. I have added a few lines to your example and tried to assign steerDirection.value() to an integer variable, it compiles fine, but all I get is R575 or L575 for the program below. Can you direct me as how to get the steerDirection.value to work with other functions than Serial.print ? Thanks.

    Here is the section of code with // added for the 3 lines I have added

    void loop()
    {
    int dir; // added declaration of integer called dir
    {
    Serial.print(steerDirection.value());
    dir = int(steerDirection.value()); // added
    Serial.print(dir); // added, prints 575 no matter if L or R
    Serial.println();
    }

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


  24. Mikal

    9 years ago

    @Brian, it possibly could have been better named, but isValid simply means that at least one sentence has set the value correctly. Initially all values are NOT valid, but as soon as the first legal sentence sets it, that value is valid forever. It does not currently sense empty fields.

    It’s one of TinyGPS++’s design goals to be very stingy with memory consumption, and accordingly, complete NMEA sentences are never stored. If you want to store complete sentences you will have to do it yourself.


  25. Mikal

    9 years ago

    @Ron, the line beginning “dir = …” converts a character pointer into an int. That’s not what you want for dir. Either directly use the string

    Serial.println(steerDirection.value());
    

    or calculate dir correctly

    dir = strcmp(steerDirection.value(), "L") == 0 ? -1 : 1; // -1 for L, 1 for R
    

  26. Brian

    9 years ago

    Good to know that the “validated” NMEA strings are not available, but for others to note, it is quite easy to simply re-create the strings by using custom objects.

    You probably would not want to re-create a lot of them, but the basic GPRMC and GPGGA (Google Earth basics) share a lot of the same data, and could be easily re-assembled from custom strings, then have a valid checksum calculated and appended to the end.

    I’m in the midst of testing, but I have my doubts that the isUpdated() function works properly on custom objects. It seems to be firing about 10x as often as possible (1Hz uBlox update rate). More to follow…


  27. Brian

    9 years ago

    FYI, HDOP is Horizontal -Dilution- of Position, you use “diminution” which is the French equivalent, and not really correct.


  28. Brian

    9 years ago

    Solved the “issue” of rapid updates, my fault! ;)

    I’ve got the “re-assembly” of a GPRMC string going fine, with a recalculated checksum added to the end (some unused parameters are dummy data, so it will be different), but I’ve run into an issue in GPGGA where a custom object can be a variable length, like altitude.

    I use this technique to utilize the custom object (display on LCD, write to SD, etc): (Not in the order below. just the concept, which works fine…)

    – TinyGPSCustom GGAalt(gps, “GPGGA”, 9);
    – strncpy(GPSaltArrayText,GGAalt.value(),4);

    The issue is with altitude, I can’t predict how many bytes the custom object will contain, and something like: arraySize = sizeof(GGAalt); seems to crash the AVR

    1) Is there a better way to move the contents of a custom object into a char array?

    2) Is there some way to determine how many bytes a custom object contains?

    Thanks!


  29. Mikal

    9 years ago

    @Brian, are you familiar with the strcpy() function? The value() method of TinyGPSCustom returns a true C-style string, so you should be able to simply:

    strcpy(GPSaltArrayText, GGAalt.value());
    

    Alternatively, if you want to make sure it fits before you copy:

    int len = strlen(GGAalt.value());
    if (len < sizeof(GPSaltArrayText))
       strcpy(GPSaltArrayText, GGAalt.value());
    

  30. Brian

    9 years ago

    Still a little fuzzy on “isValid()”…

    This is a completely “valid” NMEA string:

    $GPGGA,033219.00,,,,,0,00,99.99,,,,,,*6C

    It’s essentially what you get before the GPS has a fix, but is tracking satellites (thus the time is correct, valid, and incrementing; therefore “updating”).

    Would TinyGPS++ consider the above sentence “valid” and “updating”? If so, I need to do a lot more field validations!

    Thanks.


  31. Daniel C

    9 years ago

    Mikal,

    Great Library, thanks for the great work. I have been using it with Hardware Serial and a Mega, but I have found that the hardware serial only works with the older versions of the Arduino IDE, and now I need to be able to use the later version. I have the GPS chip (Adafruit) hooked up properly and I launch the 1.0.5 IDE and use your DeviceExample script, replacing the software serial with hardware serial, change BAUS to 9600 and it works great. I then close that and open the 1.6.0 IDE and and do the same thing and get “No GPS data received: check wiring”. Any thoughts on why I might be seeing this?

    Thanks.


  32. Ronaldo

    9 years ago

    Dear Mikal,
    How do I record only $GPRMC on the memory card?


  33. Shelley

    9 years ago

    I have gps and openlog attached to the hardware serial pins and 16×2 lcd on other pins. Everything is running at baud rate of 57600 (I need a 5 Hz updated speed readings). Data is coming through ok but there is duplicate data showing up…for every 1/5 sec I get the same reading 20x’s. Is this a baud rate issue?


  34. W1BMW

    9 years ago

    Thanks for all your hard work on the libraries offered here! I’m using TinyGPS++ and an Argent Data radio shield for an APRS tracker. Your library made coding a snap!

    I had some problems initially that turned out to be a baud rate issue. The default value of 4800 baud must be changed to 9600 for the Adafruit Ultimate GPS Breakout Board, but the code worked right out of the box!

    73 de W1BMW


  35. Georges Payne

    9 years ago

    Hello Mikal,

    Noob here, in dire need of help!

    I have a Arduino Uno rev.3 and a Garmin 72 GPS unit. I familiarized myself with the Arduino environment by playing around with a few examples and by writing my own (simple) code also. Now I am trying to run the TinyGPSPlus DeviceExample code in order to grab data from the GPS. I have connected the Tx line from the GPS to pin #3 on the Arduino and the ground wire from the GPS to the GND pin next to pin 13. The GPS is correctly setup and using a terminal program on my PC, I can read the sentences just fine at 4800 baud.

    With the GPS unit connected to the Arduino, and without any modifications in the code, The program seems to hang after the credits in the beginning, right after “By Mikal Hart”. It does not say “No GPS, check wiring…” but it doesn’t proceed to the DisplayInfo loop either, because it doesn’t print “Location: “.

    The while loop doesn’t seem to be working, because if I disconnect the GPS it doesn’t go to “No GPS”.

    If I reset the Arduino with the GPS disconnected, it says “No GPS…” but if I reconnect the GPS without resetting the Arduino, nothing happens.

    I tried the debugging lines of code you provided in this page and I can see waves after waves of gibberish characters on the serial monitor.

    I also tried the checksum line, but wasn’t able to get any results with it.

    I have banged my head against this four nights in a row, but I am stuck. I live in a somewhat remote location, and I tried to see if there are any robotics clubs around, but couldn’t find anything.

    So I’m desperate. Any help, any help at all, would be greatly appreciated.

    Cheers!
    Georges


  36. Georges Payne

    9 years ago

    Hello Mikal,

    Never mind. A noob mistake, the Garmin GPS 72 output is Serial RS232, and the Arduino serial is TTL. I bought a 7$ RS232-TTL converter, and now I can read the phrases all right.

    Thanks anyway, your page was a tremendous help.

    Cheers!
    Georges


  37. Mikal

    9 years ago

    @Daniel C, are you sure the program you’re compiling is identical when you make the transition to 1.6.0? And all the libraries?


  38. Mikal

    9 years ago

    @Ronaldo, I think I would do that outside of TinyGPS. You are capturing the raw stream: just write what you need to SD.


  39. Mikal

    9 years ago

    @Shelley, depending on which sample app you’re running, it may print data every time a new sentence is parsed. But not every sentence brings fresh instances of the data you’re looking for. It’s not an error really, just a quirk. You could modify the sample to print only when the datum you seek actually changes.


  40. Mikal

    9 years ago

    @W1BMW, hey, thanks!


  41. Lespaul

    9 years ago

    Hello Mikal (Sorry, not good at English)
    I have used gr83 mudule gps with mega1280.
    I have taken from gr83 NEMA codes to enter the gps stream.

    const char * gpsStream =
      “$ GPRMC, 000118.050, V, 1335.5938, N, 10044.9498, E ,,, 160406 ,,, N * 70 \ r \ n”.
      “$ GPGGA, 000118.050,1335.5938, N, 10044.9498, E, 0,00 ,, – 25.9, M, -27.0, M ,, 0000 * 4B \ r \ n”;

    But the result is

    BasicExample.ino
    Basic demonstration of TinyGPS ++ (no device needed).
    Testing TinyGPS ++ library v. 0.92.
    by Mikal Hart

    Location: INVALID Date / Time: 4/16/2006 00: 01: 18.05.
    Location: INVALID Date / Time: 4/16/2006 00: 01: 18.05.

    Done.

    Help me please.


  42. KP

    9 years ago

    I want to just take some time to thank you for the great library! I’ve been using this library to parse non standard (custom) NMEA data from a weather station sensor (also includes a GPS in it).


  43. kostas stefani

    9 years ago

    Hello, i want to build a project that will have an arduino gps module on it, propably a shield that would also log the gps data. I would like to ask about the accuracy of the gps,is it a matter of hardware or software?? I mean if i use this library with a gps module that says it has an accuracy of 3m or an accuracy of 10m, will i get a much better accuracy with this library and a help of a magnetometer?


  44. Mikal

    9 years ago

    @KP, hey, thanks for that! So glad it’s useful for you.


  45. Mikal

    9 years ago

    Hi @Lespaul,

    The problem is that your two NMEA sentences indicate that you don’t have a good fix.

    The ‘V’ in field 3 of $GPRMC means “invalid”.
    The ‘0’ in field 7 of $GPGGA means “no fix”.

    In this case TinyGPS++ discards all position, speed, course, or altitude data.


  46. Mikal

    9 years ago

    @kostas stefani,

    The software neither adds or subtracts accuracy. It reports exactly what the GPS module is reporting, only in a more convenient form.


  47. KP

    9 years ago

    Mikal,

    Is there already a built in function to get gps data (lat and lng) with 6 decimal as unsigned number? such as 90.123111 to 90123111?

    Thanks.


  48. Mikal

    9 years ago

    @KP, no, but you could synthesize it pretty closely with

    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)

    This won’t be exactly correct, because small billionths” values won’t be left padded with zeros, but you could create this pretty easily.


  49. KP

    9 years ago

    Hey Mikal,

    Thanks for the information.

    This is what I ended up doing.

    latitudeUINT = (gps.location.rawLat().deg * pow(10, 6)) + (round((gps.location.rawLat().billionths) / 1000.000)) ; // combine degree and decimal
    longitudeUINT = (gps.location.rawLng().deg * pow(10, 6)) + (round((gps.location.rawLng().billionths) / 1000.000));

1 Trackbacks For This Post
  1. LatLong to XY | Rocket Project

    […] the same. latlon2xy is the doc with the Arduino code. Since I last looked at GPS, Mikal Hart has an updated GPS library that computes distanceBetween() and courseTo(). It might be worth pursuing. Share […]

Leave a Reply