Serial GPS: Find Distance Between Two Points

This is some code I wrote for the reverse geocache project. It uses a LS20031 GPS module. That is attached the the TX RX lines of an ATMEGA328p. This sketch also utilizes the TinyGPS Library.

 

// get distance example
// using TinyGPS
// Written by Bill Heaster


#include <TinyGPS.h> //include for the GPS handeling.

// These would be saved in the EEPROM for your GeoCache
// For this example we will name them as const variables
const long TargetLat = 43164622;
const long TargetLon = 77609596;

TinyGPS gps;



struct //structure to organize our variables.
{
    float miles;
    float feet;
    float km;
}distance;

void setup()
{
    Serial.begin(9600); //start serial for the GPS module
}

void loop()
{
    if(isData())
    {
        getDistance(gps,TargetLat, TargetLon);
    }
    Serial.print("Miles: ");
    Serial.println(distance.miles);

    Serial.print("KM: ");
    Serial.println(distance.km);

    Serial.print("Feet: ");
    Serial.println(distance.feet);
}

bool isData() // feed the gps object with serial info and check if we are recieving a valid packet
{
  while (Serial.available())
  {
    if (gps.encode(Serial.read()))
      return true;
  }
  return false;
}

void getDistance(TinyGPS &gps, long targetLat, long targetLon)
{
  long lat, lon;
  unsigned long age;
  float latRad, lonRad;
  float flat, flon;
  float tlat, tlon;
  float tlatRad, tlonRad;
  float midLat, midLon;
  int samples=0;
  //----------------------------------------

  for (samples; samples< 20; samples++) //collect a few samples to make the data more accurate.Not sure if this is the best soloution.
  {
    gps.get_position(&lat, &lon, &age); //get the coords from the tinygps object
    if(age >= 5000) //if the data is old
    {
      delay(3000);//wait before we make another attempt
      isData(); //refresh the GPS object.
    }
    else
    {
        samples = 20;
    }
  }

  //convert to decimal degree
  flat = lat /100000.0;
  flon = lon /100000.0;
  tlat = targetLat / 100000.0;
  tlon = targetLon / 100000.0;

  //convert decimal degree into radian
  latRad = flat * 0.017453293;
  lonRad = flon * 0.017453293;
  tlatRad = tlat * 0.017453293;
  tlonRad = tlon * 0.017453293;

  midLat = tlatRad - latRad;
  midLon = tlonRad - lonRad;

  //Calculate the distance in KM
  float latSin = sin((latRad - tlatRad)/2);
  float lonSin = sin((lonRad - tlonRad)/2);
  distance.km = 2 * asin(sqrt((latSin*latSin) + cos(latRad) * cos(tlatRad) * (lonSin * lonSin)));
  distance.km = distance.km * 6371;



  //convert to miles
  distance.miles = distance.km * 0.621371192;
  distance.feet = distance.miles *5280;
  isData(); //refresh GPS during long calculations

  // --------------------------------

  }



2 comments

  • Hi, awesome code. I`m using Leonardo with GPS data logger; i`m wondering if this code works for this equipment?
    My application is that i have to save on the SD Card the distance and the time (begging and ending time).
    Best Regards,
    Carlos Morera.

    • TheCreator

      Thank you sir. This code is used on the arduino platform. If you are looking at something more portable i have a library i wrote in C here. If the leonardo gives you raw packets ($GPRMC,hhmmss.ss,A,llll.ll,a,yyyyy.yy,a,x.x,x.x,ddmmyy,x.x,a*hh) then the C library will work for you.

Leave a Reply