Measuring the Distance of GPS using arduino..

Hi,

Who among here have tried measuring the before and after distance traveled using gps? I'm going to use the code from TinyGPS library's distance_between command without constant value of latitude and longitude,

like this:

static const float LONDON_LAT = 51.508131, LONDON_LON = -0.128002

I want to see that the first GPS latitude and longitude results is used as reference point.

How will I apply it on my code so that I could be able to get the distance I traveled? Please help me.

#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 = 4, TXPin = 3;
     static const uint32_t GPSBaud = 4800;

      // The TinyGPS++ object
    TinyGPSPlus gps;

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

    void setup()
    {
     Serial.begin(115200);
     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);
      printInt(gps.hdop.value(), gps.hdop.isValid(), 5);
      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.value()) : "*** ", 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);
}

THANKS :slight_smile:

Did you know that when you're not moving, the GPS coordinates will wander around your actual location? You will accumulate "distance" even while you're sitting still.

GPS isn't good for measuring distances less than a km or so, but it depends on the accuracy of the locations you can get. With bad reception, your location can wander by 100m. With 2 locations you could calculate a distance, but it could be off by 200m.

With good reception and averaging of multiple location reports while motionless, you can decrease the error to a few meters or less. The longer you sit there, the better the average becomes.

1) Do you have a way of detecting motion? (The GPS speed isn't good for this, for the same reasons.)

2) What range of distances do you want to measure? Over what time period?

3) Do you just want the "as the crow flies" distance between a starting and ending point, or does the distance accumulate as you move?

Cheers,
/dev

@/dev
Thank you for the ideas. :slight_smile:

  1. Do you have a way of detecting motion? (The GPS speed isn't good for this, for the same reasons.)

I also have IMU for detecting motion, but for the distance we will use GPS.

  1. What range of distances do you want to measure? Over what time period?

Short range (few meters) and long range distance(yards or miles). No certain period of time, until you stop.

  1. Do you just want the "as the crow flies" distance between a starting and ending point, or does the distance accumulate as you move?

I want the distance to accumulate as I move.

Hi -dev,
I realize this is an old post but I came across it in my search for answers regarding the GPS accumulating distance.
You mention that "With good reception and averaging of multiple location reports while motionless, you can decrease the error to a few meters or less. The longer you sit there, the better the average becomes."

I tried applying averaging but I was unable to get it to work.

How did you do it?

Cheers
Lawrence

I tried applying averaging but I was unable to get it to work.

What did not work?

The usual approach is to add up N latitude numbers, N longitude numbers, and divide each sum by N.

I tried applying averaging but I was unable to get it to work.

NeoGPS comes with an averaging example: NMEAaverage.ino. It shows how to use the high-precision long integer forms of the latitude and longitude.

Like jremington said, you could add up N floating-point values and divide by N to get the average of N samples. But to use the high-precision long integers, you have to take a slightly different approach:

  1. Get FIRST location.

  2. When the NEXT location is ready, subtract it from the FIRST location to get the delta (offset).

  3. Add delta to a running accumulation of deltas (N deltas)

  4. Divide the sum of deltas by the number of deltas accumulated (divide by N) to get an average delta.

  5. Add the average delta to the FIRST location to get the current AVERAGE LOCATION.

It has to use deltas because adding N latitudes would overflow the longer integer forms. Adding the N relatively small deltas will not cause an overflow.

Cheers,
/dev

Hello -dev, I would like to explore your NeoGPS, do you have sample sketches working with long integer coordinates to calculate the distance between? I have a problem with TinyGPS's distance_between function as it only accepts float values. When I attempt to insert my LoRa p2p received string to float lat2(6) & lon2(6) variables it returns the following error message:

exit status 1
no matching function for call to 'TinyGPS::distance_between(long int)'

Will your NeoGPS allow me to use long integer's in a distance between function?

Thanking you in advance,

Do_Not_Give_Uo

lora_p2p_tx_rx_with_parsing_dist_between_1.ino (14.6 KB)

The NeoGPS distance functions will use the internal long integer values from a location. See the example NMEAdistance.INO.

With NeoGPS, you don't pass the separate floating point lat/lon values to a function. You use two Location_t structures, which can accept the long integer values:

void foo( long latitude, long longitude ) // from LoRa?
{
  NeoGPS::Location_t otherLocation;  // structure containing a lat *and* lon
  otherLocation.lat( latitude );     // assign long ints
  otherLocation.lon( longitude );

  float distance = fix.location.DistanceKm( otherLocation ); // uses internal long ints to calculate distance

Show your code for a better answer.