I made a GPS library for decoding NMEA protocol

Version 6 of the TinyGPS library is now available at http://www.sundial.com/tinygps. Depending on the feedback, I'll post on the playground.

Mikal

Very nice – I tested Version 6 with the [u]parallax GPS module[/u] and it works great.

FYI, here is the output (last few digits of the location obfuscated)

Testing TinyGPS library v. 6
by Mikal Hart

Sizeof(gpsobject) = 103

Acquired Data

Lat/Long(10^-6 deg): 5155xx, -17xx Fix age: 400ms.
Lat/Long(float): 51.55xx, -0.17xx Fix age: 454ms.
Date(ddmmyy): 210109 Time(hhmmsscc): 10594800 Fix age: 14ms.
Date: 1/21/2009 Time: 10:59:48.0 Fix age: 76ms.
Alt(cm): 4370 Course(10^-6 deg): 0 Speed(knots): 0
Alt(float): 43.7000 Course(float): 0.0000
Speed (knots): 0.0000 (mph): 0.0000 (mps): 0.0000 (kmph): 0.0000 Stats: characters: 2030 sentences: 8 failed checksum: 10

Mem, thank you very much for the feedback.

The relatively high ratio of failed checksums is a little worrisome. I usually only get 1 or 2 in an hour-long run with my EM406A. I hope it does not indicate a latent bug in TinyGPS checksum calculations, although I note that some of the sentences passed or you wouldn't have gotten any good data. Are you using the revised AFSoftSerial library?

Thanks!

Mikal

I am using the afss version posted here: http://forums.ladyada.net/viewtopic.php?f=25&t=8351

One reason that the error rate may be higher then expected is the circuitous connectivity in my test rig. The GPS was connected to the arduino via a pair of xbee modules. One xbee is connected to the GPS at 4800 baud, the other is connected to the Arduino afss input at 9600 baud.

Strange, I tried connecting the GPS directly to the Arduino and am no longer getting the encode method returning true so newdata is always false and dump is never called.

If I modify feedgps to the following, I do get the sentences printed out:

bool feedgps()
{
  while (afss.available())
  {
    char c = afss.read();
    Serial.print(c);
    if (gps.encode(c) )
//    if (gps.encode(afss.read()))
      return true;
  }
  return false;
}

Fwiw, here is some of the output from that code:

$GPGSV,2,1,08,11,70,142,40,14,22,041,00,17,40,300,00,19,12,162,00*79

$GPGSV,2,2,08,20,66,238,00,23,18,181,36,28,13,257,00,32,83,087,00*72

$GPRMC,143727,V,5133.1094,N,00010.4425,W,000.0,331.5,210109,,,N*7F

$GPGGA,143728,5133.1094,N,00010.4425,W,0,00,,-00000.0,M,047.3,M,,*67

$GPGSA,A,1,,,,,,,,,,,,,,,*1E

Not sure what is going on, I may have to put some debugging in the encode method.

edit: I just tried it again with the xbee and its no longer working with that. Its a real rats nest of wires here so the problems may have nothing to do with the code. I am going to clean everthing up and try it again - but want get back to this till much later today.

Mem,

