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;
}
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
/*
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.
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.