From 84eaad66e4a6199439b871a37613c919545b3a5c Mon Sep 17 00:00:00 2001 From: Rick Sellens Date: Wed, 29 Jan 2020 19:44:05 -0500 Subject: [PATCH 01/10] Fail Check if sentence not recognized Previous check would pass for unknown but properly formatted sentence. --- src/NMEA_parse.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/NMEA_parse.cpp b/src/NMEA_parse.cpp index 822fc57..942d198 100644 --- a/src/NMEA_parse.cpp +++ b/src/NMEA_parse.cpp @@ -588,7 +588,10 @@ boolean Adafruit_GPS::check(char *nmea) { if (snc) { strcpy(thisSentence, snc); thisCheck += NMEA_HAS_SENTENCE; - return false; + return false; // known but not parsed + } else { + parseStr(thisSentence, p, NMEA_MAX_SENTENCE_ID); + return false; // unknown } } return true; // passed all the tests From deb312b2934d8b526c161702d755cc8a6f8ea3ca Mon Sep 17 00:00:00 2001 From: Rick Sellens Date: Wed, 29 Jan 2020 19:52:13 -0500 Subject: [PATCH 02/10] Clear thisSentence and thisSource at start of each check that way previous sentence identifiers won't bleed through on failure. --- src/NMEA_parse.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/NMEA_parse.cpp b/src/NMEA_parse.cpp index 942d198..97d603a 100644 --- a/src/NMEA_parse.cpp +++ b/src/NMEA_parse.cpp @@ -545,6 +545,7 @@ bool Adafruit_GPS::parse(char *nmea) { /**************************************************************************/ boolean Adafruit_GPS::check(char *nmea) { thisCheck = 0; // new check + *thisSentence = *thisSource = 0; if (*nmea != '$' && *nmea != '!') return false; // doesn't start with $ or ! else From d14e220c1bb0f61edcb052e469516f69d61acc3f Mon Sep 17 00:00:00 2001 From: Rick Sellens Date: Thu, 30 Jan 2020 14:29:17 -0500 Subject: [PATCH 03/10] Add noCRLF option to build() new optional argument will leave the carriage return and linefeed off the end of an NMEA sentence. --- src/Adafruit_GPS.cpp | 8 +++++++- src/Adafruit_GPS.h | 2 +- src/NMEA_build.cpp | 7 ++++--- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/Adafruit_GPS.cpp b/src/Adafruit_GPS.cpp index 65e5c10..c8e46c6 100644 --- a/src/Adafruit_GPS.cpp +++ b/src/Adafruit_GPS.cpp @@ -349,7 +349,13 @@ size_t Adafruit_GPS::write(uint8_t c) { /**************************************************************************/ /*! - @brief Read one character from the GPS device + @brief Read one character from the GPS device. + + Call very frequently and multiple times per opportunity or the buffer + may overflow if there are frequent NMEA sentences. An 82 character NMEA + sentence 10 times per second will require 820 calls per second, and + once a loop() may not be enough. Check for newNMEAreceived() after at + least every 10 calls, or you may miss some short sentences. @return The character that we received, or 0 if nothing was available */ /**************************************************************************/ diff --git a/src/Adafruit_GPS.h b/src/Adafruit_GPS.h index fe9baee..acfc316 100644 --- a/src/Adafruit_GPS.h +++ b/src/Adafruit_GPS.h @@ -121,7 +121,7 @@ public: // NMEA_build.cpp #ifdef NMEA_EXTENSIONS char *build(char *nmea, const char *thisSource, const char *thisSentence, - char ref = 'R'); + char ref = 'R', bool noCRLF = false); #endif void addChecksum(char *buff); diff --git a/src/NMEA_build.cpp b/src/NMEA_build.cpp index 8b78139..201f30c 100644 --- a/src/NMEA_build.cpp +++ b/src/NMEA_build.cpp @@ -71,7 +71,7 @@ */ /**************************************************************************/ char *Adafruit_GPS::build(char *nmea, const char *thisSource, - const char *thisSentence, char ref) { + const char *thisSentence, char ref, bool noCRLF) { sprintf(nmea, "%6.2f", (double)123.45); // fail if sprintf() doesn't handle floats if (strcmp(nmea, "123.45")) @@ -569,8 +569,9 @@ char *Adafruit_GPS::build(char *nmea, const char *thisSource, } addChecksum(nmea); // Successful completion - sprintf(nmea, "%s\r\n", - nmea); // Add Carriage Return and Line Feed to comply with NMEA-183 + if (!noCRLF) { // Add Carriage Return and Line Feed to comply with NMEA-183 + sprintf(nmea, "%s\r\n", nmea); + } return nmea; // return pointer to finished product } From d0f7f47dc94f1ba8b9489f937dd190a06d9bf7e3 Mon Sep 17 00:00:00 2001 From: Rick Sellens Date: Thu, 30 Jan 2020 17:09:35 -0500 Subject: [PATCH 04/10] Warning about scaling --- src/NMEA_data.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/NMEA_data.cpp b/src/NMEA_data.cpp index d3d05ed..72a44ef 100644 --- a/src/NMEA_data.cpp +++ b/src/NMEA_data.cpp @@ -367,7 +367,11 @@ void Adafruit_GPS::initDataValue(nmea_index_t idx, char *label, char *fmt, /*! @brief Attempt to add history to a data value table entry. If it fails to malloc the space, history will not be added. Test the pointer for a - check if needed. + check if needed. Select scale and offset values carefully so that + operations and results will fit inside 16 bit integer limits. For example + a scale of 1.0 and an offset of 100000.0 would be a good choice for + atmospheric pressure in Pa with values ranging ~ +/- 3500, while a scale + of 10.0 would be pushing the integer limits. @param idx The data index for the value to have history recorded @param scale Value for scaling the integer history list @param offset Value for scaling the integer history list From 50abddc69181f3b83fb3dbea4d9c0461abee0c76 Mon Sep 17 00:00:00 2001 From: Rick Sellens Date: Thu, 30 Jan 2020 20:14:52 -0500 Subject: [PATCH 05/10] comments to solve: https://github.com/adafruit/Adafruit_GPS/issues/76 Corrections to original comments that were off by a factor of 10. --- src/Adafruit_GPS.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Adafruit_GPS.h b/src/Adafruit_GPS.h index acfc316..bf190b4 100644 --- a/src/Adafruit_GPS.h +++ b/src/Adafruit_GPS.h @@ -170,11 +170,12 @@ public: ///< as received from the GPS (DDDMM.MMMM) /** Fixed point latitude and longitude value with degrees stored in units of - 1/100000 degrees, and minutes stored in units of 1/100000 degrees. See pull - #13 for more details: + 1/10000000 of a degree. See pull #13 for more details: https://github.com/adafruit/Adafruit-GPS-Library/pull/13 */ - int32_t latitude_fixed; ///< Fixed point latitude in decimal degrees + int32_t latitude_fixed; ///< Fixed point latitude in decimal degrees. + ///< Divide by 10000000.0 to get a double. int32_t longitude_fixed; ///< Fixed point longitude in decimal degrees + ///< Divide by 10000000.0 to get a double. nmea_float_t latitudeDegrees; ///< Latitude in decimal degrees nmea_float_t longitudeDegrees; ///< Longitude in decimal degrees From 07fd81fd914bbfa33565163efec8e65e5aa59694 Mon Sep 17 00:00:00 2001 From: Rick Sellens Date: Fri, 31 Jan 2020 07:30:30 -0500 Subject: [PATCH 06/10] explicit cast eliminates ambiguity ESP32 wire lib includes requestFrom(int,int,int) and requestFrom(uint16_t,uint8_t,bool) and throws a warning trying to resolve. --- src/Adafruit_GPS.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Adafruit_GPS.cpp b/src/Adafruit_GPS.cpp index c8e46c6..bec9556 100644 --- a/src/Adafruit_GPS.cpp +++ b/src/Adafruit_GPS.cpp @@ -385,7 +385,7 @@ char Adafruit_GPS::read(void) { _buff_idx++; } else { // refill the buffer! - if (gpsI2C->requestFrom(0x10, GPS_MAX_I2C_TRANSFER, true) == + if (gpsI2C->requestFrom((uint16_t)0x10, (uint8_t)GPS_MAX_I2C_TRANSFER, true) == GPS_MAX_I2C_TRANSFER) { // got data! _buff_max = 0; From a047465a7330ffd8b95eff81f099bccabdae1f78 Mon Sep 17 00:00:00 2001 From: Rick Sellens Date: Fri, 7 Feb 2020 14:26:39 -0500 Subject: [PATCH 07/10] More rigor in parseTime() previous version ran ok with M0, but generated exceptions in ESP32 when decimals not found. --- src/NMEA_parse.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/NMEA_parse.cpp b/src/NMEA_parse.cpp index 97d603a..652becd 100644 --- a/src/NMEA_parse.cpp +++ b/src/NMEA_parse.cpp @@ -768,8 +768,11 @@ bool Adafruit_GPS::parseTime(char *p) { hour = time / 10000; minute = (time % 10000) / 100; seconds = (time % 100); - p = strchr(p, '.'); - milliseconds = atof(p) * 1000; + char *dec = strchr(p, '.'); + char *comstar = min(strchr(p, ','), strchr(p, '*')); + if(dec != NULL && comstar != NULL && dec < comstar) + milliseconds = atof(p) * 1000; + else milliseconds = 0; lastTime = sentTime; return true; } From 8c550d278e8c210d12451fe22b4be32062795ee2 Mon Sep 17 00:00:00 2001 From: Rick Sellens Date: Fri, 7 Feb 2020 14:54:26 -0500 Subject: [PATCH 08/10] fix to parsing bug on RMB sentence --- src/NMEA_parse.cpp | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/src/NMEA_parse.cpp b/src/NMEA_parse.cpp index 652becd..a7bae50 100644 --- a/src/NMEA_parse.cpp +++ b/src/NMEA_parse.cpp @@ -319,6 +319,21 @@ bool Adafruit_GPS::parse(char *nmea) { } else if (!strcmp(thisSentence, "RMB")) { //*****************************RMB // from Actisense NGW-1 from SH CP150C + // RMB Recommended Minimum Navigation Information + // 1 2 3 4 5 6 7 8 9 10 11 12 13 14 + // | | | | | | | | | | | | | | + //$--RMB,A,x.x,a,c--c,c--c,llll.ll,a,yyyyy.yy,a,x.x,x.x,x.x,A*hh + // 1) Status, V = Navigation receiver warning + // 2) Cross Track error - nautical miles + // 3) Direction to Steer, Left or Right + // 4) TO Waypoint ID + // 5) FROM Waypoint ID + // 6) Destination Waypoint Latitude 7) N or S + // 8) Destination Waypoint Longitude 9) E or W + // 10) Range to destination in nautical miles + // 11) Bearing to destination in degrees True + // 12) Destination closing velocity in knots + // 13) Arrival Status, A = Arrival Circle Entered 14) Checksum p = strchr(p, ',') + 1; // skip status nmea_float_t xte = 100000.; char xteDir = 'X'; @@ -339,15 +354,14 @@ bool Adafruit_GPS::parse(char *nmea) { if (!isEmpty(p)) parseStr(fromID, p, NMEA_MAX_WP_ID); p = strchr(p, ',') + 1; - nmea_float_t latitudeWP = - 0; // All the same position data for the next way point + nmea_float_t latitudeWP = 0; nmea_float_t longitudeWP = 0; int32_t latitude_fixedWP = 0; int32_t longitude_fixedWP = 0; nmea_float_t latitudeDegreesWP = 0; nmea_float_t longitudeDegreesWP = 0; - char latWP = 'N'; - char lonWP = 'W'; + char latWP = 'X'; + char lonWP = 'X'; // parse out both latitude and direction for WayPoint, then go to next // field, or fail @@ -371,8 +385,6 @@ bool Adafruit_GPS::parse(char *nmea) { } p = strchr(p, ',') + 1; p = strchr(p, ',') + 1; - p = strchr(p, ',') + 1; - p = strchr(p, ',') + 1; if (!isEmpty(p)) newDataValue(NMEA_DISTWP, atof(p)); p = strchr(p, ',') + 1; From 59c1a4acbd5b491825f333c57df632665992a163 Mon Sep 17 00:00:00 2001 From: Rick Sellens Date: Fri, 7 Feb 2020 20:04:33 -0500 Subject: [PATCH 09/10] casts to make unambiguous on UNO --- src/Adafruit_GPS.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Adafruit_GPS.cpp b/src/Adafruit_GPS.cpp index bec9556..c6acd61 100644 --- a/src/Adafruit_GPS.cpp +++ b/src/Adafruit_GPS.cpp @@ -385,7 +385,7 @@ char Adafruit_GPS::read(void) { _buff_idx++; } else { // refill the buffer! - if (gpsI2C->requestFrom((uint16_t)0x10, (uint8_t)GPS_MAX_I2C_TRANSFER, true) == + if (gpsI2C->requestFrom((uint8_t)0x10, (uint8_t)GPS_MAX_I2C_TRANSFER, (uint8_t) true) == GPS_MAX_I2C_TRANSFER) { // got data! _buff_max = 0; From fdda5b6e1ebd76545d90007e74fc9b26f97f48b4 Mon Sep 17 00:00:00 2001 From: Rick Sellens Date: Fri, 7 Feb 2020 20:20:30 -0500 Subject: [PATCH 10/10] clang --- src/Adafruit_GPS.cpp | 10 +++++----- src/NMEA_build.cpp | 4 ++-- src/NMEA_parse.cpp | 5 +++-- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/Adafruit_GPS.cpp b/src/Adafruit_GPS.cpp index c6acd61..2d8f25a 100644 --- a/src/Adafruit_GPS.cpp +++ b/src/Adafruit_GPS.cpp @@ -349,11 +349,11 @@ size_t Adafruit_GPS::write(uint8_t c) { /**************************************************************************/ /*! - @brief Read one character from the GPS device. - + @brief Read one character from the GPS device. + Call very frequently and multiple times per opportunity or the buffer may overflow if there are frequent NMEA sentences. An 82 character NMEA - sentence 10 times per second will require 820 calls per second, and + sentence 10 times per second will require 820 calls per second, and once a loop() may not be enough. Check for newNMEAreceived() after at least every 10 calls, or you may miss some short sentences. @return The character that we received, or 0 if nothing was available @@ -385,8 +385,8 @@ char Adafruit_GPS::read(void) { _buff_idx++; } else { // refill the buffer! - if (gpsI2C->requestFrom((uint8_t)0x10, (uint8_t)GPS_MAX_I2C_TRANSFER, (uint8_t) true) == - GPS_MAX_I2C_TRANSFER) { + if (gpsI2C->requestFrom((uint8_t)0x10, (uint8_t)GPS_MAX_I2C_TRANSFER, + (uint8_t) true) == GPS_MAX_I2C_TRANSFER) { // got data! _buff_max = 0; char curr_char = 0; diff --git a/src/NMEA_build.cpp b/src/NMEA_build.cpp index 201f30c..a45dad4 100644 --- a/src/NMEA_build.cpp +++ b/src/NMEA_build.cpp @@ -570,9 +570,9 @@ char *Adafruit_GPS::build(char *nmea, const char *thisSource, addChecksum(nmea); // Successful completion if (!noCRLF) { // Add Carriage Return and Line Feed to comply with NMEA-183 - sprintf(nmea, "%s\r\n", nmea); + sprintf(nmea, "%s\r\n", nmea); } - return nmea; // return pointer to finished product + return nmea; // return pointer to finished product } #endif // NMEA_EXTENSIONS diff --git a/src/NMEA_parse.cpp b/src/NMEA_parse.cpp index a7bae50..63be746 100644 --- a/src/NMEA_parse.cpp +++ b/src/NMEA_parse.cpp @@ -782,9 +782,10 @@ bool Adafruit_GPS::parseTime(char *p) { seconds = (time % 100); char *dec = strchr(p, '.'); char *comstar = min(strchr(p, ','), strchr(p, '*')); - if(dec != NULL && comstar != NULL && dec < comstar) + if (dec != NULL && comstar != NULL && dec < comstar) milliseconds = atof(p) * 1000; - else milliseconds = 0; + else + milliseconds = 0; lastTime = sentTime; return true; }