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


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.


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)

Then query it for the desired information:

if (gps.altitude.isUpdated())

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.


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)

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.


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?

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=");

// 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 ");

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 =
    EIFFEL_TOWER_LNG) / 1000.0;
double courseTo =
Serial.print("Distance (km) to Eiffel Tower: ");
Serial.print("Course to Eiffel Tower: ");
Serial.print("Human directions: ");

Library Version

You can retrieve the version of the TinyGPS++ library by calling the static member 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.


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
339 Responses → “TinyGPS++”

  1. Brian

    1 year ago

    Silly question perhaps, but I decided to try TinyGPSPlus with a basic Arduino with 328P versus the Mega128 and custom ATmega128A boards I’ve been successfully using, but does TinyGPSPlus allow the use of the 328P hardware serial?

    The GPS data is mirrored to the serial monitor correctly, but the TinyGPS object does not seem to do anything!

    Oddly enough, even with a Mega128, if you feed it using Serial1 (second hardware serial), it works fine, but move it to Serial0 (first serial) you get nothing!

    Any ideas?

  2. Brian

    1 year ago

    Never mind the last question! ;) Stupid pinout diagram for the breakout shield has the RX/TX lines reversed! Doh!

    In any case, before figuring out the RX/TX swap, I optimized the code seeing how having 5(!) bytes of RAM left over is probably not a good thing in an ATmega328! It now has 321 bytes free, and works fine.

  3. MF

    3 months ago

    // Hello, Good day. Thank you so much for sharing this GPS module library.

    // my project aims to warn the driver with a voice message when the speed
    // reached 80 km/hr, and also sends information like latitude and longitude via
    // text message.

    // Initially, I did not put the voice alert function, just the text message
    // function. There was no problem with the GPS module getting a fix information
    // when it was connected to the Arduino UNO and GSM module, I did not use a
    // library for the GSM module. It was working fine by then. The values from the
    // GPS module are updated.

    // But when I wired the mp3 player module and included the DFPlayer_Mini_Mp3.h
    // library and its commands to my sketch, the voice alert was fine, the GSM
    // module sends a message to my phone but is not updated, just zero values from
    // the GPS module. ex. LAT: 000000,
    // LONG: 000000

  4. Paul Rowntree

    3 months ago

    Hi! Great package, it simplified my program quite a bit! Thank you very much!
    I am new to Arduino-land, and c-programming. Why do your examples use

    TinyGPSPlus.courseTo(… // from examples on this web page
    TinyGPSPlus::courseTo(… // from some of the Example sketches

    instead of simply

    gps.courseTo( … // from my program, seems to work fine

  5. surajit paul

    3 months ago

    hi, I’m using tinygpsplus library.I’m making a project “gps controlled rc car ” using ublox neo 6m gps sensor and hmc5883l compass. my problem is that when I connect the arduino with computer everything works fine and gets gps coordinate and compass heading bt when I disconnected usb and connect with 9v battery to arduino, the car does move. rx signal receiving and tx not indicating.when I connect with usb to arduino, the car moving. I’m also using hmc5883l library. and not using this function “while(!serial). in the loop I’m using “while(ss.available ()>o)”. what’s happening please help me

  6. Ben Mc

    3 months ago

    Hi Mikal,

    Thanks for your code. I have a question in regards to gps data sampling rate. The code outputs the sentences at 1 s increments by default, is it possible to access the data faster? I would like to get altitude data off my gps module at 10-100 hz.

    Thx for any help

  7. Mikal

    2 months ago

    @Ben Mc:

    The rate at which samples are delivered depends entirely on the hardware you choose. The EM-406a and EM-506 that I often use only deliver in 1Hz samples; there is no way to bump up the rate. Other devices can be configured to deliver samples at 10Hz, but this isn’t something that can be done in TinyGPS++.

  8. Mikal

    2 months ago

    @Paul Rowntree,

    When I’m using C++ “static” member functions I like to use the ClassName::MemberName() syntax instead of Object.MemberName() to illustrate that the member function is independent of any particular object.

  9. Mikal

    2 months ago

    @MF: You should probably switch to a Teensy or Mega or something that provides more than 1 Hardware Serial port.

  10. DM Rick

    1 month ago

    Thank you so much sir. I wasn’t sure from the remarks was if you were getting the bearing and distance to London from the GPS unit by sending it a waypoint or if you were doing the calculation in TinyGPS++. My GPS unit (NEO-6M) doesn’t seem to take waypoints or produce RMB so I a super glad to find your TinyGPS++ does that work. What a find. You really have saved me as little sailboat and I were to leave a month ago but wanted to work out at least an auto steering system. Now I will have a much better system where I changed London to WayPoint and feed Lat/Lon to where I want to go. The Cross Track Error I can work out.
    This is amazing. Thank you.

  11. Rick

    1 month ago

    The more I use it the more I like it. Only thing is I still don’t fully understand it and just modified the example to get the info I needed out of the NEO-6M. It seems to run thru the void loop just once per second. I kicked up the data transfer rate of NEO and Uno (Softwareserial) to 57,600 and dropped out all but GGA and RMC from NEO but still loops about once per second. My fix is just adding another Uno for keypad and rudder control. Solves pin count problem too. I should be able to transfer the data I2C. I have plenty of boards but since I also name them (Adam, Eve, Max) I’m running out of names :)
    Thanks for writing this gem

  12. Jeferson

    1 month ago

    What type of licence tinygpsplus is under? Can I use on my drones and wings?

  13. Michele

    4 weeks ago

    I’m facing a very very strange problem…
    All the TinyGPSPlus examples works ok…
    A sketch of mine that does not use TinyGPSPlus works ok…

    If in my sketch i simply add

    TinyGPSPlus gps;

    The sketch does not work anymore (cannot find a way to debug this problem).

    My sketch is using the library JTEncode and the function that “hang” is jt65_encode of that library.

    I’ve no idea of what the statement “TinyGPSPlus gps;” does…but if i comment it, everything works ok.

    Any idea?

    PS: I’ve written to the developer of JTEncode, i’m waiting for an answer from him too.

    PLEASE, an help would be really appreciated.


  14. Mikal

    4 weeks ago

    @Michele, if your program breaks when you added only the definition of the gps variable, then my guess is that you have run out of some resource (memory or flash space).

  15. Mikal

    4 weeks ago

    No problem @Jeferson. It’s licensed under LGPL. Let us know how it works out.

  16. Mikal

    4 weeks ago

    @Rick, I think one problem might be that SoftwareSerial can get unreliable at speeds greater than 19.2 or 38.4K.

    I think the NEO-6M refreshes at 5Hz. TinyGPS++ itself has no internal limit beyond just the processing power of the underlying CPU. Subject to that it will process characters as fast as the GPS module generates them.

  17. JP_Austin

    3 weeks ago

    Mikal, great library. I have been using it in an ESP8266 project and experiencing some issues with the distanceBetween function. I have essentially the same LAT and LON values defined as my HOME location and when I exercise the function to determine how far from home it reports an error of about 10KM. Am I doping something odd or is it something with the ESP8266 and how it compiles the code?

    Only thing I could find remotely close to the error is from this Particle post. Similar issue was being reported.


    I use the function like this:

    unsigned long Distance_To_Home = (unsigned long)TinyGPSPlus::distanceBetween(gps.location.lat(),gps.location.lng(),Home_LAT, Home_LNG);
    display.print(“KM to Home: “); // Have TinyGPS Calculate distance to home and display it

  18. Mikal

    3 weeks ago

    Hi @JP_Austin.

    I don’t think you’re experiencing the same thing reported on the particle.io site.

    You realize, right, that distanceBetween() returns distance in meters, not in kilometers? Assuming so, can you give me some more detail? What number were you expecting and what number did you get? It would be useful if you could give me (approximate) values for bot lat/long pairs.

  19. JP_Austin

    3 weeks ago

    Face palm –> Meters and not KM! OK now I do feel stupid. I had loaded an example provided and it was reporting the value as KM. I didn’t scrub the documentation well enough to realize your library was reporting the distance in meters. Lesson learned – don’t pick up examples and report issues unless you really know the said example is clean.

  20. Rick

    2 weeks ago

    Mikal, Thanks. You are exactly correct. I dropped GPS transfer speed back down in steps from 57600 to 19200 and it became stable again. Of course being as I am I then dropped it to 9600 just to be sure. Still plenty fast enough at 1 Hz samples to drive a sailboat :)

    I’m still a little confused about which is newer, TinyGPS++ or TinyGPS13. I was having trouble with the count of satellites on I2C driven 20×4 LCD so rewrote it all using v.13 library and working ok so far.


    1 week ago


    TinyGPS++ is great in most of my Arduino sketches. Thanks for writing it.

    However, I am trying to run your sketch “SatelliteTracker.ino” which I got from GitHub. I’m using an Adafruit GPS Logger shield with an Arduino UNO. I changed the RXPin and TXPin numbers to 8 and 7, respectively, and I changed the GPSBaud statement to “static const uint32_t GPSBaud = 9600;” The sketch compiles OK and runs down through the Serial.println statements in the void setup. I don’t get any output after that. Do you have any suggestions? Thanks.


  22. Herve

    1 week ago

    I’m very please using TinyGPS++.
    Just one thing, I want to update the arduino time ONLY if date and time are valid (for datalogger, so I block my sketch waiting for these conditions to be valid) …. but that doesn’t work as expected.

    I’m using: if (gps.date.isValid() && gps.time.isValid()) ….

    even if the GPS replies a “false date” (2000/01/01) TinyGPS++ consider them as valid.

    Is there any solution to change that behaviour ?

    Many thanks in advance
    best regards … and thanks again for the good work !

  23. Mikal

    6 days ago


    Yes, it’s a little confusing, but the “isValid()” method on date and time is simply the library reporting that at least one NMEA stream that could contain a date or time has been parsed. Would you suggest a different algorithm? I’ll think about this.


  24. Mikal

    6 days ago

    @Jim–It’s easy to get the wiring backwards. Usually (but not always!) you connect TX to RX and RX to TX.

15 Trackbacks For This Post
  1. TinyGPS++ to the Rescue | Stainless Steelhead

    [...] to the brains behind Arduiniana, Mikal Hart, Poolbot has moved to the brand-new GPS library set, TinyGPS++.  This saved enormous time in developing custom code to process and check the validity of NMEA [...]

  2. 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 [...]

  3. GPS Ublox Neo-6M cu Arduino Uno | ArduHobby

    [...] Descarcati biblioteca tinyGPS sau tinyGPS++. [...]

  4. GPS-Logger | Pascal's Königreich

    [...] Card Breakout Board gibt’s bei Adafruit, um mit dem GPS Modul zu sprechen wurde die Library TinyGPS++ [...]

  5. GPS Distance Calculator (for golf) -Use Arduino for Projects

    [...] Tiny GPS++ [...]

  6. Arduino GPS with OLED Display | Home of Benty

    [...] OLED from Adafruit. It’s still a work in progress just squishing together code from the TinyGPS++ library and using the Adafruit GFX [...]

  7. SpainLabs - Mantener tus proyectos en hora

    [...] Con Arduino puedes usar la librería tyniGPS++. [...]

  8. Prototype 1 – GPS Module | A Mean Center

    [...] something useful with it. This isn’t due to any competence on my part, but because of  the TinyGPS++ library by Mikal Hart which is just amazing. There are many examples included with the library, so it is [...]

  9. Unexpected behavior of sprintf with i32/u32 | CL-UAT

    [...] trying to build a string of characters from several elements given by the TinyGPS++ library with the use of [...]

  10. Connecting u-blox NEO-6M GPS to Arduino | Big Dan the Blogging Man

    [...] http://arduiniana.org/libraries/tinygpsplus/ [...]

  11. 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 [...]

  12. با برد آردوینو و شیلد GPRS دستگاه ردیاب کوچک و کارآمد بسازید | رایانش نیوز

    [...] این کتابخانه را برای استفاده از برد GPS دانلود کنید. سپس کدهای [...]

  13. Shield GPS Ublox NEO-6M – Programación con Arduino MEGA 2560 – Tecno-fly C.A

    [...] http://arduiniana.org/libraries/tinygpsplus/ [...]

  14. Leyendo datos del GPS – OCEANO ABIERTO

    [...] Arduino que nos permite convertir esas cadenas de caracteres en valores fácilmente interpretables: TinyGPSplus. Tendremos que descargar el archivo .zip de la última versión e instalarlo manualmente en nuestro [...]

  15. Lightweight Module for Collecting Stratospheric Microbes | HENRY-1 HAB MISSION

    [...] RBBB was programmed with Arduino’s IDE and includes both the TinyGPS++ and Arduino Servo libraries. The TinyGPS library is very effective at parsing NMEA GPS data [...]

Leave a Reply