Average coordinate points

Hi I built a reverse geo-cache box and to get the best accuracy I want to take the average of the incoming coordinates. How would I do this?

/*
 The circuit:
 * LCD RS pin to digital pin 9
 * LCD Enable pin to digital pin 8
 * LCD D4 pin to digital pin 7
 * LCD D5 pin to digital pin 6
 * LCD D6 pin to digital pin 5
 * LCD D7 pin to digital pin 4
 * LCD R/W pin to ground
 * 10K resistor:
 * ends to +5V and ground
 * wiper to LCD VO pin (pin 3)
 
 http://www.arduino.cc/en/Tutorial/LiquidCrystal
 */

// include the library code:
#include <LiquidCrystal.h>
#include <math.h>

//#include <Servo.h> 
#include <PWMServo.h> 

#include <SoftwareSerial.h>
#include <TinyGPS.h>
// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(9, 8, 7, 6, 5, 4);
#define RXPIN 2
#define TXPIN 3
#define GPSBAUD 4800
TinyGPS gps;
SoftwareSerial uart_gps(RXPIN, TXPIN);
void getgps(TinyGPS &gps);

const float pi = 3.14;
float targetlat = rad(39.52);
float targetlong = rad(-104.92139);

int off = 11;

PWMServo myservo;
void setup() {
  myservo.attach(SERVO_PIN_B);
myservo.write(100);
pinMode(off, OUTPUT);
  // set up the LCD's number of columns and rows: 
  lcd.begin(16, 2);
  //Serial.begin(115200);
  uart_gps.begin(GPSBAUD);
  // Print a message to the LCD.
  lcd.print("waiting for lock");
  delay(1000);

}

void loop() {

  if(uart_gps.available())     // While there is data on the RX pin...
  {

    int c = uart_gps.read();    // load the data into a variable...
    if(gps.encode(c))      // if there is a new valid sentence...
    {
      lcd.clear();
      getgps(gps);         // then grab the data.
      delay(500);
    }

  }
}

void getgps(TinyGPS &gps)
{
  // To get all of the data into varialbes that you can use in your code, 
  // all you need to do is define variables and query the object for the 
  // data. To see the complete list of functions see keywords.txt file in 
  // the TinyGPS and NewSoftSerial libs.

  // Define the variables that will be used
  float latitude, longitude;
  // Then call this function
  gps.f_get_position(&latitude, &longitude);

  float lat = rad(latitude);
  float lon = rad(longitude);
  float x = (lon-targetlong)*cos(targetlat);
  float y = lat-targetlat;
  float d = 3959*sqrt(sq(x)+sq(y));
  if(d <= .05)
  {
    lcd.clear();
    lcd.print("Congrats!");
    lcd.setCursor(0,1);
    lcd.print("target reached");
    myservo.write(180);
    while(1)
    {
    }
  }
  // You can now print variables latitude and longitude
  lcd.print("Lat: "); 
  lcd.print(latitude,5); 
  lcd.setCursor(0, 1);
  lcd.print("long: "); 
  lcd.print(longitude,5);

  // Here you can print statistics on the sentences.
  unsigned long chars;
  unsigned short sentences, failed_checksum;
  gps.stats(&chars, &sentences, &failed_checksum);
  //Serial.print("Failed Checksums: ");Serial.print(failed_checksum);
  //Serial.println(); Serial.println();
  delay(5000);

  lcd.clear();
  lcd.print(d);
  lcd.setCursor(0, 1);
  lcd.print("Miles to target");
  delay(5000);
  lcd.clear();
  lcd.print("Turning off...");
  delay(2500);
digitalWrite(off, HIGH);


}

float rad(float n)
{
  float r = n*(pi/180);
  return r;
}

Add them up and divide by the number of readings I would think.

A question for you. How long does the program stay in this while loop ?

    while(1)
    {
    }

How many points do you have?
Are there outliers? ==> in that case the median might be more appropriate

UKHeliBob:
Add them up and divide by the number of readings I would think.

A question for you. How long does the program stay in this while loop ?

    while(1)

{
    }

It stays in the while loop forever, and well how would I implement a mean or median into my code?

I've tried a up and dividing them with a for loop but I get overflows on the float data type

Are you certain that your math is correct? I'm not.
The TinyGPS library offers this built in function, which seems useful for your purpose.

