gps trouble shooting

Hi,

I’m working on a gps device, and was wondering if anyone might have some suggestions for figuring out what is going on.

I have a gps device that communicates via a low voltage ttl interface. It runs on a 3.3V connection, with the ttl interface operating at 2.8V.
The data packets it sends are NMEA, with a raw data packet appended to the end of the nmea sentence. It operates at 9,600 baud, 8bit, no parity. I can run the module on its eval kit with no problem. Excluding power and ground, my only connection is:

GPStx → pin 3

this is my code (an example from the mikal hart library)

#include <NewSoftSerial.h>

#include <TinyGPS.h>

/* This sample code demonstrates the normal use of a TinyGPS object.
   It requires the use of NewSoftSerial, and assumes that you have a
   4800-baud serial GPS device hooked up on pins 3(rx) and 4(tx).
*/

TinyGPS gps;
NewSoftSerial nss(3, 4);

static void gpsdump(TinyGPS &gps);
static bool feedgps();
static void print_float(float val, float invalid, int len, int prec);
static void print_int(unsigned long val, unsigned long invalid, int len);
static void print_date(TinyGPS &gps);
static void print_str(const char *str, int len);

void setup()
{
  Serial.begin(9600);
  nss.begin(4800);
  
  Serial.print("Testing TinyGPS library v. "); Serial.println(TinyGPS::library_version());
  Serial.println("by Mikal Hart");
  Serial.println();
  Serial.print("Sizeof(gpsobject) = "); Serial.println(sizeof(TinyGPS));
  Serial.println();
  Serial.println("Sats HDOP Latitude Longitude Fix  Date       Time       Date Alt     Course Speed Card  Distance Course Card  Chars Sentences Checksum");
  Serial.println("          (deg)    (deg)     Age                        Age  (m)     --- from GPS ----  ---- to London  ----  RX    RX        Fail");
  Serial.println("--------------------------------------------------------------------------------------------------------------------------------------");
}

void loop()
{
  bool newdata = false;
  unsigned long start = millis();
  
  // Every second we print an update
  while (millis() - start < 1000)
  {
    if (feedgps())
      newdata = true;
  }
  
  gpsdump(gps);
}

static void gpsdump(TinyGPS &gps)
{
  float flat, flon;
  unsigned long age, date, time, chars = 0;
  unsigned short sentences = 0, failed = 0;
  static const float LONDON_LAT = 51.508131, LONDON_LON = -0.128002;
  
  print_int(gps.satellites(), TinyGPS::GPS_INVALID_SATELLITES, 5);
  print_int(gps.hdop(), TinyGPS::GPS_INVALID_HDOP, 5);
  gps.f_get_position(&flat, &flon, &age);
  print_float(flat, TinyGPS::GPS_INVALID_F_ANGLE, 9, 5);
  print_float(flon, TinyGPS::GPS_INVALID_F_ANGLE, 10, 5);
  print_int(age, TinyGPS::GPS_INVALID_AGE, 5);

  print_date(gps);

  print_float(gps.f_altitude(), TinyGPS::GPS_INVALID_F_ALTITUDE, 8, 2);
  print_float(gps.f_course(), TinyGPS::GPS_INVALID_F_ANGLE, 7, 2);
  print_float(gps.f_speed_kmph(), TinyGPS::GPS_INVALID_F_SPEED, 6, 2);
  print_str(gps.f_course() == TinyGPS::GPS_INVALID_F_ANGLE ? "*** " : TinyGPS::cardinal(gps.f_course()), 6);
  print_int(flat == TinyGPS::GPS_INVALID_F_ANGLE ? 0UL : (unsigned long)TinyGPS::distance_between(flat, flon, LONDON_LAT, LONDON_LON) / 1000, 0xFFFFFFFF, 9);
  print_float(flat == TinyGPS::GPS_INVALID_F_ANGLE ? 0.0 : TinyGPS::course_to(flat, flon, 51.508131, -0.128002), TinyGPS::GPS_INVALID_F_ANGLE, 7, 2);
  print_str(flat == TinyGPS::GPS_INVALID_F_ANGLE ? "*** " : TinyGPS::cardinal(TinyGPS::course_to(flat, flon, LONDON_LAT, LONDON_LON)), 6);

  gps.stats(&chars, &sentences, &failed);
  print_int(chars, 0xFFFFFFFF, 6);
  print_int(sentences, 0xFFFFFFFF, 10);
  print_int(failed, 0xFFFFFFFF, 9);
  Serial.println();
}

static void print_int(unsigned long val, unsigned long invalid, int len)
{
  char sz[32];
  if (val == invalid)
    strcpy(sz, "*******");
  else
    sprintf(sz, "%ld", val);
  sz[len] = 0;
  for (int i=strlen(sz); i<len; ++i)
    sz[i] = ' ';
  if (len > 0) 
    sz[len-1] = ' ';
  Serial.print(sz);
  feedgps();
}

