diff --git a/src/Adafruit_GPS.cpp b/src/Adafruit_GPS.cpp index 65e5c10..2d8f25a 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 */ /**************************************************************************/ @@ -379,8 +385,8 @@ char Adafruit_GPS::read(void) { _buff_idx++; } else { // refill the buffer! - if (gpsI2C->requestFrom(0x10, GPS_MAX_I2C_TRANSFER, 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/Adafruit_GPS.h b/src/Adafruit_GPS.h index fe9baee..bf190b4 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); @@ -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 diff --git a/src/NMEA_build.cpp b/src/NMEA_build.cpp index 8b78139..a45dad4 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,9 +569,10 @@ 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 - return nmea; // return pointer to finished product + 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 } #endif // NMEA_EXTENSIONS 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 diff --git a/src/NMEA_parse.cpp b/src/NMEA_parse.cpp index 822fc57..63be746 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; @@ -545,6 +557,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 @@ -588,7 +601,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 @@ -764,8 +780,12 @@ 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; }