float TinyGPS::distance_between (float lat1, float long1, float lat2, float long2)
{
// returns distance in meters between two positions, both specified
// as signed decimal-degrees latitude and longitude. Uses great-circle
// distance computation for hypothetical sphere of radius 6372795 meters

hadjisra:
I've tried a up and dividing them with a for loop but I get overflows on the float data type

Can you post your code?

/*
 The circuit:
 * LCD RS pin to digital pin 9
 * LCD Enable pin to digital pin 8
 * LCD D4 pin to digital pin 7
 * LCD D5 pin to digital pin 6
 * LCD D6 pin to digital pin 5
 * LCD D7 pin to digital pin 4
 * LCD R/W pin to ground
 * 10K resistor:
 * ends to +5V and ground
 * wiper to LCD VO pin (pin 3)
 
 http://www.arduino.cc/en/Tutorial/LiquidCrystal
 */

// include the library code:
#include <LiquidCrystal.h>
#include <math.h>

//#include <Servo.h> 
#include <PWMServo.h> 

#include <SoftwareSerial.h>
#include <TinyGPS.h>
// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(9, 8, 7, 6, 5, 4);
#define RXPIN 2
#define TXPIN 3
#define GPSBAUD 4800
TinyGPS gps;
SoftwareSerial uart_gps(RXPIN, TXPIN);
void getgps(TinyGPS &gps);

const float pi = 3.14;
float targetlat = rad(39.52);
float targetlong = rad(-104.92139);
float newlat = 0;
float newlon = 0;
int off = 11;

PWMServo myservo;
void setup() {
  myservo.attach(SERVO_PIN_B);
myservo.write(100);
pinMode(off, OUTPUT);
  // set up the LCD's number of columns and rows: 
  lcd.begin(16, 2);
  //Serial.begin(115200);
  uart_gps.begin(GPSBAUD);
  // Print a message to the LCD.
  lcd.print("waiting for lock");
  delay(1000);

}

void loop() {

  if(uart_gps.available())     // While there is data on the RX pin...
  {

    int c = uart_gps.read();    // load the data into a variable...
    if(gps.encode(c))      // if there is a new valid sentence...
    {
      lcd.clear();
      getgps(gps);         // then grab the data.
      delay(500);
    }

  }
}

void getgps(TinyGPS &gps)
{
  // To get all of the data into varialbes that you can use in your code, 
  // all you need to do is define variables and query the object for the 
  // data. To see the complete list of functions see keywords.txt file in 
  // the TinyGPS and NewSoftSerial libs.

  // Define the variables that will be used
  float latitude, longitude;
  gps.f_get_position(&latitude, &longitude);
  /* THIS WAS THE SECTION I WAS USING TO FIND THE MEAN
  lcd.clear();
  for(int mean = 0; mean < 6; mean++){ 
  lcd.print("processing data");// Then call this function
  gps.f_get_position(&latitude, &longitude);
    unsigned long chars;
  unsigned short sentences, failed_checksum;
  gps.stats(&chars, &sentences, &failed_checksum);
  float newlat = newlat + latitude;
  float newlon = newlon + longitude;
  delay(1);
  }
  newlat = newlat/5;
  newlon = newlon/5;
  */
  float lat = rad(latitude);
  float lon = rad(longitude);
  float x = (lon-targetlong)*cos(targetlat);
  float y = lat-targetlat;
  float d = 3959*sqrt(sq(x)+sq(y));
  if(d <= .05)
  {
    lcd.clear();
    lcd.print("Congrats!");
    lcd.setCursor(0,1);
    lcd.print("target reached");
    myservo.write(180);
    while(1)
    {
    }
  }
  // You can now print variables latitude and longitude
  lcd.clear();
  lcd.print("Lat: "); 
  lcd.print(latitude,5); 
  lcd.setCursor(0, 1);
  lcd.print("long: "); 
  lcd.print(longitude,5);

  // Here you can print statistics on the sentences.
unsigned long chars;
  unsigned short sentences, failed_checksum;
  gps.stats(&chars, &sentences, &failed_checksum);
  //Serial.print("Failed Checksums: ");Serial.print(failed_checksum);
  //Serial.println(); Serial.println();
  delay(5000);

  lcd.clear();
  lcd.print(d);
  lcd.setCursor(0, 1);
  lcd.print("Miles to target");
  delay(5000);
  lcd.clear();
  lcd.print("Turning off...");
  delay(2500);
digitalWrite(off, HIGH);


}

float rad(float n)
{
  float r = n*(pi/180);
  return r;
}

jremington:
Are you certain that your math is correct? I'm not.

My math is semi-sound with a mock haversine formula. What formula does tiny gps use for its distance calculations?However, I still need to fix the mean problem.

What formula does tiny gps use for its distance calculations?

It uses the correct formula for the great circle distance on a perfect sphere.

Thank you. But how would I collect multiple coordinate points and average them?

I see a couple of problems, but nothing that would cause an overflow.

  1. You keep redeclaring newlat and newlon. These should be declared outside the for loop.
    2 You are adding 6 readings, then dividing by 5.

hadjisra:

  for(int mean = 0; mean < 6; mean++){ 

lcd.print("processing data");// Then call this function
  gps.f_get_position(&latitude, &longitude);
    unsigned long chars;
  unsigned short sentences, failed_checksum;
  gps.stats(&chars, &sentences, &failed_checksum);
  float newlat = newlat + latitude;
  float newlon = newlon + longitude;
  delay(1);
  }
  newlat = newlat/5;
  newlon = newlon/5;

I believe that one of the many problems with the code you posted lies in lines like this:

  float newlat = newlat + latitude;
  float newlon = newlon + longitude;

The keyword "float" is used to define a floating point variable. In previous lines you already defined newlat and newlon as float variables. I'm not quite sure what the Arduino version of gcc does here, but it is unlikely to work as you think it should. It certainly doesn't work correctly for the compilers I normally use.

Instead try

  newlat += latitude;
  newlon += longitude;

lar3ry:
2 You are adding 6 readings, then dividing by 5.

the for loop is less than 6 so I think it makes five readings but no the six one because it is not equal to or less than

hadjisra:

the for loop is less than 6 so I think it makes five readings but no the six one because it is not equal to or less than
[/quote]

You think so, but that turns out to be untrue.

for(int mean = 0; mean < 6; mean++){

So, mean counts 0 1 2 3 4 5

Count 'em. Rethink. Correct your code. You're welcome.