Created
February 8, 2024 17:03
-
-
Save jones2126/c59a4c7479501aa3b7dcf47c0a9d0b3e to your computer and use it in GitHub Desktop.
Sending lat, lon and altitude data from #BESTPOS and $GPGGA messages to Google Sheet in order to survey a site (i.e. average the position over time) so I have use the 'fix position' statement when configuring my Base RTK GPS that sends correction data.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <HardwareSerial.h> | |
#include <WiFi.h> | |
#include <HTTPClient.h> | |
// WiFi credentials | |
const char* ssid = "Pixel_1"; | |
const char* password = "Taco1234"; | |
// Google_Deployment_ID = "AKfycbwZv_vHVI9Hw67vYj609zprKJmdVEuHyH37Mg3VCzo-2lPU9Zaz-dHLp1P7RRAgSDMb" | |
const char* googleURLPrefix = "https://script.google.com/macros/s/AKfycbwZv_vHVI9Hw67vYj609zprKJmdVEuHyH37Mg3VCzo-2lPU9Zaz-dHLp1P7RRAgSDMb/exec"; | |
HardwareSerial GPS(2); // Use UART 2 for GPS | |
String gpsMessage = ""; // Global variables to hold gps messages | |
String messageType = ""; | |
#define maxCommas 30 // 30 selected because it is 1 more than the expected max for BESTPOS sentence | |
int commaIndices[maxCommas] = {}; // Array to hold indices of commas and semicolon | |
int commaCount = 0; | |
unsigned long lastAverageTime = 0; | |
//const long averageInterval = 600000; // Interval for averaging (10 minutes in milliseconds) | |
const long averageInterval = 60000; // Interval for averaging (1 minutes in milliseconds) 60 seconds/minute X 1000 milliseconds/second=60,000 milliseconds | |
// Variables for averaging GPS data | |
double accumulatedBESTPOSLat = 0, accumulatedBESTPOSLon = 0, accumulatedBESTPOSAlt = 0; | |
double accumulatedGPGGALat = 0, accumulatedGPGGALon = 0, accumulatedGPGGAAlt = 0; | |
double avgBESTPOSLat = 0, avgBESTPOSLon = 0, avgBESTPOSAlt = 0, avgGPGGALat = 0, avgGPGGALon = 0, avgGPGGAAlt = 0; | |
int dataCountBESTPOS = 0, dataCountGPGGA = 0; | |
double lat = 0.0, lon = 0.0, alt = 0.0; | |
void setup() { | |
Serial.begin(115200); | |
WiFi.begin(ssid, password); | |
while (WiFi.status() != WL_CONNECTED) { | |
delay(500); | |
Serial.print("."); | |
} | |
Serial.println("WiFi connected"); | |
GPS.begin(115200, SERIAL_8N1, 16, 17); // RX, TX pins for UART2 | |
} | |
void loop() { | |
if (GPS.available()) { | |
gpsMessage = GPS.readStringUntil('\n'); | |
parseGPSData(); // Parse and accumulate data for averaging | |
} | |
// Based on interval setting, calculate and log averages, then reset | |
if (millis() - lastAverageTime >= averageInterval) { | |
if (dataCountBESTPOS > 0) { | |
calculateAndLogAverages(); | |
lastAverageTime = millis(); | |
} | |
} | |
} | |
void parseGPSData() { | |
// Print the raw GPS data string | |
Serial.print("Raw GPS Data: "); | |
Serial.println(gpsMessage); | |
// Find the position of the commas and store them in an array to facilitate parsing | |
for (unsigned int i = 0; i < gpsMessage.length(); i++) { | |
if (gpsMessage[i] == ',') { | |
if (commaCount > (maxCommas-1)) { | |
Serial.println("Error: Too many commas in the message."); | |
return; // Early return to avoid processing incorrect data | |
} | |
commaIndices[commaCount] = i; | |
commaCount += 1; | |
} | |
} | |
messageType = gpsMessage.substring(0, commaIndices[0]); | |
Serial.print("messageType: "); Serial.print(messageType); Serial.print(" commaCount: "); Serial.println(commaCount); | |
if (messageType == "#BESTPOSA") { | |
parseBESTPOSA(); | |
} else if (messageType == "$GPGGA") { | |
parseGPGGA(); | |
} else { | |
Serial.print("Error: Unexpected message type. Raw sentence, ("); Serial.print(gpsMessage); Serial.println(")"); | |
} | |
commaCount = 0; commaIndices[maxCommas] = {}; | |
} | |
void parseBESTPOSA() { | |
// Comma locations (start and end): Latitude(11-12), Longitude(12-13), Altitude(13-14) | |
if (commaCount == 29) { // Confirm we have the expected number of commas | |
lat = gpsMessage.substring(commaIndices[10] + 1, commaIndices[11]).toDouble(); | |
lon = gpsMessage.substring(commaIndices[11] + 1, commaIndices[12]).toDouble(); | |
String altStr = gpsMessage.substring(commaIndices[12] + 1, commaIndices[13]); | |
alt = altStr.toDouble(); | |
accumulatedBESTPOSLat += lat; | |
accumulatedBESTPOSLon += lon; | |
accumulatedBESTPOSAlt += alt; | |
dataCountBESTPOS++; | |
} else { | |
Serial.print("Error: expected 29 commas, commaCount: "); Serial.println(commaCount); | |
} | |
} | |
void parseGPGGA() { | |
// Comma locations (start and end): Latitude(2-3), Latitude Direction(3-4), Longitude(4-5), Longitude Direction(5-6), Altitude(9-10) | |
if (commaCount == 14) { // Confirm we have expected number of commas | |
lat = convertNMEAToDecimal(gpsMessage.substring(commaIndices[1] + 1, commaIndices[2]), gpsMessage.substring(commaIndices[2] + 1, commaIndices[3])); | |
lon = convertNMEAToDecimal(gpsMessage.substring(commaIndices[3] + 1, commaIndices[4]), gpsMessage.substring(commaIndices[4] + 1, commaIndices[5])); | |
String altStr = gpsMessage.substring(commaIndices[8] + 1, commaIndices[9]); | |
alt = altStr.toDouble(); | |
accumulatedGPGGALat += lat; | |
accumulatedGPGGALon += lon; | |
accumulatedGPGGAAlt += alt; | |
dataCountGPGGA++; | |
} else { | |
Serial.print("Error: expected 14 commas, commaCount: "); Serial.println(commaCount); | |
} | |
} | |
double convertNMEAToDecimal(String value, String direction) { | |
// Determine the number of digits in the degrees based on the length of the string and the direction | |
// int degreeLength = (condition) ? value_if_true : value_if_false; | |
int degreeLength = (direction == "N" || direction == "S") ? 2 : 3; | |
double degrees = value.substring(0, degreeLength).toDouble(); | |
double minutes = value.substring(degreeLength).toDouble(); | |
double decimal = degrees + (minutes / 60); | |
if (direction == "S" || direction == "W") { | |
decimal = -decimal; | |
} | |
return decimal; | |
} | |
void calculateAndLogAverages() { | |
avgBESTPOSLat = accumulatedBESTPOSLat / dataCountBESTPOS; | |
avgBESTPOSLon = accumulatedBESTPOSLon / dataCountBESTPOS; | |
avgBESTPOSAlt = accumulatedBESTPOSAlt / dataCountBESTPOS; | |
accumulatedBESTPOSLat = 0; accumulatedBESTPOSLon = 0; accumulatedBESTPOSAlt = 0; dataCountBESTPOS = 0; | |
Serial.printf("Sending BESTPOS Averages: Lat=%.10f, Lon=%.10f, Alt=%.3f\n", avgBESTPOSLat, avgBESTPOSLon, avgBESTPOSAlt); | |
avgGPGGALat = accumulatedGPGGALat / dataCountGPGGA; | |
avgGPGGALon = accumulatedGPGGALon / dataCountGPGGA; | |
avgGPGGAAlt = accumulatedGPGGAAlt / dataCountGPGGA; | |
accumulatedGPGGALat = 0; accumulatedGPGGALon = 0; accumulatedGPGGAAlt = 0; dataCountGPGGA = 0; | |
Serial.printf("Sending GPGGA Averages: Lat=%.10f, Lon=%.10f, Alt=%.3f\n", avgGPGGALat, avgGPGGALon, avgGPGGAAlt); | |
// Send to Google Sheets | |
sendToGoogleSheets(); // Formulate a URL with data and send to Google Sheets | |
} | |
void sendToGoogleSheets() { | |
if (WiFi.status() == WL_CONNECTED) { | |
char url[512]; // The current message is 246 characters | |
snprintf(url, sizeof(url), | |
"%s?BESTPOSLat=%.10f&BESTPOSLon=%.10f&BESTPOSAlt=%.3f&GPGGALat=%.10f&GPGGALon=%.10f&GPGGAAlt=%.3f", | |
googleURLPrefix, avgBESTPOSLat, avgBESTPOSLon, avgBESTPOSAlt, avgGPGGALat, avgGPGGALon, avgGPGGAAlt); | |
HTTPClient http; | |
size_t urlLength = strlen(url); | |
Serial.print("URL Length: "); Serial.println(urlLength); | |
Serial.print("url being sent: "); Serial.println(url); | |
http.begin(url); // Start the connection | |
int httpCode = http.GET(); // Send the HTTP GET request | |
String httpResponse = http.getString(); // Get the request response | |
if (httpCode == 200) { | |
Serial.println("Average data sent successfully to Google Sheets."); | |
} else if (httpCode == 302) { | |
Serial.println("Warning: Redirection Status code: " + String(httpCode)); | |
Serial.println("Response: " + httpResponse); | |
} else { | |
Serial.println("Error: Unexpected Status code: " + String(httpCode)); | |
Serial.println("Response: " + httpResponse); | |
} | |
http.end(); // Close connection | |
} else { | |
Serial.println("Error: WiFi not connected - No update to Google Sheet"); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment