3

I really hope somebody can help me.

I need help making my code receive updates faster to the parser...I need the received GPS coordinates (Latitude and Longitude) to update 5 or more times a second, currently it locks when stationary. Can somebody help?

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;
//
//double getCurrentLatitude(){
//  return cLatitude;
//}
//
//double getCurrentLongitude(){
//  return cLongitude;  
//}

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

//  Serial.print("Testing TinyGPS library v. "); Serial.println(TinyGPS::library_version());
//  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()
{
  double flat, flon = 0.0000000000000;
  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(), 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);
}
4
  • You have smartdelay(1000); in loop().
    – Nick T
    Commented Apr 10, 2014 at 1:17
  • 1
    Also, you're not going to be able to move much data at 4800 baud. You may be limited in terms of the GPS update rate by that baud-rate. Commented Apr 10, 2014 at 1:40
  • More details please. Are you using an arduino mega or an uno or what? are you using the software serial or using 2 hardware serials? What GPS device are you using? and what do you mean by locks when stationary?
    – m3z
    Commented Apr 16, 2014 at 8:55
  • Sorry, Missed the fact you're using a Due in the tags.
    – m3z
    Commented Apr 16, 2014 at 9:02

1 Answer 1

2

I assume you're using TinyGPS which I sourced from https://github.com/mikalhart/TinyGPS

I've recently done a similar thing - just trying to get the gps to work and give me as much data as possible.

The code I used to do this is here:

#include "TinyGPS.h"

#define GPS_BAUD 115200
#define PC_BAUD 115200

TinyGPS gps;

int led1 = 13;

long lat, lon;

unsigned long fix_age, time, date, speed, course;

unsigned long chars;
unsigned short sentences, failed_checksum;

void setup()
{
  pinMode(led1, OUTPUT);
  Serial1.begin(GPS_BAUD);
  Serial.begin(PC_BAUD);
  Serial1.println("");
  Serial1.println("Initializing");
  Serial1.println("");
  digitalWrite(led1, HIGH);
  delay(2000);
  digitalWrite(led1, LOW);
  delay(500);
}

void loop()
{
  while(Serial1.available()){
    if(gps.encode(Serial1.read())){
      digitalWrite(led1, HIGH);
      gps.get_position(&lat, &lon, &fix_age);
      gps.get_datetime(&date, &time);
      Serial1.println("");
      Serial1.println("Lat: " + String(lat));
      Serial1.println("Lon: " + String(lon));
      delay(3000);
      gps.stats(&chars, &sentences, &failed_checksum);
      Serial1.println("Chars: " + String(chars));
      Serial1.println("Sents: " + String(sentences));
      delay(1000);
      Serial1.println("Fails: " + String(failed_checksum));
      Serial1.println("");
      delay(1000);
    }
    Serial1.print(".");
  }
}

I was using an Arduino Mega 2560, but I think you have the same Serial ports on your Due. I connected the TX pin of my GPS ( can't remember the model but I think it was a 10Hz version of this: https://www.sparkfun.com/products/9891 ) to Serial1's RX and I used a small serial 2 row LCD display to output which was connected to Serial1's TX, hence I was using serial1 for both transmitting and receiving. If you remove the delays from the code above the data is read and then written back as fast as possible and while I never measured how many fixes I was seeing per second I'm fairly sure there were at least 5.

The code you want is probably something like this:

#include "TinyGPS.h"

#define GPS_BAUD 115200
#define PC_BAUD 115200

TinyGPS gps;

int led1 = 13;

long lat, lon;

unsigned long fix_age, time, date, speed, course;

unsigned long chars;
unsigned short sentences, failed_checksum;

void setup()
{
  pinMode(led1, OUTPUT);
  Serial1.begin(GPS_BAUD);
  Serial.begin(PC_BAUD);
  Serial1.println("");
  Serial1.println("Initializing");
  Serial1.println("");
  digitalWrite(led1, HIGH);
  delay(2000);
  digitalWrite(led1, LOW);
  delay(500);
}

void loop()
{
  while(Serial1.available()){
    if(gps.encode(Serial1.read())){
      digitalWrite(led1, HIGH);
      gps.get_position(&lat, &lon, &fix_age);
      gps.get_datetime(&date, &time);
      Serial.print("    ");
      Serial.print(lat);
      Serial.print(" ");
      Serial.print(long);
    }
  }
}

As commented by @connor-wolf above you will probably need to change the baud-rate of your communications up because otherwise you the limit of the amount of information you can send/receive per second is probably too low. The baud rate must also match the baud rate of your GPS device. Some GPS devices have an adjustable baud rate.


A quick google turned up an average NMEA sentence length of 60 bytes and if I recall correctly you may have 2 or 3 sentences to each fix? (I think the extra sentences contain extra info like satellite counts, and stuff). So assume you need 180 bytes per fix and you want at least 5 fixes per second that would be 900 bytes. In baud that is 900x8 = 7200. So assuming my estimations above are accurate or overestimated then you have enough bandwidth.

I'm not sure however if the Micro transmits/receives over serial while running the other instructions in your code - I would assume not to be safe but it's worth some research. Therefore you have to account for the time the micro spends transmitting and interpreting the data as time in the second that it can't spend receiving the data. Therefore I would suggest that doubling or even tripling the data rate would be a good idea. (as you can see from my example I just set it to as high as the GPS would go.)

Anyway. I hope all that helps.

P.S please forgive if I've used the wrong terminology for fixes/sentences or whatever

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.