Need help with TinyGPS and storing data from it

I'm doing a project that reads in a bunch of sensor data at different time. For example some update at 500ms and others at 10ms. I want to store the values in an array so that I can have access to any of the sensor data at anytime.

For the GPS I'm using the TinyGPS library and I'm having tons of trouble with getting the data into an array. I use commands like these to read the sensor data.

 myArray[2] = gps.f_course();  // heading
 myArray[5] = gps.f_speed_kmph(); // speed

The first problem is that when I store the heading and speed I only get two digits. So while my heading using the TinyGPS example will print 65.46, myArray will print 65.

The next problem is getting the latitude and longitude data. I can print it using the TinyGPS sample code but I cant get the values out at all. This is the sample code to get the latitude and longitude data to print.

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

So everything works fine to print out using the example from TinyGPS but I'm having lots of trouble storing the values.

The first problem is that when I store the heading and speed I only get two digits. So while my heading using the TinyGPS example will print 65.46, myArray will print 65.

Code snippets are not us. Post all of your code. We have no idea whether myArray is an array of char arrays, an array of floats, or an array of ints.

If you are trying to store floats in it, there is only one type that is appropriate.

The next problem is getting the latitude and longitude data. I can print it using the TinyGPS sample code but I cant get the values out at all.

The &flat and &flon in that statement tells the function to store the values in flat & flon.

myArray[x] = flat;
myArray[y] = flon;
 myArray[2] = gps.f_course();  // heading
 myArray[5] = gps.f_speed_kmph(); // speed

I suspect your array is an integer array so when you store a floating-point value in it the fractional part is thrown away.

You can store some of the fractional digits if you multiply by a power of 10. For example:

 myArray[2] = gps.f_course() * 100;  // heading with 2 fractional digits
 myArray[5] = gps.f_speed_kmph() * 10; // speed with 1 fractional digit

Serial.print( myArray[2] / 100.0);
Serial.print(myArray[5] / 10.0);

johnwasser:

 myArray[2] = gps.f_course();  // heading

myArray[5] = gps.f_speed_kmph(); // speed




I suspect your array is an integer array so when you store a floating-point value in it the fractional part is thrown away.

You can store some of the fractional digits if you multiply by a power of 10. For example:



myArray[2] = gps.f_course() * 100;  // heading with 2 fractional digits
myArray[5] = gps.f_speed_kmph() * 10; // speed with 1 fractional digit

Serial.print( myArray[2] / 100.0);
Serial.print(myArray[5] / 10.0);

I tried that and still got only two digits.

Here's the TinyGPS example code that prints out the correct values. It prints the course heading using

print_float(gps.f_course(), TinyGPS::GPS_INVALID_F_ANGLE, 7, 2);

#include <SoftwareSerial.h>

#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 3(rx) and 4(tx).
*/

TinyGPS gps;
SoftwareSerial 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(115200);
  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;
}

It has the print_float toward the bottom that's used to print out the correct value. How it works is a bit beyond my programming knowledge.

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

The Print::print() method used to not have good support for printing floating point values to any number of decimal places. Now, it does. So, that function is not really needed.

You have not answered the question about what type myArray is, nor have you shown how you are trying to print the values in the array.

PaulS:
The Print::print() method used to not have good support for printing floating point values to any number of decimal places. Now, it does. So, that function is not really needed.

You have not answered the question about what type myArray is, nor have you shown how you are trying to print the values in the array.

Thanks! This is a dumb mistake I've spent hours on.

I had:

int myArray[10];

I change it to

float myArray[10];

And everything works great now!

This is a dumb mistake I've spent hours on.

I'll bet that's a mistake you'll never make again.