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 thoughts on “Serial GPS: Find Distance Between Two Points”

  1. 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.

    1. 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

Your email address will not be published. Required fields are marked *

Invent the future.