GPS not working properly on Due but works perfect on UNO

Hi guys,

I have the Adafruit Ultimate GPS (http://goo.gl/v08qSz) which works perfectly fine with the Arduino Uno, now when I hook up that same GPS module with the Due, it doesn't work, I know its not a coding problem since I load in a blank sketch (i.e. void setup(){} void loop(){} ) into the board in order to by pass the Arduino board and just read data coming from the GPS module itself via Serial Monitor since the GPS module it has a built-in microcontroller.

When I perform the same procedure on the Due board and do the same exact hookup (the direct wiring instructions are found here: http://goo.gl/42hybn), the serial monitor reads a few garbage values and then will not output anything else until I press the reset button on the Due board, then it only outputs a partial nmea sentence until I press reset over and over again do I get a complete GPGGA or GPRMA sentence. This is driving me crazy, why is this happening?

I know most of you guys probably don't have this GPS module, but maybe you can tell me what I could potentially be doing wrong? Maybe I need to import a library or use an additional wire, maybe I'm hooking it up wrong, but I'm following the example I linked above, so this can't be it...any ideas guys??

From the site

5V friendly design

Is it a 3v3 or 5v module?


Rob

Graynomad has suggested something critical to check ... I haven't used this, but I wouldn't use their wiring instructions and power it with 5V. This is not compatible with the Due and could damage I/O (or worse). I checked their pdf and it states on page 3 "Best of all, we added all the extra goodies you could ever want: a ultra-low dropout 3.3V regulator so you can power it with 3.3-5VDC in ..." Also, on page 4: Vin range: 3.0-5.5VDC. Ensure that its powered with 3.3V and give it a try.

@Graynomad its a 3.3v

Hi,

are you using hardware serial?

I tried this with the due and it worked very well.

Regards, Otto.

Sorry, forgot the link,

http://bradsduino.blogspot.be/2013/06/adafruit-ultimate-gps-breakout-arduino.html

Regards, Otto.

@otto thanks Otto, but shouldn't there be a way of reading data directly off the GPS module itself not via the parser? I will try this out and will report back the results

Hi,

I have a SKM53 GPS module, which is a 5V one, connected to 3V3, using TinyGPS13 and it’s working very well… my Arduino DUE is still holding!!!

maybe you could give it a try with the library…

Regarding the wiring, I’ve connected the GPS to Serial1 and commented all ‘SoftwareSerial’ stuff since it was not needed:

//#include <SoftwareSerial.h>

#include <TinyGPS13.h>

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

TinyGPS13 gps;
//SoftwareSerial ss(4, 3);

static void smartdelay(unsigned long ms);
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(TinyGPS13 &gps);
static void print_str(const char *str, int len);

void setup()
{
  Serial.begin(115200);
  
  Serial.print("Testing TinyGPS library v. "); Serial.println(TinyGPS13::library_version());
  Serial.println("by Mikal Hart");
  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("------------------------------------------------------------------------------------------------------------------------------------------");

  Serial1.begin(9600);
}

void loop()
{
  float flat, flon;
  unsigned long age, date, time, chars = 0;
  unsigned short sentences = 0, failed = 0;
  static const double LONDON_LAT = 51.508131, LONDON_LON = -0.128002;
  
  print_int(gps.satellites(), TinyGPS13::GPS_INVALID_SATELLITES, 5);
  print_int(gps.hdop(), TinyGPS13::GPS_INVALID_HDOP, 5);
  gps.f_get_position(&flat, &flon, &age);
  print_float(flat, TinyGPS13::GPS_INVALID_F_ANGLE, 13, 8);
  print_float(flon, TinyGPS13::GPS_INVALID_F_ANGLE, 13, 8);
  print_int(age, TinyGPS13::GPS_INVALID_AGE, 5);
  print_date(gps);
  print_float(gps.f_altitude(), TinyGPS13::GPS_INVALID_F_ALTITUDE, 7, 2);
  print_float(gps.f_course(), TinyGPS13::GPS_INVALID_F_ANGLE, 7, 2);
  print_float(gps.f_speed_kmph(), TinyGPS13::GPS_INVALID_F_SPEED, 6, 2);
  print_str(gps.f_course() == TinyGPS13::GPS_INVALID_F_ANGLE ? "*** " : TinyGPS13::cardinal(gps.f_course()), 6);
  print_int(flat == TinyGPS13::GPS_INVALID_F_ANGLE ? 0xFFFFFFFF : (unsigned long)TinyGPS13::distance_between(flat, flon, LONDON_LAT, LONDON_LON) / 1000, 0xFFFFFFFF, 9);
  print_float(flat == TinyGPS13::GPS_INVALID_F_ANGLE ? TinyGPS13::GPS_INVALID_F_ANGLE : TinyGPS13::course_to(flat, flon, LONDON_LAT, LONDON_LON), TinyGPS13::GPS_INVALID_F_ANGLE, 7, 2);
  print_str(flat == TinyGPS13::GPS_INVALID_F_ANGLE ? "*** " : TinyGPS13::cardinal(TinyGPS13::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();
  
  smartdelay(1000);
}

static void smartdelay(unsigned long ms)
{
  unsigned long start = millis();
  do 
  {
    while (Serial1.available())
      gps.encode(Serial1.read());
  } while (millis() - start < ms);
}

static void print_float(float val, float invalid, int len, int prec)
{
  if (val == invalid)
  {
    while (len-- > 1)
      Serial.print('*');
    Serial.print(' ');
  }
  else
  {
    Serial.print(val, prec);
    int vi = abs((int)val);
    int flen = prec + (val < 0.0 ? 2 : 1); // . and -
    flen += vi >= 1000 ? 4 : vi >= 100 ? 3 : vi >= 10 ? 2 : 1;
    for (int i=flen; i<len; ++i)
      Serial.print(' ');
  }
  smartdelay(0);
}

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);
  smartdelay(0);
}

static void print_date(TinyGPS13 &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 == TinyGPS13::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, TinyGPS13::GPS_INVALID_AGE, 5);
  smartdelay(0);
}

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] : ' ');
  smartdelay(0);
}

It worked well for me…

cheers

And another thing.... if you wired it to TX0/RX0.... I'm not quite sure, but I believe that Serial (Serial0) is used to read data on screen and should be avoided if you are trying to get feedback values on screen... that's why I used Serial1 and voilá... Serial----> on screen COMXX feedback (nothing wired) Serial1---> GPS working good!!

I Hope it helped...I'm just an amateur on arduino Due...

cheers!!!

Just want to notify miqbal that I use the Adafruit Ultimate GPS module with the Due without any special libraries. I simply use hardware Serial1 (pins 19 (RX) and 18 (TX)). I configured the GPS module using the "Mini GPS" tool available at Adafruit. I used it to set the baud rate to 115200 and NMEA string update rate to 10hz. The Due had no issues receiving these strings at said speed. One trick about the "Mini GPS" tool: hit CNTRL+ALT+S to get setup page, otherwise you can't customize the module. You can also configure the contents of the NMEA string. For example, I had it simply send UTC time - it's all I needed and made the parsing effort fast and simple. Good luck.

@pistolero992000 Thanks I'm checking out your link right now

@randomvibe Thanks I will keep your suggestion if I encounter any issues.

@ hersoft your link worked for me, I just need to modify it to give me the GPGGA sentence rather than the other info

@pistolero992000

I know my question will sound dumb but I'm new to Arduino and micro controllers, I had the same problem as @miqbal, I downloaded the TinyGPS13 library and gave your code a try and it worked except that I've noticed the latitude field does not update as often as longitude? The longitude field works updates every second but not the latitude field. I guess the problem is that I am having trouble understanding the code.

I just want to print to console the latitude and longitude no other information. How can I do this in code?

like:

Serial.println(gps.flat);
Serial.println(gps.flon);

Any help or advise would be much appreciated.

@mynameismitch

If you want just the lat and longitude (continuously updated ofcourse) then make the main loop look like this:

void loop()
{
  float flat, flon;
  unsigned long age, date, time, chars = 0;
  
  gps.f_get_position(&flat, &flon, &age);
  print_float(flat, TinyGPS13::GPS_INVALID_F_ANGLE, 13, 8);
  print_float(flon, TinyGPS13::GPS_INVALID_F_ANGLE, 13, 8);
  print_int(age, TinyGPS13::GPS_INVALID_AGE, 5);
  Serial.println();
  smartdelay(1000);
}

when you make the gps object, you immediately get access to all the prewritten methods written(look into the cpp and h files from the library and you will see these), so method f_get_position() will get you your current position, method print_float will print to console the your lat and lon, if position is invalid you will get ***** written instead. print_int will do the same thing and ensure you’re reading are updated constantly. smart delay will delay for 1 second. I hope this helps

Thanks @miqbal, it worked!

(look into the cpp and h files from the library and you will see these)

Typical of Arduino stuff, little or no documentation.


Rob

@ pistolero992000

I modifed your code a bit just so I only get lat and lon but for some reason the GPS coordinates don’t seem to update as fast as before? Could anybody tell me how to fix this? Like make it update at least 5 times a second, I know this GPS unit does up to 10 times per second.

Here is the modified code:

#include <TinyGPS.h>

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

TinyGPS gps;
//SoftwareSerial ss(4, 3);

static void smartdelay(unsigned long ms);
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);
//double getCurrentLatitude();
//double getCurrentLongitude();

//double cLatitude = 0.0;
//double cLongitude = 0.0;
//
//public double getCurrentLatitude(){
//  return cLatitude;
//}
//
//double getCurrentLongitude(){
//  return cLongitude;  
//}

void setup()
{
  Serial.begin(115200);

  Serial1.begin(9600);
}

void loop()
{
  double flat, flon = 0.0000000000000;
  unsigned long age, date, time, chars = 0;
  unsigned short sentences = 0, failed = 0;
  
//  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);
//  gps.f_get_position(&cLatitude,&cLongitude, &age);
  
  //print_float(flat, TinyGPS::GPS_INVALID_F_ANGLE, 13, 8);
  //print_float(flon, TinyGPS::GPS_INVALID_F_ANGLE, 13, 8);
  
  float lati = (float)flat;
  float longi = (float)flon;
  
  Serial.print("     ");
  Serial.print(lati, 8);
  Serial.print(" ");
  Serial.print(longi, 8);
  smartdelay(0);
  //cLatitude = flat;
  //cLongitude = flon;
//  print_float(getCurrentLatitude(), TinyGPS::GPS_INVALID_F_ANGLE, 13, 8);
//  print_float(getCurrentLongitude(), TinyGPS::GPS_INVALID_F_ANGLE, 13, 8);
  
  
//  print_int(age, TinyGPS::GPS_INVALID_AGE, 5);
//  print_date(gps);
//  print_float(gps.f_altitude(), TinyGPS::GPS_INVALID_F_ALTITUDE, 7, 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 ? 0xFFFFFFFF : (unsigned long)TinyGPS::distance_between(flat, flon, LONDON_LAT, LONDON_LON) / 1000, 0xFFFFFFFF, 9);
//  print_float(flat == TinyGPS::GPS_INVALID_F_ANGLE ? TinyGPS::GPS_INVALID_F_ANGLE : TinyGPS::course_to(flat, flon, LONDON_LAT, LONDON_LON), 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();
  
  smartdelay(1000);
}

static void smartdelay(unsigned long ms)
{
  unsigned long start = millis();
  do 
  {
    while (Serial1.available())
      gps.encode(Serial1.read());
  } while (millis() - start < ms);
}

static void print_float(float val, float invalid, int len, int prec)
{
  if (val == invalid)
  {
    while (len-- > 1)
      Serial.print('*');
    Serial.print(' ');
  }
  else
  {
    Serial.print(val, prec);
    int vi = abs((int)val);
    int flen = prec + (val < 0.0 ? 2 : 1); // . and -
    flen += vi >= 1000 ? 4 : vi >= 100 ? 3 : vi >= 10 ? 2 : 1;
    for (int i=flen; i<len; ++i)
      Serial.print(' ');
  }
  smartdelay(0);
}


/*
    If data is invalid, print out *******
    otherwise print out buffer
*/
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);
  smartdelay(0);
}

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);
  smartdelay(0);
}

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] : ' ');
  smartdelay(0);
}

So now the coordinates themselves are put into float variables lati and longi, this way I can use the data while the GPS continuously updates.

So now the output is just like this:

     34.073620 -118.400356
     34.073620 -118.400356
     34.073620 -118.400356
     34.073620 -118.400356
     34.073620 -118.400356
     34.073620 -118.400356
     34.073620 -118.400356
     34.073620 -118.400356
     34.073620 -118.400356
     34.073620 -118.400356
     34.073620 -118.400340
     34.073620 -118.400340
     34.073620 -118.400340
     34.073620 -118.400340
     34.073620 -118.400340
     34.073620 -118.400340
     34.073620 -118.400340
     34.073620 -118.400343
     34.073620 -118.400356
     34.073620 -118.400356
     34.073620 -118.400356
     34.073620 -118.400356
     34.073620 -118.400356
     34.073618 -118.400356
     34.073618 -118.400352
     34.073618 -118.400352

Notice how the location stays the same for a bit, how do I make it so it updates faster? Any help or suggestions will be much appreciated, thanks

You need to take a look at your gps specs.... Refresh rate, normally expressed as Hz...

If your gps refresh its data at 1 Hz you'll be able to read it only once per second... 5 Hz five times per second... And so on...

I've seen GPSs that are able up to 10 Hz, and it is selectable. So, you need to send a code to the gps to make it work at that speed....

Check the gps operation manual....

Hope that helps!!!!

Ah, BTW if you have the SKgps 53, it works at 1Hz....