static void print_float(float val, float invalid, int len, int prec)
{
  char sz[32];
  if (val == invalid)
  {
    strcpy(sz, "*******");
    sz[len] = 0;
        if (len > 0) 
          sz[len-1] = ' ';
    for (int i=7; i<len; ++i)
        sz[i] = ' ';
    Serial.print(sz);
  }
  else
  {
    Serial.print(val, prec);
    int vi = abs((int)val);
    int flen = prec + (val < 0.0 ? 2 : 1);
    flen += vi >= 1000 ? 4 : vi >= 100 ? 3 : vi >= 10 ? 2 : 1;
    for (int i=flen; i<len; ++i)
      Serial.print(" ");
  }
  feedgps();
}

static void print_date(TinyGPS &gps)
{
  int year;
  byte month, day, hour, minute, second, hundredths;
  unsigned long age;
  gps.crack_datetime(&year, &month, &day, &hour, &minute, &second, &hundredths, &age);
  if (age == TinyGPS::GPS_INVALID_AGE)
    Serial.print("*******    *******    ");
  else
  {
    char sz[32];
    sprintf(sz, "%02d/%02d/%02d %02d:%02d:%02d   ",
        month, day, year, hour, minute, second);
    Serial.print(sz);
  }
  print_int(age, TinyGPS::GPS_INVALID_AGE, 5);
  feedgps();
}

static void print_str(const char *str, int len)
{
  int slen = strlen(str);
  for (int i=0; i<len; ++i)
    Serial.print(i<slen ? str[i] : ' ');
  feedgps();
}

static bool feedgps()
{
  while (nss.available())
  {
    if (gps.encode(nss.read()))
      return true;
  }
  return false;
}

the output on the serial port is very interesting, and suggests I am reading something, but I don’t know what. This is what it looks like

**** **** ******* ******* **** ******* ******* **** ******* ****** ***** *** 0 0.00 *** 977 0 139
**** **** ******* ******* **** ******* ******* **** ******* ****** ***** *** 0 0.00 *** 1961 0 281
**** **** ******* ******* **** ******* ******* **** ******* ****** ***** *** 0 0.00 *** 2929 0 428
**** **** ******* ******* **** ******* ******* **** ******* ****** ***** *** 0 0.00 *** 3913 0 584
**** **** ******* ******* **** ******* ******* **** ******* ****** ***** *** 0 0.00 *** 4893 0 730
**** **** ******* ******* **** ******* ******* **** ******* ****** ***** *** 0 0.00 *** 5868 0 899
**** **** ******* ******* **** ******* ******* **** ******* ****** ***** *** 0 0.00 *** 6852 0 1041
**** **** ******* ******* **** ******* ******* **** ******* ****** ***** *** 0 0.00 *** 7830 0 1188
**** **** ******* ******* **** ******* ******* **** ******* ****** ***** *** 0 0.00 *** 8819 0 1328
**** **** ******* ******* **** ******* ******* **** ******* ****** ***** *** 0 0.00 *** 9817 0 1480
**** **** ******* ******* **** ******* ******* **** ******* ****** ***** *** 0 0.00 *** 10804 0 1620
**** **** ******* ******* **** ******* ******* **** ******* ****** ***** *** 0 0.00 *** 11785 0 1768
**** **** ******* ******* **** ******* ******* **** ******* ****** ***** *** 0 0.00 *** 12020 0 1801
**** **** ******* ******* **** ******* ******* **** ******* ****** ***** *** 0 0.00 *** 12998 0 1939
**** **** ******* ******* **** ******* ******* **** ******* ****** ***** *** 0 0.00 *** 13974 0 2081
**** **** ******* ******* **** ******* ******* **** ******* ****** ***** *** 0 0.00 *** 14952 0 2225

Can anyone possibly shed some light on this? Please let me know if more info is needed.

Has your GPS been operating under a clear sky long enough to download the ephemeris data from the satellites?

another idea is to make a small test program that does nothing but read from the GPS and display it to the console. don’t even bother with the tinygps.h or anything else. that’s how I started with my GPS.

All the asterisks are where the GPS data would go, if the GPS was getting data to the Arduino. That there are nothing but asterisks suggests that this is not the case.

It runs on a 3.3V connection, with the ttl interface operating at 2.8V.

The 2.8 is probably not high enough to trigger a HIGH on the Arduino, which requires 0.6 * the operating voltage (typically 5.0V).

Perhaps you need a 3.3V Arduino (or a Netduino, since they operate at 3.3V).

The GPS is transmitting data to the Arduino and it is being received, the 3rd to last column on the output is the cumulative number of characters received from the GPS, the 2nd to last is the cumulative number of sentences received.

The strings of asterisks are hat symbol that routine uses for invalid data, meaning the GPS has no fix possible reasons for the lack of fix - no clear view of the sky - the GPS has not been on long enough for the almanac to be loaded, the almanac gives it an idea what sats in that geographic area and time should be visible - bad antenna connection - bad GPS unit

Focus on the first and give it up to 30 minutes for it to get its cold fix.

wade

thanks for the input.

I hooked it up to an evaluation kit to ensure that it was working properly. It would seem that the issue was needing the time required to download the almanac and ephemeris data. After it began getting data on the eval kit, I rewired it to the arduino, and seem to be getting good data.