I took the 5 sentences you posted and ran them through TinyGPS -- it's easy to do this by editing the testgps1 example -- and they all pass the checksum test. But they don't provide any data. I did a little debugging and finally noticed that the $GPRMC sentence is reporting V ("void") (term #2), which according to one page indicates "navigation receiver warming". This field must be "A" for TinyGPS to recognize it as valid. Also the $GPGGA sentence reports position type of "invalid or not available". The $GPGSV and $GPGSA sentences are checked for valid checksum, but no useful data is extracted.

http://ssro.ee.uec.ac.jp/ssro/uchuu-tsuushin/gps/GPS-data-format.html

Thanks again,

Mikal

Once I fixed an errant ground wire and starting getting serial data again, I was able to determine the signal with the GPS on inside of the window sill was probably causing the failed checksums. Moving the GPS to the outside of the window gave these results:

Acquired Data

Lat/Long(10^-6 deg): 5155xx, -17xx Fix age: 263ms.
Lat/Long(float): 51.55xx, -0.17xx Fix age: 315ms.
Date(ddmmyy): 210109 Time(hhmmsscc): 20062100 Fix age: 365ms.
Date: 1/21/2009 Time: 20:6:21.0 Fix age: 49ms.
Alt(cm): -210 Course(10^-6 deg): 1350 Speed(knots): 0
Alt(float): -2.0999 Course(float): 13.5000
Speed (knots): 0.0000 (mph): 0.0000 (mps): 0.0000 (kmph): 0.0000
Stats: characters: 33236 sentences: 181 failed checksum: 6

The signal is still not great (the altitude is off by almost 100 meters) but I will wait till its stops raining before taking the test rig outside. Anyway, I am happy that your library is working fine.

I am not sure if this is related to your failed checksums, but some GPS device need a really clean voltage supply to work better. I hope this helps...

Hi Mikal,
The most recent test had the GPS directly connected to the arduino and used USB power through ten feet of cable. No extra decoupling was used on GPS which was powered from the Arduino 5v line.

When connected to the Xbee shield, both the xbee shield and GPS were powered from a battery providing 5 volts.

My guess is that the problem is due to the GPS not getting full view of the sky. I will do some more tests later today. But I doubt it has anything to do with the library code.

The checksum has nothing to do with RF signal quality. The checksum is calculated inside the GPS receiver and is to reduce errors on the RS232 communications link.

GPS at best does an adequate job of altitude determination. The higher overhead the satellites are the better it will do. If you're testing inside your house, most likely you're getting the satellites toward the horizon, which is going to leave you with more error in your altitude.

-j

The checksum has nothing to do with RF signal quality.
strange that number of checksum errors dropped significantly when the GPS was moved from the inside to the outside of the window. But perhaps other things were changed that caused the difference.

The higher overhead the satellites are the better it will do
I know :wink:

Mikal, how does your library behave in the absence of a valid GPS lock?

I perused the web site (but not the source code) and didn't see any way to check if the GPS has a fix.

-j

j--

The TinyGPS documentation is still pretty flimsy, I'm afraid.

Your GPS has never gotten a "fix" if the "fix_age" parameter in get_position() and get_datetime() returns GPS_INVALID_AGE (0xFFFFFFFF). Under normal circumstances, fix_age is the number of milliseconds since the last valid fix was recorded. When things are working properly, I never get a value more than about 1000, since my GPS provides fix data every second or so. If you start seeing this value get above 2000 or so, it is probably an indication that you had a fix at some point, but no longer do.

Also, if you have never gotten a fix, lat/long will be returned as GPS_INVALID_ANGLE. Otherwise, these will be the from the latest valid fix -- whenever that was.

Mikal

j--

Just a quick note that I added some text about establishing fix age based on your question, and today I released the first "real" version of TinyGPS: http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1233298045/0#0. Thanks for your feedback.

Mikal

Just a quick question, is the library here http://www.maartenlamers.com/nmea/gps-nav-001.html the current one? I have problems getting the example codes provided to compile, both on Arduino Mega and arduino pro.

Has any succesfully made a gps logger with the arduino platform? I was thinking about using this library and the sd card library

Any thoughts on this?

Kim

The library that this thread is about is here:

http://arduiniana.org/libraries/tinygps/

The GPS Logger shield from Adafruit works great, and has working sample code.

I have some notes on my GPS project (that includes logging) here:
http://hiredgunsoftware.net/wp/?tag=gps
I haven't posted the code yet, since part of it is incomplete, but I'd be glad to share what I have.

Rob

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

and not returning it in m/s?

Because the GPS returns speed in knots?

Using hundredths allows you to avoid the issue of floating point performance and still get the fractional speed if your GPS has that resolution.

-j

Exactly right. NMEA provides for speed to be reported in knots. TinyGPS returns the speed in integral units of 100th of a knot to retain maximum precision without having to resort to floating point. However, if you don't mind floating point you can also call f_speed_mps to get your speed in meters per second.

Mikal