TinyGPS

A Compact Arduino GPS/NMEA Parser

Note: TinyGPS 12 is now available.  TinyGPS 12 provides several new features:

  1. satellites() – Number of satellites counter from $GPRMC
  2. hdop() – Horizontal Dilution of Precision from $GPRMC — the smaller this value is the more confidence you have in the accuracy of the location reading.
  3. course_to() – another Maarten Lamers’ borrowing that complements his distance_to
  4. cardinal() – a nice little static function by Matt Monson that converts a course to a compass direction like “SSE”.

Note: TinyGPS 11 is now Arduino 1.0 compatible.

TinyGPS is designed to provide most of the NMEA GPS functionality I imagine an Arduino user would want – position, date, time, altitude, speed and course – without the large size that seems to accompany similar bodies of code.  To keep resource consumption low, the library avoids any floating point dependency and ignores all but a few key GPS fields.

Usage

To use, simply create an instance of an object like this:

#include "TinyGPS.h"
TinyGPS gps;

Feed the object serial NMEA data one character at a time using the encode() method. (TinyGPS does not handle retrieving serial data from a GPS unit.) When encode() returns “true”, a valid sentence has just changed the TinyGPS object’s internal state. For example:

#define RXPIN 3
#define TXPIN 2
SoftwareSerial nss(RXPIN, TXPIN);
void loop()
{
  while (nss.available())
  {
    int c = nss.read();
    if (gps.encode(c))
    {
      // process new gps info here
    }
  }
}

You can then query the object to get various tidbits of data. To test whether the data returned is stale, examine the (optional) parameter “fix_age” which returns the number of milliseconds since the data was encoded.

long lat, lon;
unsigned long fix_age, time, date, speed, course;
unsigned long chars;
unsigned short sentences, failed_checksum;

// retrieves +/- lat/long in 100000ths of a degree
gps.get_position(&lat, &lon, &fix_age);

// time in hhmmsscc, date in ddmmyy
gps.get_datetime(&date, &time, &fix_age);

// returns speed in 100ths of a knot
speed = gps.speed();

// course in 100ths of a degree
course = gps.course();

Statistics

The stats method provides a clue whether you are getting good data or not. It provides statistics that help with troubleshooting.

// statistics
gps.stats(&chars, &sentences, &failed_checksum);
  • chars
    - the number of characters fed to the object
  • sentences
    - the number of valid $GPGGA and $GPRMC sentences processed
  • failed_checksum
    - the number of sentences that failed the checksum test

Integral values

Values returned by the core TinyGPS methods are integral. Angular latitude and longitude measurements, for example, are provided in units of 10-5 degrees, so instead of 90°30’00″, get_position() returns a longitude value of 9050000, or 90.5 degrees. But…

Using Floating Point

…for applications which are not resource constrained, it may be more convenient to use floating-point numbers. For these, TinyGPS offers several inline functions that return more easily-managed data. Don’t use these unless you can afford to link the floating-point libraries. Doing so may add 2000 or more bytes to the size of your application.

float flat, flon;

// returns +/- latitude/longitude in degrees
gps.f_get_position(&flat, &flon, &fix_age);
float falt = gps.f_altitude(); // +/- altitude in meters
float fc = gps.f_course(); // course in degrees
float fk = gps.f_speed_knots(); // speed in knots
float fmph = gps.f_speed_mph(); // speed in miles/hr
float fmps = gps.f_speed_mps(); // speed in m/sec
float fkmph = gps.f_speed_kmph(); // speed in km/hr

Date/time cracking

For more convenient access to date/time use this:

int year;
byte month, day, hour, minutes, second, hundredths;
unsigned long fix_age;

gps.crack_datetime(&year, &month, &day,
  &hour, &minute, &second, &hundredths, &fix_age);

Establishing a fix

TinyGPS objects depend on an external source, i.e. its host program, to feed valid and up-to-date NMEA GPS data. This is the only way to make sure that TinyGPS’s notion of the “fix” is current. Three things must happen to get valid position and time/date:

  1. You must feed the object serial NMEA data.
  2. The NMEA sentences must pass the checksum test.
  3. The NMEA sentences must report valid data. 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 those sentences are discarded.

To test whether the TinyGPS object contains valid fix data, pass the address of an unsigned long variable for the “fix_age” parameter in the methods that support it. If the returned value is TinyGPS::GPS_INVALID_AGE, then you know the object has never received a valid fix. If not, then fix_age is the number of milliseconds since the last valid fix. If you are “feeding” the object regularly, fix_age should probably never get much over 1000. If fix_age starts getting large, that may be a sign that you once had a fix, but have lost it.

