diff --git a/Adafruit_GPS.cpp b/Adafruit_GPS.cpp index 16b3acf..7e90722 100755 --- a/Adafruit_GPS.cpp +++ b/Adafruit_GPS.cpp @@ -103,7 +103,7 @@ boolean Adafruit_GPS::parse(char *nmea) { fixquality = atoi(p); if(fixquality > 0){ fix = true; - lastFix = millis(); + lastFix = recvdTime; } else fix = false; } @@ -178,6 +178,7 @@ boolean Adafruit_GPS::parse(char *nmea) { day = fulldate / 10000; month = (fulldate % 10000) / 100; year = (fulldate % 100); + lastDate = recvdTime; } return true; } @@ -226,6 +227,7 @@ void Adafruit_GPS::parseTime(char *p) { seconds = (time % 100); milliseconds = fmod(timef, 1.0) * 1000; + lastTime = recvdTime; } /**************************************************************************/ @@ -332,7 +334,7 @@ boolean Adafruit_GPS::parseLonDir(char *p) { boolean Adafruit_GPS::parseFix(char *p) { if (p[0] == 'A'){ fix = true; - lastFix = millis(); + lastFix = recvdTime; } else if (p[0] == 'V') fix = false; @@ -343,15 +345,37 @@ boolean Adafruit_GPS::parseFix(char *p) { /**************************************************************************/ /*! - @brief Time in seconds since the last fix was obtained. Will fail by - rolling over to zero after one millis() cycle, about 6-1/2 weeks. + @brief Time in seconds since the last position fix was obtained. Will + fail by rolling over to zero after one millis() cycle, about 6-1/2 weeks. @return float value in seconds since last fix. */ /**************************************************************************/ -float Adafruit_GPS::timeSinceFix() { +float Adafruit_GPS::secondsSinceFix() { return (millis()-lastFix) / 1000.; } +/**************************************************************************/ +/*! + @brief Time in seconds since the last GPS time was obtained. Will fail + by rolling over to zero after one millis() cycle, about 6-1/2 weeks. + @return float value in seconds since last GPS time. +*/ +/**************************************************************************/ +float Adafruit_GPS::secondsSinceTime() { + return (millis()-lastTime) / 1000.; +} + +/**************************************************************************/ +/*! + @brief Time in seconds since the last GPS date was obtained. Will fail + by rolling over to zero after one millis() cycle, about 6-1/2 weeks. + @return float value in seconds since last GPS date. +*/ +/**************************************************************************/ +float Adafruit_GPS::secondsSinceDate() { + return (millis()-lastDate) / 1000.; +} + /**************************************************************************/ /*! @brief Read one character from the GPS device @@ -400,6 +424,7 @@ char Adafruit_GPS::read(void) { //Serial.println("----"); lineidx = 0; recvdflag = true; + recvdTime = millis(); // time we got the end of the string } return c; diff --git a/Adafruit_GPS.h b/Adafruit_GPS.h old mode 100755 new mode 100644 index 5aef9d3..0f9cd49 --- a/Adafruit_GPS.h +++ b/Adafruit_GPS.h @@ -119,7 +119,9 @@ class Adafruit_GPS { char read(void); boolean parse(char *); - float timeSinceFix(); + float secondsSinceFix(); + float secondsSinceTime(); + float secondsSinceDate(); boolean wakeup(void); boolean standby(void); @@ -179,7 +181,12 @@ class Adafruit_GPS { void parseLon(char *); boolean parseLonDir(char *); boolean parseFix(char *); - time_t lastFix; + // Make all of these times far in the past by setting them near the middle of the + // millis() range. Timing assumes that sentences are parsed promptly. + time_t lastFix = 2000000000L; // millis() when last fix received + time_t lastTime = 2000000000L; // millis() when last time received + time_t lastDate = 2000000000L; // millis() when last date received + time_t recvdTime = 2000000000L; // millis() when last full sentence received boolean paused; uint8_t parseResponse(char *response); diff --git a/examples/GPS_HardwareSerial_Timing/GPS_HardwareSerial_Timing.ino b/examples/GPS_HardwareSerial_Timing/GPS_HardwareSerial_Timing.ino new file mode 100644 index 0000000..d5d1493 --- /dev/null +++ b/examples/GPS_HardwareSerial_Timing/GPS_HardwareSerial_Timing.ino @@ -0,0 +1,136 @@ +// Test code for Ultimate GPS Using Hardware Serial (e.g. GPS Flora or FeatherWing) +// +// This code is similar to GPS_HardwareSerial_Parsing, except for the additional +// elements to keep track of how long it has been since time and fix data have been +// received. This approach lets you keep an up to date clock based on GPS time at +// any time in between GPS fixes. +// +// This code shows how to listen to the GPS module via polling. Best used with +// Feathers or Flora where you have hardware Serial and no interrupt +// +// Tested and works great with the Adafruit GPS FeatherWing +// ------> https://www.adafruit.com/products/3133 +// or Flora GPS +// ------> https://www.adafruit.com/products/1059 +// but also works with the shield, breakout +// ------> https://www.adafruit.com/products/1272 +// ------> https://www.adafruit.com/products/746 +// +// Pick one up today at the Adafruit electronics shop +// and help support open source hardware & software! -ada + +#include + +// what's the name of the hardware serial port? +#define GPSSerial Serial1 + +// Connect to the GPS on the hardware port +Adafruit_GPS GPS(&GPSSerial); + +// Set GPSECHO to 'false' to turn off echoing the GPS data to the Serial console +// Set to 'true' if you want to debug and listen to the raw GPS sentences +#define GPSECHO true + +uint32_t timer = millis(); + + +void setup() +{ + //while (!Serial); // uncomment to have the sketch wait until Serial is ready + + // connect at 115200 so we can read the GPS fast enough and echo without dropping chars + // also spit it out + Serial.begin(115200); + Serial.println("Adafruit GPS library basic test!"); + + // 9600 NMEA is the default baud rate for Adafruit MTK GPS's- some use 4800 + GPS.begin(9600); + // uncomment this line to turn on RMC (recommended minimum) and GGA (fix data) including altitude + GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA); + // uncomment this line to turn on only the "minimum recommended" data + //GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCONLY); + // For parsing data, we don't suggest using anything but either RMC only or RMC+GGA since + // the parser doesn't care about other sentences at this time + // Set the update rate (uncomment the one you want.) + //GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ); // 1 Hz update rate + //GPS.sendCommand(PMTK_SET_NMEA_UPDATE_200_MILLIHERTZ); // 5 second update time + GPS.sendCommand(PMTK_SET_NMEA_UPDATE_100_MILLIHERTZ); // 10 second update time + // For the parsing code to work nicely and have time to sort thru the data, and + // print it out we don't suggest using anything higher than 1 Hz + + // Request updates on antenna status, comment out to keep quiet + GPS.sendCommand(PGCMD_ANTENNA); + + delay(1000); + + // Ask for firmware version + GPSSerial.println(PMTK_Q_RELEASE); +} + +void loop() // run over and over again +{ + // read data from the GPS in the 'main loop' + char c = GPS.read(); + // if you want to debug, this is a good time to do it! + if (GPSECHO) + if (c) Serial.print(c); + // if a sentence is received, we can check the checksum, parse it... + if (GPS.newNMEAreceived()) { + // a tricky thing here is if we print the NMEA sentence, or data + // we end up not listening and catching other sentences! + // so be very wary if using OUTPUT_ALLDATA and trytng to print out data + //Serial.println(GPS.lastNMEA()); // this also sets the newNMEAreceived() flag to false + if (!GPS.parse(GPS.lastNMEA())) // this also sets the newNMEAreceived() flag to false + return; // we can fail to parse a sentence in which case we should just wait for another + } + // if millis() or timer wraps around, we'll just reset it + if (timer > millis()) timer = millis(); + + // approximately every 2 seconds or so, random intervals, print out the current stats + static unsigned nextInterval = 2000; + if (millis() - timer > nextInterval) { + timer = millis(); // reset the timer + nextInterval = 1500 + random(1000); + // Time in seconds keeps increasing after we get the NMEA sentence. + // This estimate will lag real time due to transmission and parsing delays, + // but the lag should be small and should also be consistent. + float s = GPS.seconds + GPS.milliseconds/1000. + GPS.secondsSinceTime(); + int m = GPS.minute; + int h = GPS.hour; + int d = GPS.day; + // Adjust time and day forward to account for elapsed time. + // This will break at month boundaries!!! Humans will have to cope with April 31,32 etc. + while(s > 60){ s -= 60; m++; } + while(m > 60){ m -= 60; h++; } + while(h > 24){ h -= 24; d++; } + // ISO Standard Date Format, with leading zeros https://xkcd.com/1179/ + Serial.print("\nDate: "); + Serial.print(GPS.year+2000, DEC); Serial.print("-"); + if(GPS.month < 10) Serial.print("0"); + Serial.print(GPS.month, DEC); Serial.print("-"); + if(d < 10) Serial.print("0"); + Serial.print(d, DEC); + Serial.print(" Time: "); + if(h < 10) Serial.print("0"); + Serial.print(h, DEC); Serial.print(':'); + if(m < 10) Serial.print("0"); + Serial.print(m, DEC); Serial.print(':'); + if(s < 10) Serial.print("0"); + Serial.println(s, 3); + Serial.print("Fix: "); Serial.print((int)GPS.fix); + Serial.print(" quality: "); Serial.println((int)GPS.fixquality); + Serial.print("Times [s] since last fix: "); Serial.print(GPS.secondsSinceFix(),3); + Serial.print(", GPS time: "); Serial.print(GPS.secondsSinceTime(),3); + Serial.print(", GPS date: "); Serial.println(GPS.secondsSinceDate(),3); + if (GPS.fix) { + Serial.print("Location: "); + Serial.print(GPS.latitude, 4); Serial.print(GPS.lat); + Serial.print(", "); + Serial.print(GPS.longitude, 4); Serial.println(GPS.lon); + Serial.print("Speed (knots): "); Serial.println(GPS.speed); + Serial.print("Angle: "); Serial.println(GPS.angle); + Serial.print("Altitude: "); Serial.println(GPS.altitude); + Serial.print("Satellites: "); Serial.println((int)GPS.satellites); + } + } +}