Arduino GPS

I am using a Ruggeduino for a project involving an autonomous vehicle, and I need GPS capability in it. I am using the "VPN1513 GPS Smart Module with External Antenna" from Parallax (https://www.parallax.com/product/28510), and the TinyGPS Library (http://arduiniana.org/libraries/tinygps/). I have it supplied with 5v, grounded, and with the SIG and EN wires going to ports 0 and 1 on the Ruggeduino. Everything that I have done so far has resulted in this example program from the library returning "****", which means it is getting invalid data. Does anyone know what I'm doing wrong? Thank's for the help in advance.

Here's the program:

   #include <SoftwareSerial.h>

   #include <TinyGPS.h>

   TinyGPS gps;
   SoftwareSerial nss(1, 0);

   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(115200);
     nss.begin(9600);

     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;
   }

Have you done a simple 'SerialRelay' type of program to examine the raw data you are receiving?

Oh, and using [code][/code] tags will format your code correctly instead of putting into italics. Read the Sticky at the top of the page. Observing forum etiquette may well get you more responses.

I'm sorry, I'm really new to arduino. Would you mind explaining exactly what I should do? I have no idea what a SerialRelay program is.

(I'm assuming that your Ruggeduino is an Uno compatible)

SoftwareSerial nss(1, 0);

Not a good idea. The Hardware Serial uses pins D0 & D1 for communication.

A SerialRelay sketch simply relays serial data from Serial Monitor to device and vice versa. Connect your Rx/Tx pins to D2 & D3 and try the following (not compiled and untested):

#include <SoftwareSerial.h>

SoftwareSerial mySerial(2, 3);

void setup()
{
  mySerial.begin(9600);
  Serial.begin(19200);
}

void loop()
{
  if (mySerial.available())
    Serial.write(mySerial.read());
  if (Serial.available())
    mySerial.write(Serial.read());
}

Open serial monitor and you should see the NMEA sentences from the GPS unit. If not swap over the connections to D2 & D3.

The net has several sources explaining the structure of the NMEA sentence.

I tried the program, but it didn't output anything. I know it's not my wiring, that's the one thing I'm sure of. Any idea why?

Have you verified that the GPS unit is getting a satellite fix? Your documentation states that the status LED will blink. It doesn't state what the asterisks mean but I've seen other GPS modules show asterisks in their messages when no fix is available.

It can and will take a long time from a cold start to get that satellite fix. And along those lines the typical solution is to just take everything outside so you get a clear signal.

The unit is getting a satellite fix. The liht is blinking, and we have tried running it for about ten minutes with no effect. Also the asterisks are just part of the program I had. It returns them on the serial monitor if it recieves invalid data.

I tried the program, but it didn't output anything. I know it's not my wiring, that's the one thing I'm sure of. Any idea why?

Since you don't mention changing it, I'll assume that you didn't. Therefore, you can't expect any change in behavior.

You are taking the GPS outside, aren't you?

I did change it over to the other connections, but it did nothing. Also, I am taking it outside. Also, according to the documentation, the light on the unit blinks when it connects, and is solid when it is not connected. It is blinking. That said, it is blinking irregularly. Could it be that it is losing the connection? One last thing- I called tech support for the product, and they directed me to a program built for it. It output "Module Not Responding", which is slightly worrying.

It output "Module Not Responding", which is slightly worrying.

Very worrying, but you may not have it connected correctly.

Just in case I'm wrong, would anyone mind posting a diagram and program I can use with it? Like I said, I'm really new and I could be wrong.

Looking more closely at the documentation of your GPS module (which it's more than just a "GPS module") you need to be aware that this module does not speak NMEA0183 sentences to "you". Your module is a GPS chip PLUS a Propeller chip interface. The GPS chip talks to the Propeller via NMEA0183 sentences, but you have to talk to the Propeller using its proprietary protocol.

Regarding the program that tech support sent you to (I assume it's that "GPSSmartModule_V1_0.ino" in the "ST-00059--GPS-Smart-Module-Arduino-V1.0.zip" archive), it wants the "SIG" pin connected to pin 12 on the Arduino, VCC and GND is obvious, and then leave the "EN" pin unconnected -- it's ENabled by default.

The first step is going to be getting that example program running. Second step might be throwing the module away and getting a more conventional GPS module, but that's another story.

Second step might be throwing the module away and getting a more conventional GPS module, but that's another story.

After looking at the documentation on the Parallax site for this module, I'm inclined to support Chagrin's (quoted) suggestion. This module was intended for Parallax-specific applications and not for an Arduino, so you if want to use it, you will have to learn a bunch of material that, in the long run, will be otherwise completely useless!

Chagrin:
Second step might be throwing the module away and getting a more conventional GPS module

I, for example, have this adafruit one; had it working in the time it took to boil the kettle for tea when I got home one evening.

Thanks for the help, Chagrin. Now it's giving me latitude and longitude, but not giving me the heading. It's giving "n/a" for it. Any idea what the problem is? Again, thank you all for your help.

Your module doesn't have a magnetometer, so the only way the heading is derived is from movement. Are you moving the unit? Beyond that tidbit of advice, the source for your firmware is not available so it's impossible to know the exact method by which the heading is derived.

You were totally right. Once it was moving, I got an accurate heading. Thanks. :slight_smile:

Another question...

Say I want to have the gps hooked up to an arduino. Then, I have another arduino hooked up to the first arduino. Is there any easy way to send the data from the first to the second? I looked online and read a whole lot of stuff I didn't understand about serial communication, and tried several scripts I found that didn't work. Can anyone just supply me with a simple script to send a string to another arduino? I'm still a beginner programmer and all I've found has just confused me more.

Thanks for all the help.

Regarding the wiring there's not much to it: TX on one to RX on the other and RX to TX.

Try EasyTransfer Arduino Library « The Mind of Bill Porter for a complete solution on sending messages between Arduinos. It's designed to keep a struct of data in sync between those Arduinos but it can be manipulated for more ad-hoc messages too.

Handling IO in C is something that just comes with more experience in C. There's no particular tricks or anything; once you have more experience things will just make more sense. Dunno what else to say about that...

kornexls:
Thanks for the help, Chagrin. Now it's giving me latitude and longitude, but not giving me the heading. It's giving "n/a" for it. Any idea what the problem is? Again, thank you all for your help.

Can you tell me what have you done so it started sending latitude and longitude? Thanks.