float flat, flon; unsigned long fix_age; // returns +- latitude/longitude in degrees gps.f_get_position(&flat, &flon, &fix_age); if (fix_age == TinyGPS::GPS_INVALID_AGE) Serial.println("No fix detected"); else if (fix_age > 5000) Serial.println("Warning: possible stale data!"); else Serial.println("Data is current.");

Interfacing with Serial GPS

To get valid and timely GPS fixes, you must provide a reliable NMEA sentence feed. If your NMEA data is coming from a serial GPS unit, connect it to Arduino’s hardware serial port, or, if using a “soft” serial port, make sure that you are using a reliable SoftSerial library. As of this writing (Arduino 0013), the SoftwareSerial library provided with the IDE is inadequate. It’s best to use my NewSoftSerial library, which builds upon the fine work ladyada did with the AFSoftSerial library.

Library Version

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

int ver = TinyGPS::library_version();

Resource Consumption

Linking the TinyGPS library to your application adds approximately 2500 bytes to its size, unless you are invoking any of the f_* methods. These require the floating point libraries, which might add another 600+ bytes.

Download

The latest version of TinyGPS is available here: TinyGPS12.zip

Change Log

  1. initial version
  2. << streaming, supports $GPGGA for altitude, floating point inline functions
  3. also extract lat/long/time from $GPGGA for compatibility with devices with no $GPRMC
  4. bug fixes
  5. API re-org, attach separate fix_age’s to date/time and position.
  6. Prefer encode() over operator<<. Encode() returns boolean indicating whether TinyGPS object has changed state.
  7. Changed examples to use NewSoftSerial in lieu of AFSoftSerial; rearranged the distribution package.
  8. Greater precision in latitude and longitude.  Angles measured in 10-5 degrees instead of 10-4 as previously.  Some constants redefined.
  9. Minor bug fix release: the fix_age parameter of get_datetime() was not being set correctly.
  10. Added Maarten Lamers’ distance_to() as a static function.
  11. Arduino 1.0 compatibility
  12. Added satellites(), hdop(), course_to(), and cardinal()

Acknowledgements

Many thanks to Arduino forum users mem and Brad Burleson for outstanding help in alpha testing this code. Thanks also to Maarten Lamers, who wrote the wiring library that originally gave me the idea of how to organize TinyGPS.  Thanks also to Dan P. for suggesting that I increase the lat/long precision in version 8.  Thanks to many people who suggested new useful features for TinyGPS, especially Matt Monson, who wrote some nice sample code to do so.

All input is appreciated.

Mikal Hart

Page last updated on March 17, 2012 at 6:39 pm
280 Responses → “TinyGPS”

  1. Mikal

    1 week ago

    A Siefert,
    Are you using [New]SoftSerial to communicate with the GPS? If so, check nss.overflow() to see if you are losing characters. I bet that’s the case. I bet you are not processing the data as fast as it’s arriving.


  2. Mikal

    1 week ago

    Amaynard,

    Love the Fio cat tracker idea. We want to build one of those too. Make sure you get the latest versions of Arduino and all the libraries and they should work together ok.


  3. ADRIANA

    1 week ago

    hola disculpa TinyGPS ES COMPATIBLE CON ARDUINO NG Atmega8 estoy haciendo un dataloger y esto utilizando el GPS FV-M8 y me gustaria saber si es compatible o hay una libreria para la version 0022 de arduino esque no me corre el ejemplo de la libreria llamado static_test me dice que es el sketch es demaciado grande gracias


  4. Mikal

    1 week ago

    Does anyone know if TinyGPS is small enough to work with Atmega8? I imagine it should work fin.


  5. D

    6 days ago

    Mikal,
    Sorry if my question was unclear. I’m trying to get date and time regardless of satellites in view. GPRMC sentences have good time data available via real time clock on the module. This is the sentence that the datetime crack seems to not like. “$GPRMC,184104.706,V,,,,,,,020512,,,N*40″
    As soon as I move within view of a satellite the datetime crack works as expected.
    Any thoughts?

    Thanks,
    D

