Understanding GPS (TinyGPS++) commands .isValid and if (millis() version

Hi

im new to Arduino and im trying to make a GPS. im useing the TinyGPS++ library (tested others, liked this best) so far all is going good. im getting the values i want.

im checking other project codes useing TinyGPS and I can see they are useing the commands i dont fully understand. and i would really like to understand them fully before I use them myself. they are also without comment // so no explanation.

So if someone could please tell me (in an easy language since im new to this) what they mean\do.
These codes can also be found in the TinyGPS++ example : FullExample

  1. if (millis() > 5000 && gps.charsProcessed() < 10)
  2. gps.location.isValid(), 11, 6);
  3. gps.location.isValid(), 12, 6);

number 2 and 3 its the .isValid i dont understand. can also be found more places in the code.

here is the FullExample code for TinyGPS++

#include <TinyGPS++.h>
#include <SoftwareSerial.h>
/*
   This sample code demonstrates the normal use of a TinyGPS++ (TinyGPSPlus) 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).
*/
static const int RXPin = 8, TXPin = 9;
static const uint32_t GPSBaud = 9600;

// The TinyGPS++ object
TinyGPSPlus gps;

// The serial connection to the GPS device
SoftwareSerial ss(RXPin, TXPin);

void setup()
{
  Serial.begin(9600);
  ss.begin(GPSBaud);

  Serial.println(F("FullExample.ino"));
  Serial.println(F("An extensive example of many interesting TinyGPS++ features"));
  Serial.print(F("Testing TinyGPS++ library v. ")); Serial.println(TinyGPSPlus::libraryVersion());
  Serial.println(F("by Mikal Hart"));
  Serial.println();
  Serial.println(F("Sats HDOP  Latitude   Longitude   Fix  Date       Time     Date Alt    Course Speed Card  Distance Course Card  Chars Sentences Checksum"));
  Serial.println(F("           (deg)      (deg)       Age                      Age  (m)    --- from GPS ----  ---- to London  ----  RX    RX        Fail"));
  Serial.println(F("----------------------------------------------------------------------------------------------------------------------------------------"));
}

void loop()
{
  static const double LONDON_LAT = 51.508131, LONDON_LON = -0.128002;

  printInt(gps.satellites.value(), gps.satellites.isValid(), 5);
  printFloat(gps.hdop.hdop(), gps.hdop.isValid(), 6, 1);
  printFloat(gps.location.lat(), gps.location.isValid(), 11, 6);
  printFloat(gps.location.lng(),gps.location.isValid(), 12, 6);
  printInt(gps.location.age(), gps.location.isValid(), 5);
  printDateTime(gps.date, gps.time);
  printFloat(gps.altitude.meters(), gps.altitude.isValid(), 7, 2);
  printFloat(gps.course.deg(), gps.course.isValid(), 7, 2);
  printFloat(gps.speed.kmph(), gps.speed.isValid(), 6, 2);
  printStr(gps.course.isValid() ? TinyGPSPlus::cardinal(gps.course.deg()) : "*** ", 6);

  unsigned long distanceKmToLondon =
    (unsigned long)TinyGPSPlus::distanceBetween(
      gps.location.lat(),
      gps.location.lng(),
      LONDON_LAT, 
      LONDON_LON) / 1000;
  printInt(distanceKmToLondon, gps.location.isValid(), 9);

  double courseToLondon =
    TinyGPSPlus::courseTo(
      gps.location.lat(),
      gps.location.lng(),
      LONDON_LAT, 
      LONDON_LON);

  printFloat(courseToLondon, gps.location.isValid(), 7, 2);

  const char *cardinalToLondon = TinyGPSPlus::cardinal(courseToLondon);

  printStr(gps.location.isValid() ? cardinalToLondon : "*** ", 6);

  printInt(gps.charsProcessed(), true, 6);
  printInt(gps.sentencesWithFix(), true, 10);
  printInt(gps.failedChecksum(), true, 9);
  Serial.println();
  
  smartDelay(1000);

 if (millis() > 5000 && gps.charsProcessed() < 10)
    Serial.println(F("No GPS data received: check wiring"));
}

// This custom version of delay() ensures that the gps object
// is being "fed".
static void smartDelay(unsigned long ms)
{
  unsigned long start = millis();
  do 
  {
    while (ss.available())
      gps.encode(ss.read());
  } while (millis() - start < ms);
}

static void printFloat(float val, bool valid, int len, int prec)
{
  if (!valid)
  {
    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 printInt(unsigned long val, bool valid, int len)
{
  char sz[32] = "*****************";
  if (valid)
    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 printDateTime(TinyGPSDate &d, TinyGPSTime &t)
{
  if (!d.isValid())
  {
    Serial.print(F("********** "));
  }
  else
  {
    char sz[32];
    sprintf(sz, "%02d/%02d/%02d ", d.month(), d.day(), d.year());
    Serial.print(sz);
  }
  
  if (!t.isValid())
  {
    Serial.print(F("******** "));
  }
  else
  {
    char sz[32];
    sprintf(sz, "%02d:%02d:%02d ", t.hour(), t.minute(), t.second());
    Serial.print(sz);
  }

  printInt(d.age(), d.isValid(), 5);
  smartDelay(0);
}

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

gps.location.isValid()

Is the GPS location valid ?

Or "Is the GPS producing good valid data or just a pile of rubbish"

The 'printFloat()' function uses the value of the second argument (true or false) to

artiskri:

  1. if (millis() > 5000 && gps.charsProcessed() < 10)
  2. gps.location.isValid(), 11, 6);
  3. gps.location.isValid(), 12, 6);

number 2 and 3 its the .isValid i dont understand. can also be found more places in the code.

#1: "if (the sketch has been running for at least five seconds AND we have received fewer than ten characters from the GPS) display "No GPS data received: check wiring". It's warning displayed if the GPS is not producing data.
#2 and #3: If 'gps.location.isValid()' returns 'false', fill the field with '***********' rather than using the invalid data.

when in doubt, pop the hood and eyeball the engine:

from TinyGPS++.h:

struct TinyGPSDate
{
   friend class TinyGPSPlus;
public:
   bool isValid() const       { return valid; }
   bool isUpdated() const     { return updated; }
   uint32_t age() const       { return valid ? millis() - lastCommitTime : (uint32_t)ULONG_MAX; }

   uint32_t value()           { updated = false; return date; }
   uint16_t year();
   uint8_t month();
   uint8_t day();

   TinyGPSDate() : valid(false), updated(false), date(0)
   {}

isValid & isUpdated are variables from the TinyGPSPlus library. Boolean values, 1 = true & 0 = false

Thanks alot I do understand alot more now.

Last thing in gps.location.isValid(), 11, 6);
the to numbers. i understand if I use one number will return the vaule with ,x desimals but what happens with 2 numbers?

gps.location.isValid(), 11, 6);

That statement is malformed and incomplete. The isValid() method takes no arguments. The numbers that follow it are arguments to some other function that you haven't shared with us.

I believe that questions 2 and 3 are calls to this function...

static void printFloat(float val, bool valid, int len, int prec)

This prints a specific length, adding spaces as required. prec, or precision, is the number of decimal places.

If valid is false,then it prints ***** instead, but keeps the length.

Float is what C calls a decimal number. Look up a reference on floating-point maths. It is actually quite tricky as the floating point representation has some unexpected limitations. It is also very slow on an Arduino and you will sometimes see some creative use of integers just to make the program run fast enough.