diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..5008ddf Binary files /dev/null and b/.DS_Store differ diff --git a/Adafruit_GPS.cpp b/Adafruit_GPS.cpp old mode 100755 new mode 100644 index 390550d..12adfe5 --- a/Adafruit_GPS.cpp +++ b/Adafruit_GPS.cpp @@ -205,14 +205,23 @@ boolean Adafruit_GPS::parse(char *nmea) { } } -#ifdef NMEA_EXTENSIONS //********************************************Sentences not required for basic GPS functionality - else if (!strcmp(thisSentence,"TXT")){ //********************************************TXT - if (!isEmpty(p)) txtTot = atoi(p); p = strchr(p, ',')+1; - if (!isEmpty(p)) txtN = atoi(p); p = strchr(p, ',')+1; - if (!isEmpty(p)) txtID = atoi(p); p = strchr(p, ',')+1; - if (!isEmpty(p)) parseStr(txtTXT,p,61); // copy the text to NMEA TXT max of 61 characters +#ifdef NMEA_EXTENSIONS //********************************************Sentences + //not required for basic GPS functionality + else if (!strcmp(thisSentence, + "TXT")) { //********************************************TXT + if (!isEmpty(p)) + txtTot = atoi(p); + p = strchr(p, ',') + 1; + if (!isEmpty(p)) + txtN = atoi(p); + p = strchr(p, ',') + 1; + if (!isEmpty(p)) + txtID = atoi(p); + p = strchr(p, ',') + 1; + if (!isEmpty(p)) + parseStr(txtTXT, p, 61); // copy the text to NMEA TXT max of 61 characters } -#endif // NMEA_EXTENSIONS +#endif // NMEA_EXTENSIONS // we dont parse the remaining, yet! else @@ -307,7 +316,7 @@ const char *Adafruit_GPS::tokenOnList(char *token, const char **list) { /**************************************************************************/ /*! - @brief Parse a string token from pointer p to the next comma, asterisk + @brief Parse a string token from pointer p to the next comma, asterisk or end of string. @param buff Pointer to the buffer to store the string in @param p Pointer into a string @@ -315,22 +324,22 @@ const char *Adafruit_GPS::tokenOnList(char *token, const char **list) { @return Pointer to the string buffer */ /**************************************************************************/ -char * Adafruit_GPS::parseStr(char * buff, char *p, int n) { +char *Adafruit_GPS::parseStr(char *buff, char *p, int n) { char *e = strchr(p, ','); int len = 0; - if(e){ + if (e) { len = min(e - p, n - 1); - strncpy(buff,p,len); // copy up to the comma + strncpy(buff, p, len); // copy up to the comma buff[len] = 0; } else { - e = strchr(p, '*'); - if(e){ + e = strchr(p, '*'); + if (e) { len = min(e - p, n - 1); - strncpy(buff,p,len); // or up to the * - buff[e-p] = 0; + strncpy(buff, p, len); // or up to the * + buff[e - p] = 0; } else { - len = min((int) strlen(p), n - 1); - strncpy(buff,p,len); // or to the end or max capacity + len = min((int)strlen(p), n - 1); + strncpy(buff, p, len); // or to the end or max capacity } } return buff; @@ -339,15 +348,17 @@ char * Adafruit_GPS::parseStr(char * buff, char *p, int n) { /**************************************************************************/ /*! @brief Is the field empty, or should we try conversion? Won't work - for a text field that starts with an asterisk or a comma, but that + for a text field that starts with an asterisk or a comma, but that probably violates the NMEA-183 standard. @param pStart Pointer to the location of the token in the NMEA string @return true if empty field, false if something there */ /**************************************************************************/ bool Adafruit_GPS::isEmpty(char *pStart) { - if (',' != *pStart && '*' != *pStart && pStart != NULL) return false; - else return true; + if (',' != *pStart && '*' != *pStart && pStart != NULL) + return false; + else + return true; } /**************************************************************************/ @@ -1044,36 +1055,34 @@ static boolean strStartsWith(const char *str, const char *prefix) { to make the timing look like the sentence arrived from the GPS. */ /**************************************************************************/ -void Adafruit_GPS::resetSentTime(){ - sentTime = millis(); -} +void Adafruit_GPS::resetSentTime() { sentTime = millis(); } /**************************************************************************/ /*! - @brief Build an NMEA sentence string based on the relevant variables. - Sentences start with a $, then a two character source identifier, then - a three character sentence name that defines the format, then a comma - and more comma separated fields defined by the sentence name. There are - many sentences listed that are not yet supported. Most of these sentence + @brief Build an NMEA sentence string based on the relevant variables. + Sentences start with a $, then a two character source identifier, then + a three character sentence name that defines the format, then a comma + and more comma separated fields defined by the sentence name. There are + many sentences listed that are not yet supported. Most of these sentence definitions were found at http://fort21.ru/download/NMEAdescription.pdf - build() will work with other lengths for source and sentence to allow + build() will work with other lengths for source and sentence to allow extension to building proprietary sentences like $PMTK220,100*2F. - build() will not work properly in an environment that does not support + build() will not work properly in an environment that does not support the %f floating point formatter in sprintf(), and will return NULL. - build() adds Carriage Return and Line Feed to sentences to conform to + build() adds Carriage Return and Line Feed to sentences to conform to NMEA-183, so send your output with a print, not a println. - Some of the data in these test sentences may be arbitrary, e.g. for the - TXT sentence which has a more complicated protocol for multiple lines - sent as a message set. Also, the data in the class variables are presumed - to be valid, so these sentences may contain values that are stale, or + Some of the data in these test sentences may be arbitrary, e.g. for the + TXT sentence which has a more complicated protocol for multiple lines + sent as a message set. Also, the data in the class variables are presumed + to be valid, so these sentences may contain values that are stale, or the result of initialization rather than measurement. - + @param nmea Pointer to the NMEA string buffer. Must be big enough to - hold the sentence. No guarantee what will be in it if the + hold the sentence. No guarantee what will be in it if the building of the sentence fails. @param thisSource Pointer to the source name string (2 upper case) @param thisSentence Pointer to the sentence name string (3 upper case) @@ -1081,59 +1090,72 @@ void Adafruit_GPS::resetSentTime(){ @return Pointer to sentence if successful, NULL if fails */ /**************************************************************************/ -char * Adafruit_GPS::build(char *nmea, const char *thisSource, const char *thisSentence, char ref) { - sprintf(nmea,"%6.2f",123.45); // fail if sprintf() doesn't handle floats - if(strcmp(nmea,"123.45")) return NULL; +char *Adafruit_GPS::build(char *nmea, const char *thisSource, + const char *thisSentence, char ref) { + sprintf(nmea, "%6.2f", 123.45); // fail if sprintf() doesn't handle floats + if (strcmp(nmea, "123.45")) + return NULL; *nmea = '$'; char *p = nmea + 1; // Pointer to move through the sentence - strncpy(p,thisSource,strlen(thisSource)); p += strlen(thisSource); - strncpy(p,thisSentence,strlen(thisSentence)); p += strlen(thisSentence); - *p = ','; p += 1; //Now $XXSSS, and need to add argument fields - // This may look inefficient, but an M0 will get down the list in about 1 us / strcmp()! - // Put the GPS sentences from Adafruit_GPS at the top to make pruning excess code easier. - // Otherwise, keep them alphabetical for ease of reading. + strncpy(p, thisSource, strlen(thisSource)); + p += strlen(thisSource); + strncpy(p, thisSentence, strlen(thisSentence)); + p += strlen(thisSentence); + *p = ','; + p += 1; // Now $XXSSS, and need to add argument fields + // This may look inefficient, but an M0 will get down the list in about 1 us / + // strcmp()! Put the GPS sentences from Adafruit_GPS at the top to make + // pruning excess code easier. Otherwise, keep them alphabetical for ease of + // reading. - if (!strcmp(thisSentence,"GGA")){ //********************************************GGA - //GGA Global Positioning System Fix Data. Time, Position and fix related data for a GPS receiver + if (!strcmp(thisSentence, + "GGA")) { //********************************************GGA + // GGA Global Positioning System Fix Data. Time, Position and fix related + // data for a GPS receiver // 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 - // | | | | | | | | | | | | | | | + // | | | | | | | | | | | | | | | //$--GGA,hhmmss.ss,ddmm.mm,a,dddmm.mm,a,x,xx,x.x,x.x,M,x.x,M,x.x,xxxx*hh - //1) Time (UTC) - //2) Latitude - //3) N or S (North or South) - //4) Longitude - //5) E or W (East or West) - //6) GPS Quality Indicator, 0 - fix not available, 1 - GPS fix, 2 - Differential GPS fix - //7) Number of satellites in view, 00 - 12 - //8) Horizontal Dilution of precision - //9) Antenna Altitude above/below mean-sea-level (geoid) - //10) Units of antenna altitude, meters - //11) Geoidal separation, the difference between the WGS-84 earth - // ellipsoid and mean-sea-level (geoid), "-" means mean-sea-level below ellipsoid - //12) Units of geoidal separation, meters - //13) Age of differential GPS data, time in seconds since last SC104 + // 1) Time (UTC) + // 2) Latitude + // 3) N or S (North or South) + // 4) Longitude + // 5) E or W (East or West) + // 6) GPS Quality Indicator, 0 - fix not available, 1 - GPS fix, 2 - + // Differential GPS fix 7) Number of satellites in view, 00 - 12 8) + // Horizontal Dilution of precision 9) Antenna Altitude above/below + // mean-sea-level (geoid) 10) Units of antenna altitude, meters 11) Geoidal + // separation, the difference between the WGS-84 earth + // ellipsoid and mean-sea-level (geoid), "-" means mean-sea-level below + // ellipsoid + // 12) Units of geoidal separation, meters + // 13) Age of differential GPS data, time in seconds since last SC104 // type 1 or 9 update, null field when DGPS is not used - //14) Differential reference station ID, 0000-1023 - //15) Checksum - sprintf(p,"%09.2f,%09.4f,%c,%010.4f,%c,%d,%02d,%f,%f,M,%f,M,,",hour*10000L + minute*100L + seconds + milliseconds/1000., - latitude,lat,longitude,lon,fixquality,satellites,HDOP,altitude,geoidheight); + // 14) Differential reference station ID, 0000-1023 + // 15) Checksum + sprintf(p, "%09.2f,%09.4f,%c,%010.4f,%c,%d,%02d,%f,%f,M,%f,M,,", + hour * 10000L + minute * 100L + seconds + milliseconds / 1000., + latitude, lat, longitude, lon, fixquality, satellites, HDOP, + altitude, geoidheight); - } else if (!strcmp(thisSentence,"GLL")){ //********************************************GLL - //GLL Geographic Position – Latitude/Longitude + } else if (!strcmp(thisSentence, + "GLL")) { //********************************************GLL + // GLL Geographic Position – Latitude/Longitude // 1 2 3 4 5 6 7 // | | | | | | | //$--GLL,llll.ll,a,yyyyy.yy,a,hhmmss.ss,A*hh - //1) Latitude ddmm.mm format - //2) N or S (North or South) - //3) Longitude dddmm.mm format - //4) E or W (East or West) - //5) Time (UTC) - //6) Status A - Data Valid, V - Data Invalid - //7) Checksum - sprintf(p,"%09.4f,%c,%010.4f,%c,%09.2f,A",latitude,lat,longitude,lon,hour*10000L + minute*100L + seconds + milliseconds/1000.); + // 1) Latitude ddmm.mm format + // 2) N or S (North or South) + // 3) Longitude dddmm.mm format + // 4) E or W (East or West) + // 5) Time (UTC) + // 6) Status A - Data Valid, V - Data Invalid + // 7) Checksum + sprintf(p, "%09.4f,%c,%010.4f,%c,%09.2f,A", latitude, lat, longitude, lon, + hour * 10000L + minute * 100L + seconds + milliseconds / 1000.); - } else if (!strcmp(thisSentence,"GSA")){ //******************************************** - //GSA GPS DOP and active satellites + } else if (!strcmp(thisSentence, + "GSA")) { //******************************************** + // GSA GPS DOP and active satellites // 1 2 3 14 15 16 17 18 // | | | | | | | | //$--GSA,a,a,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x.x,x.x,x.x*hh @@ -1142,15 +1164,16 @@ char * Adafruit_GPS::build(char *nmea, const char *thisSource, const char *thisS // 3) ID of 1st satellite used for fix // 4) ID of 2nd satellite used for fix // ... - //14) ID of 12th satellite used for fix - //15) PDOP in meters - //16) HDOP in meters - //17) VDOP in meters - //18) Checksum - return NULL; + // 14) ID of 12th satellite used for fix + // 15) PDOP in meters + // 16) HDOP in meters + // 17) VDOP in meters + // 18) Checksum + return NULL; - } else if (!strcmp(thisSentence,"RMC")){ //********************************************RMC - //RMC Recommended Minimum Navigation Information + } else if (!strcmp(thisSentence, + "RMC")) { //********************************************RMC + // RMC Recommended Minimum Navigation Information // 12 // 1 2 3 4 5 6 7 8 9 10 11 | // | | | | | | | | | | | | @@ -1164,32 +1187,36 @@ char * Adafruit_GPS::build(char *nmea, const char *thisSource, const char *thisS // 7) Speed over ground, knots // 8) Track made good, degrees true // 9) Date, ddmmyy - //10) Magnetic Variation, degrees - //11) E or W - //12) Checksum - sprintf(p,"%09.2f,A,%09.4f,%c,%010.4f,%c,%f,%f,%06d,%f,%c",hour*10000L + minute*100L + seconds + milliseconds/1000., - latitude,lat,longitude,lon,speed,angle,day*10000+month*100+year,magvariation,mag); + // 10) Magnetic Variation, degrees + // 11) E or W + // 12) Checksum + sprintf(p, "%09.2f,A,%09.4f,%c,%010.4f,%c,%f,%f,%06d,%f,%c", + hour * 10000L + minute * 100L + seconds + milliseconds / 1000., + latitude, lat, longitude, lon, speed, angle, + day * 10000 + month * 100 + year, magvariation, mag); - } else if (!strcmp(thisSentence,"TXT")){ //********************************************TXT + } else if (!strcmp(thisSentence, + "TXT")) { //********************************************TXT // as mentioned in https://github.com/adafruit/Adafruit_GPS/issues/95 - //TXT Text Transmission + // TXT Text Transmission // 1 2 3 4 5 // | | | | | //$--TXT,xx,xx,xx,c--c*hh - //1) Total Number of Sentences 01-99 - //2) Sentence Number 01-99 - //3) Text Identifier 01-99 - //4) Text String, max 61 characters - //5) Checksum - sprintf(p,"01,01,23,This is the text of the sample message"); - - } else { - return NULL; // didn't find a match for the build request + // 1) Total Number of Sentences 01-99 + // 2) Sentence Number 01-99 + // 3) Text Identifier 01-99 + // 4) Text String, max 61 characters + // 5) Checksum + sprintf(p, "01,01,23,This is the text of the sample message"); + + } else { + return NULL; // didn't find a match for the build request } - 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 + 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 } -#endif // NMEA_EXTENSIONS +#endif // NMEA_EXTENSIONS diff --git a/Adafruit_GPS.h b/Adafruit_GPS.h index 19b1a5d..e752127 100644 --- a/Adafruit_GPS.h +++ b/Adafruit_GPS.h @@ -28,11 +28,11 @@ /**************************************************************************/ /** - Comment out the definition of NMEA_EXTENSIONS to make the library use as - little memory as possible for GPS functionality only. The ARDUINO_ARCH_AVR + Comment out the definition of NMEA_EXTENSIONS to make the library use as + little memory as possible for GPS functionality only. The ARDUINO_ARCH_AVR test should leave it out of any compilations for the UNO and similar. */ #ifndef ARDUINO_ARCH_AVR -#define NMEA_EXTENSIONS ///< if defined will include more NMEA sentences +#define NMEA_EXTENSIONS ///< if defined will include more NMEA sentences #endif #define USE_SW_SERIAL ///< comment this out if you don't want to include @@ -235,16 +235,16 @@ public: float speed; ///< Current speed over ground in knots float angle; ///< Course in degrees from true north float magvariation; ///< Magnetic variation in degrees (vs. true north) - float HDOP; ///< Horizontal Dilution of Precision - relative accuracy of - ///< horizontal position - float VDOP; ///< Vertical Dilution of Precision - relative accuracy of - ///< vertical position - float PDOP; ///< Position Dilution of Precision - Complex maths derives a - ///< simple, single number for each kind of DOP - char lat = 'X'; ///< N/S - char lon = 'X'; ///< E/W - char mag = 'X'; ///< Magnetic variation direction - boolean fix; ///< Have a fix? + float HDOP; ///< Horizontal Dilution of Precision - relative accuracy of + ///< horizontal position + float VDOP; ///< Vertical Dilution of Precision - relative accuracy of + ///< vertical position + float PDOP; ///< Position Dilution of Precision - Complex maths derives a + ///< simple, single number for each kind of DOP + char lat = 'X'; ///< N/S + char lon = 'X'; ///< E/W + char mag = 'X'; ///< Magnetic variation direction + boolean fix; ///< Have a fix? uint8_t fixquality; ///< Fix quality (0, 1, 2 = Invalid, GPS, DGPS) uint8_t fixquality_3d; ///< 3D fix quality (1, 3, 3 = Nofix, 2D fix, 3D fix) uint8_t satellites; ///< Number of satellites in use @@ -268,20 +268,21 @@ public: #ifdef NMEA_EXTENSIONS // NMEA additional public functions - char * build(char *nmea, const char *thisSource, const char *thisSentence, char ref = 'R'); + char *build(char *nmea, const char *thisSource, const char *thisSentence, + char ref = 'R'); void resetSentTime(); - + // NMEA additional public variables - char txtTXT[63] = {0}; ///< text content from most recent TXT sentence - int txtTot = 0; ///< total TXT sentences in group - int txtID = 0; ///< id of the text message - int txtN = 0; ///< the TXT sentence number -#endif // NMEA_EXTENSIONS + char txtTXT[63] = {0}; ///< text content from most recent TXT sentence + int txtTot = 0; ///< total TXT sentences in group + int txtID = 0; ///< id of the text message + int txtN = 0; ///< the TXT sentence number +#endif // NMEA_EXTENSIONS private: const char *tokenOnList(char *token, const char **list); - char * parseStr(char * buff, char *p, int n); - bool isEmpty(char *pStart); + char *parseStr(char *buff, char *p, int n); + bool isEmpty(char *pStart); void parseTime(char *); void parseLat(char *); boolean parseLatDir(char *); diff --git a/examples/GPS_HardwareSerial_Timing/GPS_HardwareSerial_Timing.ino b/examples/GPS_HardwareSerial_Timing/GPS_HardwareSerial_Timing.ino index c917bb0..41ab240 100644 --- a/examples/GPS_HardwareSerial_Timing/GPS_HardwareSerial_Timing.ino +++ b/examples/GPS_HardwareSerial_Timing/GPS_HardwareSerial_Timing.ino @@ -1,12 +1,14 @@ -// Test code for Ultimate GPS Using Hardware Serial (e.g. GPS Flora or FeatherWing) +// 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 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. // -// It also shows how to take advantage of the build() function to generate test sentences. -// The additional code is within #ifdef NMEA_EXTENSIONS and #endif tags. +// It also shows how to take advantage of the build() function to generate test +// sentences. The additional code is within #ifdef NMEA_EXTENSIONS and #endif +// tags. // // 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 @@ -31,9 +33,9 @@ Adafruit_GPS GPS(&GPSSerial); #ifdef NMEA_EXTENSIONS -// Create another GPS object to hold the state of the boat, with no communications, -// so don't call Boat.begin() in setup. -// We will build some fake sentences from the Boat data to feed to GPS for testing. +// Create another GPS object to hold the state of the boat, with no +// communications, so don't call Boat.begin() in setup. We will build some fake +// sentences from the Boat data to feed to GPS for testing. Adafruit_GPS Boat(&GPSSerial); #endif @@ -43,30 +45,31 @@ Adafruit_GPS Boat(&GPSSerial); uint32_t timer = millis(); +void setup() { + // while (!Serial); // uncomment to have the sketch wait until Serial is + // ready -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 + // 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 + // 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 + // 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_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 + // 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); @@ -83,20 +86,26 @@ void loop() // run over and over again 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 (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 + // 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(); + if (timer > millis()) + timer = millis(); - // approximately every 2 seconds or so, random intervals, print out the current stats + // 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 @@ -104,74 +113,105 @@ void loop() // run over and over again // 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(); + 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"); + // 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"); + 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("Time [s] since last fix: "); Serial.println(GPS.secondsSinceFix(),3); - Serial.print(" since last GPS time: "); Serial.println(GPS.secondsSinceTime(),3); - Serial.print(" since last GPS date: "); Serial.println(GPS.secondsSinceDate(),3); + Serial.print("Fix: "); + Serial.print((int)GPS.fix); + Serial.print(" quality: "); + Serial.println((int)GPS.fixquality); + Serial.print("Time [s] since last fix: "); + Serial.println(GPS.secondsSinceFix(), 3); + Serial.print(" since last GPS time: "); + Serial.println(GPS.secondsSinceTime(), 3); + Serial.print(" since last GPS date: "); + Serial.println(GPS.secondsSinceDate(), 3); if (GPS.fix) { Serial.print("Location: "); - Serial.print(GPS.latitude, 4); Serial.print(GPS.lat); + 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); + 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); } #ifdef NMEA_EXTENSIONS char latestBoat[200] = ""; - updateBoat(); //create some test data in Boat - Boat.build(latestBoat,"GN","RMC"); //make a sentence from Boat data - Serial.print("\nbuild() test output -->"); // - Serial.print(latestBoat); // - GPS.resetSentTime(); //make timing look like it came in on GPS - GPS.parse(latestBoat); //parse the test data and store in GPS + updateBoat(); // create some test data in Boat + Boat.build(latestBoat, "GN", "RMC"); // make a sentence from Boat data + Serial.print("\nbuild() test output -->"); // + Serial.print(latestBoat); // + GPS.resetSentTime(); // make timing look like it came in on GPS + GPS.parse(latestBoat); // parse the test data and store in GPS #endif } } #ifdef NMEA_EXTENSIONS -void updateBoat(){ //fill up the boat values with some test data to use in build() +void updateBoat() { // fill up the boat values with some test data to use in + // build() double t = millis() / 1000.; - double theta = t / 100.; //slow - double gamma = theta * 10; //faster - Boat.latitude = 4400 + sin(theta)*60; + double theta = t / 100.; // slow + double gamma = theta * 10; // faster + Boat.latitude = 4400 + sin(theta) * 60; Boat.lat = 'N'; - Boat.longitude = 7600 + cos(theta)*60; + Boat.longitude = 7600 + cos(theta) * 60; Boat.lon = 'W'; Boat.fixquality = 2; Boat.speed = 3 + sin(gamma); Boat.hour = abs(cos(theta)) * 24; - Boat.minute = 30 + sin(theta/2) * 30; + Boat.minute = 30 + sin(theta / 2) * 30; Boat.seconds = 30 + sin(gamma) * 30; - Boat.milliseconds = 500+ sin(gamma) * 500; - Boat.year = 1+abs(sin(theta)) * 25; - Boat.month = 1+abs(sin(gamma)) * 11; - Boat.day = 1+ abs(sin(gamma)) * 26; + Boat.milliseconds = 500 + sin(gamma) * 500; + Boat.year = 1 + abs(sin(theta)) * 25; + Boat.month = 1 + abs(sin(gamma)) * 11; + Boat.day = 1 + abs(sin(gamma)) * 26; Boat.satellites = abs(cos(gamma)) * 10; } #endif