25 Trackbacks For This Post
  1. เริ่มต้นสร้าง GPS จอสีกับอาดูอี้โน่ | Ayarafun Factory

    [...] http://www.sundial.org/arduino/?page_id=3 [...]

  2. 10

    [...] won’t. I answer a few questions on the Arduino microcontroller forum and post an update to a library I [...]

  3. The Hired Gun » GPS project: show me something

    [...] this journey I also looked into using the TinyGPS library. While it does a nice job of handling the core GPS parsing, I still had the primary desire to log [...]

  4. GPS mit Arduino - Webmeister Blog

    [...] serielle Verbindung werden die  Daten ans Display geschickt. Verwendet werden die Bibliotheken TinyGPS und [...]

  5. The Frustromantic Box, Part 4: Software « New Bright Idea

    [...] Arduino developers for the great librarires, and to Mikal Hart in particular for his work on the TinyGPS and NewSoftSerial [...]

  6. Transmission success - Projects

    [...] and sending the bits of “Hello World” in 7N1 format.  I spent some time with the TinyGPS and NewSoftSerial libraries from Mikal Hart, and got the parsing working nicely and building an [...]

  7. GPS testing with LCD Character Display

    [...] can have the LCD output latitude, longitude, or whatever. You’ll need the TinyGPS library from Arduiniana downloaded and installed for it to work. They suggest using NewSoftSerial, but I couldn’t get [...]

  8. Arduino GPS — not exactly pocket-sized, but cool! « Arduino Projects FTW

    [...] EEPROM so they are persistent between power cycles. The sketch uses Mikal Hart's excellent TinyGPS library and includes code from the ArduPilot Projectfor [...]

  9. A fully functional Arduino GPS receiver | Embedded projects from around the web

    [...] uses a TinyGPS library for easier GPS shield access. So device can be used as normal GPS tracking device the only [...]

  10. Moving Forward with Arduino – Chapter 17 – GPS « t r o n i x s t u f f

    [...] point you will need to install two libraries into the Arduino software – NewSoftSerial and TinyGPS. Extract the folders into the libraries folder within your arduino-001x [...]

  11. Shield Driven Arduino GPS

    [...] sketch uses Mikal Hart’s excellent TinyGPS library and includes code from the ArduPilot Project for [...]

  12. GPS bővítés « Nikon D5000 DSLR

    [...] 2 [...]

  13. The Maritime Geocaching Association » Build Your Own Steampunk GPS

    [...] attached code should pretty much speak for itself. Using the TinyGPS library, your current position is taken and the direction to the final location is calculated. [...]

  14. Moving Forward with Arduino – Chapter 19 – GPS part II « t r o n i x s t u f f

    [...] pull-down resistor). You will need to install the SdFAT library, NewSoftSerial library, TinyGPS library and the SdFat library if not already [...]

  15. Arduinoによる放射線データ収集(3) « stastaka's Blog

    [...] http://arduiniana.org/libraries/tinygps/ USBシリアルを使っているとTX,RXが使えませんが、 [...]

  16. reptile-addict.nl | My Arduino Blog

    [...] Mikal Hart’s tinyGPS library; [...]

  17. Communicating to GPS Receiver using USB Host Shield « Circuits@Home

    [...] how to send raw GPS output to a NMEA 0183 message parser. For the following code example I used Mikal Hart’s TinyGps library. Since the library itself is not handling serial input, it was only necessary to make changes in [...]

  18. GpsBee and Seeeduino Stalker v2 « Wireless Building Automation

    [...] easy developing of the necessary Arduino application I used an existent dedicated library: TinyGPS (http://arduiniana.org/libraries/tinygps/), which help us to parse all the packets received on the serial port from the GpsBee module. Ok, so [...]

  19. SheekGeek » Blog Archive » Weather Balloon Payload Testing on a Model Rocket (Pt.1)

    [...] and gyroscope package and slapped together a simple SD card interface. The libraries I used were TinyGPS and fat16lib (for SD card use). Weather_Balloon_Code and schematic in case you’d like to [...]

  20. Moving Forward with Arduino – Chapter 19 – GPS part II « t r o n i x s t u f f

    [...] forget the 10k ohm pull-down resistor). You will need to install NewSoftSerial library, TinyGPS library and the SdFat library if not already [...]

  21. Anonymous

    [...] [...]

  22. Jacket Positioning System: JPS « Titles are Strange Things

    [...] it’s pretty simple. It only does those functions, but with the help of the truly fantastic TinyGPS library, I have a destination function in the [...]

  23. Testing MTK3329 10Hz GPS module and making an Arduino GPS logger | Develop with Arduino

    [...] TinyGPS for Arduino [...]

  24. Arduino + GPS Shield + LCD 16x2 | We Are The Electric Brothers

    [...] tinygps [...]

  25. TinyGPS Libraryを使ってGPSデータを取得

    [...] ちなみに、データ処理部分は、TinyGPS Libraryなる便利なものがあったので、それを使ってみた。 [...]

Leave a Reply