Hardware components | ||||||
![]() |
| × | 4 | |||
![]() |
| × | 4 | |||
![]() |
| × | 1 | |||
![]() |
| × | 4 | |||
Software apps and online services | ||||||
![]() |
|
Intro:
Complex systems often require calculations involving distances and relative positions in space. A computer on it's own doesn't know either its location or it's distance to another unit on its network. For this the computers need GPS receivers and bit of code to figure out how far apart they are. One obvious example of this is in the military where one computer(a designator) is used to guide another computer aboard a jet, rocket, or artillery to help it travel and/or aim precisely. Without the devices known where they are relative to one another this is impossible. However there are many scientific and civilian uses for this technology like creating a grid of non-static sensors and still being able to gather and analyze location specific data. This could be used for weather balloons, buoys, or used to find and recover lost and/or dispersed sensors. Whatever the purpose location and distance are important for real word sensor data and analytics.
For IOT Project 048 we decided to see if we could build a network that performed this relative geolocation. For this we used generic Arduino GPS modules interfaced with Particle Argon computers. The Argons pass their GPS data over the internet and use what's known as the Great Circle Equation or the Great Circle Distance to determine and log how far apart the units are in space over time. It should be noted that if too close the GPS and Argon will interfere. They must be placed about 1 foot apart at least in order for the GPS to achieve a stable satellite link.
Link The Great Circle Equation Wiki: https://en.wikipedia.org/wiki/Great-circle_distance
How it works:
First our variables are initialized in the setup. Then in the loop we initialize our GPS serial stream and parse the data using the GPS libraries listed at the top of each code (#include <TinyGPS++/TinyGPS++.h> -and- #include <Particle-GPS.h>. These libraries include example code you can pull from as we did.
Next you'll want to store each units relative latitude and longitude in unique variables. It should be noted that while it appears like a decimal (e.g. Lat = 3518.0371), but this is actually degrees and minutes in decimal in the format of ddmm.mmmm. Meaning the String pulled from the GPS stream in the previous example indicates 35 degrees and 18.0371 minutes of angle. There is an algorithm in the code GPS_B_Math.ino that pareses this data into floating point and integer values and converts it to decimal degrees of angle only. This is important because next we must convert those degrees into radians in order to plug them into the Great Circle Distance Equation. This equations is run three times outputting the distances BA (unit B to unit A), BC (unit B to unit C), and BD (unit B to unit D) in meters which are graphed using ThinkSpeak.
The graph of the distance between modules A and B is displayed on this website. The readings of 9 million indicate disconnect events that occurred when moving the modules around on the school network
Thingspeak: https://thingspeak.com/channels/920765/private_show
Youtube:
// This #include statement was automatically added by the Particle IDE.
#include <Particle-GPS.h>
// This #include statement was automatically added by the Particle IDE.
#include <TinyGPS++.h>
//IOT Project 048: initialize lattitude and longitude string variables
String Lat_A;
String Lon_A;
// ***
// *** Create a Gps instance. The RX an TX pins are connected to
// *** the TX and RX pins on the electron (Serial1).
// ***
Gps _gps = Gps(&Serial1);
// ***
// *** Create a timer that fires every 1 ms to capture
// *** incoming serial port data from the GPS.
// ***
Timer _timer = Timer(1, onSerialData);
void setup()
{
delay(2000);
// ***
// *** Initialize the USB Serial for debugging.
// ***
Serial.begin();
Serial.println("Initializing...");
// ***
// *** Initialize the GPS.
// ***
_gps.begin(9600);
// ***
// *** Start the timer.
// ***
_timer.start();\
//IOT Project 048: assign Lat and Lon as Particle cloud variables
Particle.variable("Lat_A", Lat_A);
Particle.variable("Lon_A", Lon_A);
}
void onSerialData()
{
_gps.onSerialData();
}
void loop()
{
// ***
// *** Get the Antenna Status ($PGTOP).
// ***
Pgtop pgtop = Pgtop(_gps);
if (pgtop.parse())
{
Serial.println("1) Antenna Status ($PGTOP)");
Serial.println("======================================================");
Serial.print("Command ID: "); Serial.println(pgtop.commandId);
Serial.print("Antenna Status: "); Serial.println(pgtop.reference);
Serial.println("");
}
// ***
// *** Get the Global Positioning System Fixed Data ($GPGGA).
// ***
Gga gga = Gga(_gps);
if (gga.parse())
{
Serial.println("2) Global Positioning System Fixed Data ($GPGGA)");
Serial.println("======================================================");
Serial.print("UTC Time: "); Serial.println(gga.utcTime);
Serial.print("Latitude: "); Serial.println(gga.latitude);
Serial.print("North/SouthIndicator: "); Serial.println(gga.northSouthIndicator);
Serial.print("Longitude: "); Serial.println(gga.longitude);
Serial.print("East/WestIndicator: "); Serial.println(gga.eastWestIndicator);
Serial.print("Position Fix Indicator: "); Serial.println(gga.positionFixIndicator);
Serial.print("Satellites Used: "); Serial.println(gga.satellitesUsed);
Serial.print("Horizontal Dilution of Precision: "); Serial.println(gga.hdop);
Serial.print("Altitude: "); Serial.print(gga.altitude); Serial.print(" "); Serial.println(gga.altitudeUnit);
Serial.print("Geoidal Separation: "); Serial.print(gga.geoidalSeparation); Serial.print(" "); Serial.println(gga.geoidalSeparationUnit);
Serial.print("Age of Diff. Corr.: "); Serial.println(gga.ageOfDiffCorr);
Serial.println("");
//IOT Project 048: Update Particle variables with GPS fix data and publish to the cloud.
Lat_A = gga.latitude;
Lon_A= gga.longitude;
//Particle.publish("Latitude_A", Lat_A);
//Particle.publish("Longitude_A", Lon_A);
}
// ***
// *** Get the Recommended Minimum Navigation Information ($GPRMC).
Rmc rmc = Rmc(_gps);
if (rmc.parse())
{
Serial.println("3) Recommended Minimum Navigation Information ($GPRMC)");
Serial.println("======================================================");
Serial.print("UTC Time: "); Serial.println(rmc.utcTime);
Serial.print("Latitude: "); Serial.println(rmc.latitude);
Serial.print("North/SouthIndicator: "); Serial.println(rmc.northSouthIndicator);
Serial.print("Longitude: "); Serial.println(rmc.longitude);
Serial.print("East/WestIndicator: "); Serial.println(rmc.eastWestIndicator);
Serial.print("Speed Over Ground: "); Serial.println(rmc.speedOverGround);
Serial.print("Course Over Ground: "); Serial.println(rmc.courseOverGround);
Serial.print("Date: "); Serial.println(rmc.date);
Serial.print("Magnetic Variation: "); Serial.print(rmc.magneticVariation); Serial.print(" "); Serial.println(rmc.magneticVariationDirection);
Serial.print("Mode: "); Serial.println(rmc.mode);
Serial.println("");
Lat_A = rmc.latitude;
Lon_A = rmc.longitude;
//Particle.publish("Latitude_A", Lat_A);
//Particle.publish("Longitude_A", Lon_A);
}
delay(1000);
String data = String(10);
// Trigger the webhook
Particle.publish("Lat_A", Lat_A);
// Trigger the webhook
Particle.publish("Lon_A", Lon_A);
//Particle.subscribe("Total", test, MY_DEVICES);
// Wait 60 seconds
delay(30000);
}
int i = 0;
void test(const char *event, const char *data){
i++;
Serial.print(i);
Serial.print(event);
Serial.print(", data: ");
if (data)
Serial.println(data);
else
Serial.println("NULL");
}
#include <TinyGPS++/TinyGPS++.h>
// This #include statement was automatically added by the Particle IDE.
#include <libfixmath.h>
// This #include statement was automatically added by the Particle IDE.
#include <Particle-GPS.h>
#include <math.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
String Lat_A;
String Lon_A;
String Lat_C;
String Lon_C;
String Lat_D;
String Lon_D;
//Cod for GPS Module B
//IOT Project 048: initialize lattitude and longitude string variables
String Lat_B;
String Lon_B;
float Lat_Bd;
float Lon_Bd;
float radians = (M_PI/180);
#define sq(x) ((x)*(x))
float BA;
float BC;
float BD;
// String lata = *Lat_A;
//String lona = *Lon_A;
// String latc = *Lat_C;
// String lonc = *Lon_C;
//String latd = *Lat_D;
//String lond = *Lon_D;
float Btest;
String Lat_Bt;
// ***
// *** Create a Gps instance. The RX an TX pins are connected to
// *** the TX and RX pins on the electron (Serial1).
// ***
Gps _gps = Gps(&Serial1);
// ***
// *** Create a timer that fires every 1 ms to capture
// *** incoming serial port data from the GPS.
// ***
Timer _timer = Timer(1, onSerialData);
void setup()
{
delay(2000);
// ***
// *** Initialize the USB Serial for debugging.
// ***
Serial.begin();
Serial.println("Initializing...");
// ***
// *** Initialize the GPS.
// ***
_gps.begin(9600);
// ***
// *** Start the timer.
// ***
_timer.start();\
//IOT Project 048: assign Lat and Lon as Particle cloud variables
// Particle.variable("BA", double(BA));
// Particle.variable("BC", double(BC));
// Particle.variable("BD", double(BD));
Particle.variable("Lat_B", Lat_B);
Particle.variable("Lon_B", Lon_B);
Particle.variable("Lat_A", Lat_A);
Particle.variable("Lon_A", Lon_A);
Particle.variable("Lat_C", Lat_C);
Particle.variable("Lon_C", Lon_C);
Particle.variable("Lat_D", Lat_D);
Particle.variable("Lon_D", Lon_D);
//Particle.variable("Lat_Bd", double(Lat_Bd));
//Particle.variable("Lon_Bd", double(Lon_Bd));
//Particle.variable("Btest", String(Btest));
Particle.subscribe("Lat_A", lata, ALL_DEVICES);
Particle.subscribe("Lon_A", lona, ALL_DEVICES);
Particle.subscribe("Lat_C", latc, ALL_DEVICES);
Particle.subscribe("Lon_C", lonc, ALL_DEVICES);
Particle.subscribe("Lat_D", latd, ALL_DEVICES);
Particle.subscribe("Lon_D", lond, ALL_DEVICES);
}
void onSerialData()
{
_gps.onSerialData();
}
void loop()
{
Particle.subscribe("Lat_A", lata, ALL_DEVICES);
Particle.subscribe("Lon_A", lona, ALL_DEVICES);
Particle.subscribe("Lat_C", latc, ALL_DEVICES);
Particle.subscribe("Lon_C", lonc, ALL_DEVICES);
Particle.subscribe("Lat_D", latd, ALL_DEVICES);
Particle.subscribe("Lon_D", lond, ALL_DEVICES);
// ***
// *** Get the Antenna Status ($PGTOP).
// ***
Pgtop pgtop = Pgtop(_gps);
if (pgtop.parse())
{
Serial.println("1) Antenna Status ($PGTOP)");
Serial.println("======================================================");
Serial.print("Command ID: "); Serial.println(pgtop.commandId);
Serial.print("Antenna Status: "); Serial.println(pgtop.reference);
Serial.println("");
}
// ***
// *** Get the Global Positioning System Fixed Data ($GPGGA).
// ***
Gga gga = Gga(_gps);
if (gga.parse())
{
Serial.println("2) Global Positioning System Fixed Data ($GPGGA)");
Serial.println("======================================================");
Serial.print("UTC Time: "); Serial.println(gga.utcTime);
Serial.print("Latitude: "); Serial.println(gga.latitude);
Serial.print("North/SouthIndicator: "); Serial.println(gga.northSouthIndicator);
Serial.print("Longitude: "); Serial.println(gga.longitude);
Serial.print("East/WestIndicator: "); Serial.println(gga.eastWestIndicator);
Serial.print("Position Fix Indicator: "); Serial.println(gga.positionFixIndicator);
Serial.print("Satellites Used: "); Serial.println(gga.satellitesUsed);
Serial.print("Horizontal Dilution of Precision: "); Serial.println(gga.hdop);
Serial.print("Altitude: "); Serial.print(gga.altitude); Serial.print(" "); Serial.println(gga.altitudeUnit);
Serial.print("Geoidal Separation: "); Serial.print(gga.geoidalSeparation); Serial.print(" "); Serial.println(gga.geoidalSeparationUnit);
Serial.print("Age of Diff. Corr.: "); Serial.println(gga.ageOfDiffCorr);
Serial.println("");
//IOT Project 048: Update Particle variables with GPS fix data and publish to the cloud.
Lat_B = gga.latitude;
Lon_B = gga.longitude;
// Particle.publish("Lattitude_B", Lat_B);
//Particle.publish("Longitude_B", Lon_B);
}
// ***
// *** Get the Recommended Minimum Navigation Information ($GPRMC).
Rmc rmc = Rmc(_gps);
if (rmc.parse())
{
Serial.println("3) Recommended Minimum Navigation Information ($GPRMC)");
Serial.println("======================================================");
Serial.print("UTC Time: "); Serial.println(rmc.utcTime);
Serial.print("Latitude: "); Serial.println(rmc.latitude);
Serial.print("North/SouthIndicator: "); Serial.println(rmc.northSouthIndicator);
Serial.print("Longitude: "); Serial.println(rmc.longitude);
Serial.print("East/WestIndicator: "); Serial.println(rmc.eastWestIndicator);
Serial.print("Speed Over Ground: "); Serial.println(rmc.speedOverGround);
Serial.print("Course Over Ground: "); Serial.println(rmc.courseOverGround);
Serial.print("Date: "); Serial.println(rmc.date);
Serial.print("Magnetic Variation: "); Serial.print(rmc.magneticVariation); Serial.print(" "); Serial.println(rmc.magneticVariationDirection);
Serial.print("Mode: "); Serial.println(rmc.mode);
Serial.println("");
Lat_B = rmc.latitude;
Lon_B = rmc.longitude;
Particle.publish("Latitude_B", Lat_B);
Particle.publish("Longitude_B", Lon_B);
}
delay(1000);
float AB = distance(Lat_A, Lon_A, Lat_B, Lon_B);
float CB = distance(Lat_C, Lon_C, Lat_B, Lon_B);
float DB = distance(Lat_D, Lon_D, Lat_B, Lon_B);
Particle.publish("Distance AB: ", String(AB));
Particle.publish("Distance CB: ", String(CB));
Particle.publish("Distance DB: ", String(DB));
// Trigger the webhook
Particle.publish("Distance", String(AB), PRIVATE);
Particle.publish("Distance 2", String(CB), PRIVATE);
// Wait 60 seconds
// Wait 60 seconds
delay(30000);
}
//A Handlers
void lata(const char *event, const char *data)
{
if (data){
Lat_A = data;
Particle.publish("Lat A Heard", Lat_A);
}
else{
Serial.println("NULL");
}
}
void lona(const char *event, const char *data)
{
if (data){
Lon_A = data;
Particle.publish("Lon A Heard", Lon_A);
}
else{
Serial.println("NULL");
}
}
//C Handlers
void latc(const char *event, const char *data)
{
if (data){
Lat_C = data;
Particle.publish("Lat C heard", Lat_C);
}
else{
Serial.println("NULL");
}
}
void lonc(const char *event, const char *data)
{
if (data){
Lon_C = data;
Particle.publish("Lon C heard", Lon_C);
}
else{
Serial.println("NULL");
}
}
//D Handlers
void latd(const char *event, const char *data)
{
if (data){
Lat_D = data;
Particle.publish("Lat D heard", Lat_D);
}
else{
Serial.println("NULL");
}
}
void lond(const char *event, const char *data)
{
if (data){
Lon_D = data;
Particle.publish("Lon D heard", Lon_D);
}
else{
Serial.println("NULL");
}
}
void test(){
//IOT Project 048: Distance between Unit A and Unit B [BA]
// -First convert lat/lon strings into double variables
//For A
float Lat_Ad = Lat_A.toFloat(); //string to float
Lat_Ad = Lat_Ad/100; //float/100 (ddmm.mmmm ---> dd.mmmmmm)
int Lat_Adeg = int(Lat_Ad); //Then int truncates the decimal to leave (dd)
float Lat_Amin = (Lat_Ad - Lat_Adeg)*100; //subtract the int from origional to leave just .mmmmmm, *100 to bring mm.mmmm
Lat_Ad = Lat_Adeg + (Lat_Amin/60);
Particle.publish("Lat_Ad", String(Lat_Ad), PRIVATE);//return decimal degrees = int degrees + (min/60)
float Lon_Ad = Lon_A.toFloat(); //string to float
Lon_Ad = Lon_Ad/100; //float/100 (ddmm.mmmm ---> dd.mmmmmm)
int Lon_Adeg = int(Lon_Ad); //Then int truncates the decimal to leave (dd)
float Lon_Amin = (Lon_Ad - Lon_Adeg)*100; //subtract the int from origional to leave just .mmmmmm, *100 to bring mm.mmmm
Lon_Ad = Lon_Adeg + (Lon_Amin/60); //return decimal degrees = int degrees + (min/60)
//For B
float Lat_Bd = Lat_B.toFloat(); //string to float
//String Lat_bt = "5500";
//Btest = Lat_bt.toFloat();
//Particle.publish("Btest", String(Btest), PRIVATE);
Lat_Bd = Lat_Bd/100; //float/100 (ddmm.mmmm ---> dd.mmmmmm)
int Lat_Bdeg = int(Lat_Bd); //Then int truncates the decimal to leave (dd)
float Lat_Bmin = (Lat_Bd - Lat_Bdeg)*100; //subtract the int from origional to leave just .mmmmmm, *100 to bring mm.mmmm
Lat_Bd = Lat_Bdeg + (Lat_Bmin/60); //return decimal degrees = int degrees + (min/60)
float Lont_Bd = Lon_B.toFloat(); //string to float
Lon_Bd = Lon_Bd/100; //float/100 (ddmm.mmmm ---> dd.mmmmmm)
int Lon_Bdeg = int(Lon_Bd); //Then int truncates the decimal to leave (dd)
float Lon_Bmin = (Lon_Bd - Lon_Bdeg)*100; //subtract the int from origional to leave just .mmmmmm, *100 to bring mm.mmmm
Lon_Bd = Lon_Bdeg + (Lon_Bmin/60); //return decimal degrees = int degrees + (min/60)
//For C
float Lat_Cd =Lat_C.toFloat(); //string to float
Lat_Cd = Lat_Cd/100; //float/100 (ddmm.mmmm ---> dd.mmmmmm)
int Lat_Cdeg = int(Lat_Cd); //Then int truncates the decimal to leave (dd)
float Lat_Cmin = (Lat_Cd - Lat_Cdeg)*100; //subtract the int from origional to leave just .mmmmmm, *100 to bring mm.mmmm
Lat_Cd = Lat_Cdeg + (Lat_Cmin/60); //return decimal degrees = int degrees + (min/60)
float Lon_Cd = Lon_C.toFloat(); //string to float
Lon_Cd = Lon_Cd/100; //float/100 (ddmm.mmmm ---> dd.mmmmmm)
int Lon_Cdeg = int(Lon_Cd); //Then int truncates the decimal to leave (dd)
float Lon_Cmin = (Lon_Cd - Lon_Cdeg)*100; //subtract the int from origional to leave just .mmmmmm, *100 to bring mm.mmmm
Lon_Cd = Lon_Cdeg + (Lon_Cmin/60); //return decimal degrees = int degrees + (min/60)
//For D
float Lat_Dd = Lat_D.toFloat(); //string to float
Lat_Dd = Lat_Dd/100; //float/100 (ddmm.mmmm ---> dd.mmmmmm)
int Lat_Ddeg = int(Lat_Dd); //Then int truncates the decimal to leave (dd)
float Lat_Dmin = (Lat_Dd - Lat_Ddeg)*100; //subtract the int from origional to leave just .mmmmmm, *100 to bring mm.mmmm
Lat_Dd = Lat_Ddeg + (Lat_Dmin/60); //return decimal degrees = int degrees + (min/60)
float Lon_Dd = Lon_D.toFloat(); //string to float
Lon_Dd = Lon_Dd/100; //float/100 (ddmm.mmmm ---> dd.mmmmmm)
int Lon_Ddeg = int(Lon_Dd); //Then int truncates the decimal to leave (dd)
float Lon_Dmin = (Lon_Dd - Lon_Ddeg)*100; //subtract the int from origional to leave just .mmmmmm, *100 to bring mm.mmmm
Lon_Dd = Lon_Ddeg + (Lon_Dmin/60); //return decimal degrees = int degrees + (min/60)
{
// 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.
// Because Earth is no exact sphere, rounding errors may be up to 0.5%.
// Courtesy of Maarten Lamers
//Particle.publish("Lon_Bd", String(Lon_Bd));
//Particle.publish("Lon_Ad", String(Lon_Ad));
float delta = radians*(Lon_Bd-Lon_Ad);
//Particle.publish("Delta", String(delta));
float sdlong = sin(delta);
// Particle.publish("sdlong", String(sdlong));
float cdlong = cos(delta);
// Particle.publish("cdlong", String(cdlong));
float lat_b = radians*(Lat_Bd);
// Particle.publish("lat_b", String(lat_b));
float lat_a = radians*(Lat_Ad);
// Particle.publish("lat_a", String(lat_a));
float slat_b = sin(lat_b);
// Particle.publish("slat_b", String(slat_b));
float clat_b = cos(lat_b);
// Particle.publish("clat_b", String(clat_b));
float slat_a = sin(lat_a);
// Particle.publish("slat_a", String(slat_a));
float clat_a = cos(lat_a);
//Particle.publish("clat_a", String(clat_a));
delta = (clat_b * slat_a) - (slat_b * clat_a * cdlong);
//Particle.publish("Delta", String(delta));
delta = sq(delta);
//Particle.publish("Delta", String(delta));
delta += sq(clat_a * sdlong);
//Particle.publish("Delta", String(delta));
delta = sqrt(delta);
//Particle.publish("Delta", String(delta));
float denom = (slat_b * slat_a) + (clat_b * clat_a * cdlong);
//Particle.publish("Demon", String(denom));
delta = atan2(delta, denom);
//Particle.publish("Delta", String(delta));
BA = delta * 6372795;
//Particle.publish("BA", String(BA));
}
//IOT Project 048: Distance between Unit C and Unit B [BC]
{
// 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.
// Because Earth is no exact sphere, rounding errors may be up to 0.5%.
// Courtesy of Maarten Lamers
float delta = radians*(Lon_Bd-Lon_Cd);
float sdlong = sin(delta);
float cdlong = cos(delta);
float lat_b = radians*(Lat_Bd);
float lat_c = radians*(Lat_Cd);
float slat_b = sin(lat_b);
float clat_b = cos(lat_b);
float slat_c = sin(lat_c);
float clat_c = cos(lat_c);
delta = (clat_b * slat_c) - (slat_b * clat_c * cdlong);
delta = sq(delta);
delta += sq(clat_c * sdlong);
delta = sqrt(delta);
float denom = (slat_b * slat_c) + (clat_b * clat_c * cdlong);
delta = atan2(delta, denom);
BC = delta * 6372795;
}
//IOT Project 048: Distance between Unit D and Unit B [BD]
{
//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.
//Because Earth is no exact sphere, rounding errors may be up to 0.5%.
//Courtesy of Maarten Lamers
float delta = radians*(Lon_Bd-Lon_Dd);
float sdlong = sin(delta);
float cdlong = cos(delta);
float lat_b = radians*(Lat_Bd);
float lat_d = radians*(Lat_Dd);
float slat_b = sin(lat_b);
float clat_b = cos(lat_b);
float slat_d = sin(lat_d);
float clat_d = cos(lat_d);
delta = (clat_b * slat_d) - (slat_b * clat_d * cdlong);
delta = sq(delta);
delta += sq(clat_d * sdlong);
delta = sqrt(delta);
float denom = (slat_b * slat_d) + (clat_b * clat_d * cdlong);
delta = atan2(delta, denom);
BD = delta * 6372795;
}
Particle.publish("BA", String(BA));
Particle.publish("BC", String(BC));
Particle.publish("BD", String(BD));
}
float distance(String lat1, String lon1, String lat2, String lon2){
float distance = 0;
float formlat1 = formatLat(lat1);
float formlon1 = formatLon(lon1);
float formlat2 = formatLat(lat2);
float formlon2 = formatLon(lon2);
float delta = radians*(formlon1-formlon2);
float sdlong = sin(delta);
float cdlong = cos(delta);
float lat_b = radians*(formlat1);
float lat_c = radians*(formlat2);
float slat_b = sin(lat_b);
float clat_b = cos(lat_b);
float slat_c = sin(lat_c);
float clat_c = cos(lat_c);
delta = (clat_b * slat_c) - (slat_b * clat_c * cdlong);
delta = sq(delta);
delta += sq(clat_c * sdlong);
delta = sqrt(delta);
float denom = (slat_b * slat_c) + (clat_b * clat_c * cdlong);
delta = atan2(delta, denom);
distance = delta * 6372795;
return distance;
}
float formatLat(String lat){
float latitude = lat.toFloat();
latitude = latitude/100;
int latdeg = int(latitude);
float latmin = (latitude - latdeg)*100;
latitude = latdeg + (latmin/60);
return latitude;
}
float formatLon(String lon){
float longitude = lon.toFloat(); //string to float
longitude = longitude/100; //float/100 (ddmm.mmmm ---> dd.mmmmmm)
int londeg = int(longitude); //Then int truncates the decimal to leave (dd)
float lonmin = (longitude - londeg)*100; //subtract the int from origional to leave just .mmmmmm, *100 to bring mm.mmmm
longitude = londeg + (lonmin/60);
return longitude;
}
// This #include statement was automatically added by the Particle IDE.
#include <Particle-GPS.h>
// This #include statement was automatically added by the Particle IDE.
#include <TinyGPS++.h>
//IOT Project 048: initialize lattitude and longitude string variables
String Lat_D;
String Lon_D;
// ***
// *** Create a Gps instance. The RX an TX pins are connected to
// *** the TX and RX pins on the electron (Serial1).
// ***
Gps _gps = Gps(&Serial1);
// ***
// *** Create a timer that fires every 1 ms to capture
// *** incoming serial port data from the GPS.
// ***
Timer _timer = Timer(1, onSerialData);
void setup()
{
delay(2000);
// ***
// *** Initialize the USB Serial for debugging.
// ***
Serial.begin();
Serial.println("Initializing...");
// ***
// *** Initialize the GPS.
// ***
_gps.begin(9600);
// ***
// *** Start the timer.
// ***
_timer.start();\
//IOT Project 048: assign Lat and Lon as Particle cloud variables
Particle.variable("Lat_D", Lat_D);
Particle.variable("Lon_D", Lon_D);
}
void onSerialData()
{
_gps.onSerialData();
}
void loop()
{
// ***
// *** Get the Antenna Status ($PGTOP).
// ***
Pgtop pgtop = Pgtop(_gps);
if (pgtop.parse())
{
Serial.println("1) Antenna Status ($PGTOP)");
Serial.println("======================================================");
Serial.print("Command ID: "); Serial.println(pgtop.commandId);
Serial.print("Antenna Status: "); Serial.println(pgtop.reference);
Serial.println("");
}
// ***
// *** Get the Global Positioning System Fixed Data ($GPGGA).
// ***
Gga gga = Gga(_gps);
if (gga.parse())
{
Serial.println("2) Global Positioning System Fixed Data ($GPGGA)");
Serial.println("======================================================");
Serial.print("UTC Time: "); Serial.println(gga.utcTime);
Serial.print("Latitude: "); Serial.println(gga.latitude);
Serial.print("North/SouthIndicator: "); Serial.println(gga.northSouthIndicator);
Serial.print("Longitude: "); Serial.println(gga.longitude);
Serial.print("East/WestIndicator: "); Serial.println(gga.eastWestIndicator);
Serial.print("Position Fix Indicator: "); Serial.println(gga.positionFixIndicator);
Serial.print("Satellites Used: "); Serial.println(gga.satellitesUsed);
Serial.print("Horizontal Dilution of Precision: "); Serial.println(gga.hdop);
Serial.print("Altitude: "); Serial.print(gga.altitude); Serial.print(" "); Serial.println(gga.altitudeUnit);
Serial.print("Geoidal Separation: "); Serial.print(gga.geoidalSeparation); Serial.print(" "); Serial.println(gga.geoidalSeparationUnit);
Serial.print("Age of Diff. Corr.: "); Serial.println(gga.ageOfDiffCorr);
Serial.println("");
//IOT Project 048: Update Particle variables with GPS fix data and publish to the cloud.
Lat_D = gga.latitude;
Lon_D= gga.longitude;
//Particle.publish("Latitude_A", Lat_A);
//Particle.publish("Longitude_A", Lon_A);
}
// ***
// *** Get the Recommended Minimum Navigation Information ($GPRMC).
Rmc rmc = Rmc(_gps);
if (rmc.parse())
{
Serial.println("3) Recommended Minimum Navigation Information ($GPRMC)");
Serial.println("======================================================");
Serial.print("UTC Time: "); Serial.println(rmc.utcTime);
Serial.print("Latitude: "); Serial.println(rmc.latitude);
Serial.print("North/SouthIndicator: "); Serial.println(rmc.northSouthIndicator);
Serial.print("Longitude: "); Serial.println(rmc.longitude);
Serial.print("East/WestIndicator: "); Serial.println(rmc.eastWestIndicator);
Serial.print("Speed Over Ground: "); Serial.println(rmc.speedOverGround);
Serial.print("Course Over Ground: "); Serial.println(rmc.courseOverGround);
Serial.print("Date: "); Serial.println(rmc.date);
Serial.print("Magnetic Variation: "); Serial.print(rmc.magneticVariation); Serial.print(" "); Serial.println(rmc.magneticVariationDirection);
Serial.print("Mode: "); Serial.println(rmc.mode);
Serial.println("");
Lat_D = rmc.latitude;
Lon_D = rmc.longitude;
//Particle.publish("Latitude_A", Lat_A);
//Particle.publish("Longitude_A", Lon_A);
}
delay(1000);
String data = String(10);
// Trigger the webhook
Particle.publish("Lat_D", Lat_D);
// Trigger the webhook
Particle.publish("Lon_D", Lon_D);
//Particle.subscribe("Total", test, MY_DEVICES);
// Wait 60 seconds
delay(30000);
}
int i = 0;
void test(const char *event, const char *data){
i++;
Serial.print(i);
Serial.print(event);
Serial.print(", data: ");
if (data)
Serial.println(data);
else
Serial.println("NULL");
}
// This #include statement was automatically added by the Particle IDE.
#include <Particle-GPS.h>
// This #include statement was automatically added by the Particle IDE.
#include <TinyGPS++.h>
//IOT Project 048: initialize lattitude and longitude string variables
String Lat_C;
String Lon_C;
// ***
// *** Create a Gps instance. The RX an TX pins are connected to
// *** the TX and RX pins on the electron (Serial1).
// ***
Gps _gps = Gps(&Serial1);
// ***
// *** Create a timer that fires every 1 ms to capture
// *** incoming serial port data from the GPS.
// ***
Timer _timer = Timer(1, onSerialData);
void setup()
{
delay(2000);
// ***
// *** Initialize the USB Serial for debugging.
// ***
Serial.begin();
Serial.println("Initializing...");
// ***
// *** Initialize the GPS.
// ***
_gps.begin(9600);
// ***
// *** Start the timer.
// ***
_timer.start();\
//IOT Project 048: assign Lat and Lon as Particle cloud variables
Particle.variable("Lat_C", Lat_C);
Particle.variable("Lon_C", Lon_C);
}
void onSerialData()
{
_gps.onSerialData();
}
void loop()
{
// ***
// *** Get the Antenna Status ($PGTOP).
// ***
Pgtop pgtop = Pgtop(_gps);
if (pgtop.parse())
{
Serial.println("1) Antenna Status ($PGTOP)");
Serial.println("======================================================");
Serial.print("Command ID: "); Serial.println(pgtop.commandId);
Serial.print("Antenna Status: "); Serial.println(pgtop.reference);
Serial.println("");
}
// ***
// *** Get the Global Positioning System Fixed Data ($GPGGA).
// ***
Gga gga = Gga(_gps);
if (gga.parse())
{
Serial.println("2) Global Positioning System Fixed Data ($GPGGA)");
Serial.println("======================================================");
Serial.print("UTC Time: "); Serial.println(gga.utcTime);
Serial.print("Latitude: "); Serial.println(gga.latitude);
Serial.print("North/SouthIndicator: "); Serial.println(gga.northSouthIndicator);
Serial.print("Longitude: "); Serial.println(gga.longitude);
Serial.print("East/WestIndicator: "); Serial.println(gga.eastWestIndicator);
Serial.print("Position Fix Indicator: "); Serial.println(gga.positionFixIndicator);
Serial.print("Satellites Used: "); Serial.println(gga.satellitesUsed);
Serial.print("Horizontal Dilution of Precision: "); Serial.println(gga.hdop);
Serial.print("Altitude: "); Serial.print(gga.altitude); Serial.print(" "); Serial.println(gga.altitudeUnit);
Serial.print("Geoidal Separation: "); Serial.print(gga.geoidalSeparation); Serial.print(" "); Serial.println(gga.geoidalSeparationUnit);
Serial.print("Age of Diff. Corr.: "); Serial.println(gga.ageOfDiffCorr);
Serial.println("");
//IOT Project 048: Update Particle variables with GPS fix data and publish to the cloud.
Lat_C = gga.latitude;
Lon_C= gga.longitude;
//Particle.publish("Latitude_A", Lat_A);
//Particle.publish("Longitude_A", Lon_A);
}
// ***
// *** Get the Recommended Minimum Navigation Information ($GPRMC).
Rmc rmc = Rmc(_gps);
if (rmc.parse())
{
Serial.println("3) Recommended Minimum Navigation Information ($GPRMC)");
Serial.println("======================================================");
Serial.print("UTC Time: "); Serial.println(rmc.utcTime);
Serial.print("Latitude: "); Serial.println(rmc.latitude);
Serial.print("North/SouthIndicator: "); Serial.println(rmc.northSouthIndicator);
Serial.print("Longitude: "); Serial.println(rmc.longitude);
Serial.print("East/WestIndicator: "); Serial.println(rmc.eastWestIndicator);
Serial.print("Speed Over Ground: "); Serial.println(rmc.speedOverGround);
Serial.print("Course Over Ground: "); Serial.println(rmc.courseOverGround);
Serial.print("Date: "); Serial.println(rmc.date);
Serial.print("Magnetic Variation: "); Serial.print(rmc.magneticVariation); Serial.print(" "); Serial.println(rmc.magneticVariationDirection);
Serial.print("Mode: "); Serial.println(rmc.mode);
Serial.println("");
Lat_C = rmc.latitude;
Lon_C = rmc.longitude;
//Particle.publish("Latitude_A", Lat_A);
//Particle.publish("Longitude_A", Lon_A);
}
delay(1000);
String data = String(10);
// Trigger the webhook
Particle.publish("Lat_C", Lat_C);
// Trigger the webhook
Particle.publish("Lon_C", Lon_C);
//Particle.subscribe("Total", test, MY_DEVICES);
// Wait 60 seconds
delay(30000);
}
int i = 0;
void test(const char *event, const char *data){
i++;
Serial.print(i);
Serial.print(event);
Serial.print(", data: ");
if (data)
Serial.println(data);
else
Serial.println("NULL");
}
Comments