clanged files

This commit is contained in:
Rick Sellens 2020-01-18 10:23:14 -05:00
parent a41cbce062
commit c8d4e037e7
4 changed files with 270 additions and 202 deletions

BIN
.DS_Store vendored Normal file

Binary file not shown.

241
Adafruit_GPS.cpp Executable file → Normal file
View File

@ -205,14 +205,23 @@ boolean Adafruit_GPS::parse(char *nmea) {
} }
} }
#ifdef NMEA_EXTENSIONS //********************************************Sentences not required for basic GPS functionality #ifdef NMEA_EXTENSIONS //********************************************Sentences
else if (!strcmp(thisSentence,"TXT")){ //********************************************TXT //not required for basic GPS functionality
if (!isEmpty(p)) txtTot = atoi(p); p = strchr(p, ',')+1; else if (!strcmp(thisSentence,
if (!isEmpty(p)) txtN = atoi(p); p = strchr(p, ',')+1; "TXT")) { //********************************************TXT
if (!isEmpty(p)) txtID = atoi(p); p = strchr(p, ',')+1; if (!isEmpty(p))
if (!isEmpty(p)) parseStr(txtTXT,p,61); // copy the text to NMEA TXT max of 61 characters 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! // we dont parse the remaining, yet!
else 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. or end of string.
@param buff Pointer to the buffer to store the string in @param buff Pointer to the buffer to store the string in
@param p Pointer into a string @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 @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, ','); char *e = strchr(p, ',');
int len = 0; int len = 0;
if(e){ if (e) {
len = min(e - p, n - 1); 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; buff[len] = 0;
} else { } else {
e = strchr(p, '*'); e = strchr(p, '*');
if(e){ if (e) {
len = min(e - p, n - 1); len = min(e - p, n - 1);
strncpy(buff,p,len); // or up to the * strncpy(buff, p, len); // or up to the *
buff[e-p] = 0; buff[e - p] = 0;
} else { } else {
len = min((int) strlen(p), n - 1); len = min((int)strlen(p), n - 1);
strncpy(buff,p,len); // or to the end or max capacity strncpy(buff, p, len); // or to the end or max capacity
} }
} }
return buff; 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 @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. probably violates the NMEA-183 standard.
@param pStart Pointer to the location of the token in the NMEA string @param pStart Pointer to the location of the token in the NMEA string
@return true if empty field, false if something there @return true if empty field, false if something there
*/ */
/**************************************************************************/ /**************************************************************************/
bool Adafruit_GPS::isEmpty(char *pStart) { bool Adafruit_GPS::isEmpty(char *pStart) {
if (',' != *pStart && '*' != *pStart && pStart != NULL) return false; if (',' != *pStart && '*' != *pStart && pStart != NULL)
else return true; 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. to make the timing look like the sentence arrived from the GPS.
*/ */
/**************************************************************************/ /**************************************************************************/
void Adafruit_GPS::resetSentTime(){ void Adafruit_GPS::resetSentTime() { sentTime = millis(); }
sentTime = millis();
}
/**************************************************************************/ /**************************************************************************/
/*! /*!
@brief Build an NMEA sentence string based on the relevant variables. @brief Build an NMEA sentence string based on the relevant variables.
Sentences start with a $, then a two character source identifier, then Sentences start with a $, then a two character source identifier, then
a three character sentence name that defines the format, then a comma a three character sentence name that defines the format, then a comma
and more comma separated fields defined by the sentence name. There are and more comma separated fields defined by the sentence name. There are
many sentences listed that are not yet supported. Most of these sentence many sentences listed that are not yet supported. Most of these sentence
definitions were found at http://fort21.ru/download/NMEAdescription.pdf 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. 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. 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. 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 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 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 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 to be valid, so these sentences may contain values that are stale, or
the result of initialization rather than measurement. the result of initialization rather than measurement.
@param nmea Pointer to the NMEA string buffer. Must be big enough to @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. building of the sentence fails.
@param thisSource Pointer to the source name string (2 upper case) @param thisSource Pointer to the source name string (2 upper case)
@param thisSentence Pointer to the sentence name string (3 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 @return Pointer to sentence if successful, NULL if fails
*/ */
/**************************************************************************/ /**************************************************************************/
char * Adafruit_GPS::build(char *nmea, const char *thisSource, const char *thisSentence, char ref) { char *Adafruit_GPS::build(char *nmea, const char *thisSource,
sprintf(nmea,"%6.2f",123.45); // fail if sprintf() doesn't handle floats const char *thisSentence, char ref) {
if(strcmp(nmea,"123.45")) return NULL; sprintf(nmea, "%6.2f", 123.45); // fail if sprintf() doesn't handle floats
if (strcmp(nmea, "123.45"))
return NULL;
*nmea = '$'; *nmea = '$';
char *p = nmea + 1; // Pointer to move through the sentence char *p = nmea + 1; // Pointer to move through the sentence
strncpy(p,thisSource,strlen(thisSource)); p += strlen(thisSource); strncpy(p, thisSource, strlen(thisSource));
strncpy(p,thisSentence,strlen(thisSentence)); p += strlen(thisSentence); p += strlen(thisSource);
*p = ','; p += 1; //Now $XXSSS, and need to add argument fields strncpy(p, thisSentence, strlen(thisSentence));
// This may look inefficient, but an M0 will get down the list in about 1 us / strcmp()! p += strlen(thisSentence);
// Put the GPS sentences from Adafruit_GPS at the top to make pruning excess code easier. *p = ',';
// Otherwise, keep them alphabetical for ease of reading. 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 if (!strcmp(thisSentence,
//GGA Global Positioning System Fix Data. Time, Position and fix related data for a GPS receiver "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 // 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 //$--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) // 1) Time (UTC)
//2) Latitude // 2) Latitude
//3) N or S (North or South) // 3) N or S (North or South)
//4) Longitude // 4) Longitude
//5) E or W (East or West) // 5) E or W (East or West)
//6) GPS Quality Indicator, 0 - fix not available, 1 - GPS fix, 2 - Differential GPS fix // 6) GPS Quality Indicator, 0 - fix not available, 1 - GPS fix, 2 -
//7) Number of satellites in view, 00 - 12 // Differential GPS fix 7) Number of satellites in view, 00 - 12 8)
//8) Horizontal Dilution of precision // Horizontal Dilution of precision 9) Antenna Altitude above/below
//9) Antenna Altitude above/below mean-sea-level (geoid) // mean-sea-level (geoid) 10) Units of antenna altitude, meters 11) Geoidal
//10) Units of antenna altitude, meters // separation, the difference between the WGS-84 earth
//11) Geoidal separation, the difference between the WGS-84 earth // ellipsoid and mean-sea-level (geoid), "-" means mean-sea-level below
// ellipsoid and mean-sea-level (geoid), "-" means mean-sea-level below ellipsoid // ellipsoid
//12) Units of geoidal separation, meters // 12) Units of geoidal separation, meters
//13) Age of differential GPS data, time in seconds since last SC104 // 13) Age of differential GPS data, time in seconds since last SC104
// type 1 or 9 update, null field when DGPS is not used // type 1 or 9 update, null field when DGPS is not used
//14) Differential reference station ID, 0000-1023 // 14) Differential reference station ID, 0000-1023
//15) Checksum // 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., sprintf(p, "%09.2f,%09.4f,%c,%010.4f,%c,%d,%02d,%f,%f,M,%f,M,,",
latitude,lat,longitude,lon,fixquality,satellites,HDOP,altitude,geoidheight); hour * 10000L + minute * 100L + seconds + milliseconds / 1000.,
latitude, lat, longitude, lon, fixquality, satellites, HDOP,
altitude, geoidheight);
} else if (!strcmp(thisSentence,"GLL")){ //********************************************GLL } else if (!strcmp(thisSentence,
//GLL Geographic Position Latitude/Longitude "GLL")) { //********************************************GLL
// GLL Geographic Position Latitude/Longitude
// 1 2 3 4 5 6 7 // 1 2 3 4 5 6 7
// | | | | | | | // | | | | | | |
//$--GLL,llll.ll,a,yyyyy.yy,a,hhmmss.ss,A*hh //$--GLL,llll.ll,a,yyyyy.yy,a,hhmmss.ss,A*hh
//1) Latitude ddmm.mm format // 1) Latitude ddmm.mm format
//2) N or S (North or South) // 2) N or S (North or South)
//3) Longitude dddmm.mm format // 3) Longitude dddmm.mm format
//4) E or W (East or West) // 4) E or W (East or West)
//5) Time (UTC) // 5) Time (UTC)
//6) Status A - Data Valid, V - Data Invalid // 6) Status A - Data Valid, V - Data Invalid
//7) Checksum // 7) Checksum
sprintf(p,"%09.4f,%c,%010.4f,%c,%09.2f,A",latitude,lat,longitude,lon,hour*10000L + minute*100L + seconds + milliseconds/1000.); 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")){ //******************************************** } else if (!strcmp(thisSentence,
//GSA GPS DOP and active satellites "GSA")) { //********************************************
// GSA GPS DOP and active satellites
// 1 2 3 14 15 16 17 18 // 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 //$--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 // 3) ID of 1st satellite used for fix
// 4) ID of 2nd satellite used for fix // 4) ID of 2nd satellite used for fix
// ... // ...
//14) ID of 12th satellite used for fix // 14) ID of 12th satellite used for fix
//15) PDOP in meters // 15) PDOP in meters
//16) HDOP in meters // 16) HDOP in meters
//17) VDOP in meters // 17) VDOP in meters
//18) Checksum // 18) Checksum
return NULL; return NULL;
} else if (!strcmp(thisSentence,"RMC")){ //********************************************RMC } else if (!strcmp(thisSentence,
//RMC Recommended Minimum Navigation Information "RMC")) { //********************************************RMC
// RMC Recommended Minimum Navigation Information
// 12 // 12
// 1 2 3 4 5 6 7 8 9 10 11 | // 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 // 7) Speed over ground, knots
// 8) Track made good, degrees true // 8) Track made good, degrees true
// 9) Date, ddmmyy // 9) Date, ddmmyy
//10) Magnetic Variation, degrees // 10) Magnetic Variation, degrees
//11) E or W // 11) E or W
//12) Checksum // 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., sprintf(p, "%09.2f,A,%09.4f,%c,%010.4f,%c,%f,%f,%06d,%f,%c",
latitude,lat,longitude,lon,speed,angle,day*10000+month*100+year,magvariation,mag); 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 // as mentioned in https://github.com/adafruit/Adafruit_GPS/issues/95
//TXT Text Transmission // TXT Text Transmission
// 1 2 3 4 5 // 1 2 3 4 5
// | | | | | // | | | | |
//$--TXT,xx,xx,xx,c--c*hh //$--TXT,xx,xx,xx,c--c*hh
//1) Total Number of Sentences 01-99 // 1) Total Number of Sentences 01-99
//2) Sentence Number 01-99 // 2) Sentence Number 01-99
//3) Text Identifier 01-99 // 3) Text Identifier 01-99
//4) Text String, max 61 characters // 4) Text String, max 61 characters
//5) Checksum // 5) Checksum
sprintf(p,"01,01,23,This is the text of the sample message"); sprintf(p, "01,01,23,This is the text of the sample message");
} else { } else {
return NULL; // didn't find a match for the build request return NULL; // didn't find a match for the build request
} }
addChecksum(nmea); // Successful completion addChecksum(nmea); // Successful completion
sprintf(nmea,"%s\r\n",nmea); // Add Carriage Return and Line Feed to comply with NMEA-183 sprintf(nmea, "%s\r\n",
return nmea; // return pointer to finished product 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

View File

@ -28,11 +28,11 @@
/**************************************************************************/ /**************************************************************************/
/** /**
Comment out the definition of NMEA_EXTENSIONS to make the library use as 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 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. */ test should leave it out of any compilations for the UNO and similar. */
#ifndef ARDUINO_ARCH_AVR #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 #endif
#define USE_SW_SERIAL ///< comment this out if you don't want to include #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 speed; ///< Current speed over ground in knots
float angle; ///< Course in degrees from true north float angle; ///< Course in degrees from true north
float magvariation; ///< Magnetic variation in degrees (vs. true north) float magvariation; ///< Magnetic variation in degrees (vs. true north)
float HDOP; ///< Horizontal Dilution of Precision - relative accuracy of float HDOP; ///< Horizontal Dilution of Precision - relative accuracy of
///< horizontal position ///< horizontal position
float VDOP; ///< Vertical Dilution of Precision - relative accuracy of float VDOP; ///< Vertical Dilution of Precision - relative accuracy of
///< vertical position ///< vertical position
float PDOP; ///< Position Dilution of Precision - Complex maths derives a float PDOP; ///< Position Dilution of Precision - Complex maths derives a
///< simple, single number for each kind of DOP ///< simple, single number for each kind of DOP
char lat = 'X'; ///< N/S char lat = 'X'; ///< N/S
char lon = 'X'; ///< E/W char lon = 'X'; ///< E/W
char mag = 'X'; ///< Magnetic variation direction char mag = 'X'; ///< Magnetic variation direction
boolean fix; ///< Have a fix? boolean fix; ///< Have a fix?
uint8_t fixquality; ///< Fix quality (0, 1, 2 = Invalid, GPS, DGPS) 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 fixquality_3d; ///< 3D fix quality (1, 3, 3 = Nofix, 2D fix, 3D fix)
uint8_t satellites; ///< Number of satellites in use uint8_t satellites; ///< Number of satellites in use
@ -268,20 +268,21 @@ public:
#ifdef NMEA_EXTENSIONS #ifdef NMEA_EXTENSIONS
// NMEA additional public functions // 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(); void resetSentTime();
// NMEA additional public variables // NMEA additional public variables
char txtTXT[63] = {0}; ///< text content from most recent TXT sentence char txtTXT[63] = {0}; ///< text content from most recent TXT sentence
int txtTot = 0; ///< total TXT sentences in group int txtTot = 0; ///< total TXT sentences in group
int txtID = 0; ///< id of the text message int txtID = 0; ///< id of the text message
int txtN = 0; ///< the TXT sentence number int txtN = 0; ///< the TXT sentence number
#endif // NMEA_EXTENSIONS #endif // NMEA_EXTENSIONS
private: private:
const char *tokenOnList(char *token, const char **list); const char *tokenOnList(char *token, const char **list);
char * parseStr(char * buff, char *p, int n); char *parseStr(char *buff, char *p, int n);
bool isEmpty(char *pStart); bool isEmpty(char *pStart);
void parseTime(char *); void parseTime(char *);
void parseLat(char *); void parseLat(char *);
boolean parseLatDir(char *); boolean parseLatDir(char *);

View File

@ -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 // 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 // elements to keep track of how long it has been since time and fix data have
// received. This approach lets you keep an up to date clock based on GPS time at // been received. This approach lets you keep an up to date clock based on GPS
// any time in between GPS fixes. // time at any time in between GPS fixes.
// //
// It also shows how to take advantage of the build() function to generate test sentences. // It also shows how to take advantage of the build() function to generate test
// The additional code is within #ifdef NMEA_EXTENSIONS and #endif tags. // 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 // 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 // Feathers or Flora where you have hardware Serial and no interrupt
@ -31,9 +33,9 @@
Adafruit_GPS GPS(&GPSSerial); Adafruit_GPS GPS(&GPSSerial);
#ifdef NMEA_EXTENSIONS #ifdef NMEA_EXTENSIONS
// Create another GPS object to hold the state of the boat, with no communications, // Create another GPS object to hold the state of the boat, with no
// so don't call Boat.begin() in setup. // communications, so don't call Boat.begin() in setup. We will build some fake
// We will build some fake sentences from the Boat data to feed to GPS for testing. // sentences from the Boat data to feed to GPS for testing.
Adafruit_GPS Boat(&GPSSerial); Adafruit_GPS Boat(&GPSSerial);
#endif #endif
@ -43,30 +45,31 @@ Adafruit_GPS Boat(&GPSSerial);
uint32_t timer = millis(); uint32_t timer = millis();
void setup() {
// while (!Serial); // uncomment to have the sketch wait until Serial is
// ready
void setup() // connect at 115200 so we can read the GPS fast enough and echo without
{ // dropping chars also spit it out
//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.begin(115200);
Serial.println("Adafruit GPS library basic test!"); Serial.println("Adafruit GPS library basic test!");
// 9600 NMEA is the default baud rate for Adafruit MTK GPS's- some use 4800 // 9600 NMEA is the default baud rate for Adafruit MTK GPS's- some use 4800
GPS.begin(9600); 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); GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA);
// uncomment this line to turn on only the "minimum recommended" data // uncomment this line to turn on only the "minimum recommended" data
//GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCONLY); // GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCONLY);
// For parsing data, we don't suggest using anything but either RMC only or RMC+GGA since // For parsing data, we don't suggest using anything but either RMC only or
// the parser doesn't care about other sentences at this time // RMC+GGA since the parser doesn't care about other sentences at this time
// Set the update rate (uncomment the one you want.) // 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_1HZ); // 1 Hz update rate
//GPS.sendCommand(PMTK_SET_NMEA_UPDATE_200_MILLIHERTZ); // 5 second update time // GPS.sendCommand(PMTK_SET_NMEA_UPDATE_200_MILLIHERTZ); // 5 second update
// time
GPS.sendCommand(PMTK_SET_NMEA_UPDATE_100_MILLIHERTZ); // 10 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 // For the parsing code to work nicely and have time to sort thru the data,
// print it out we don't suggest using anything higher than 1 Hz // and print it out we don't suggest using anything higher than 1 Hz
// Request updates on antenna status, comment out to keep quiet // Request updates on antenna status, comment out to keep quiet
GPS.sendCommand(PGCMD_ANTENNA); GPS.sendCommand(PGCMD_ANTENNA);
@ -83,20 +86,26 @@ void loop() // run over and over again
char c = GPS.read(); char c = GPS.read();
// if you want to debug, this is a good time to do it! // if you want to debug, this is a good time to do it!
if (GPSECHO) 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 a sentence is received, we can check the checksum, parse it...
if (GPS.newNMEAreceived()) { if (GPS.newNMEAreceived()) {
// a tricky thing here is if we print the NMEA sentence, or data // a tricky thing here is if we print the NMEA sentence, or data
// we end up not listening and catching other sentences! // we end up not listening and catching other sentences!
// so be very wary if using OUTPUT_ALLDATA and trytng to print out data // 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 // Serial.println(GPS.lastNMEA()); // this also sets the newNMEAreceived()
if (!GPS.parse(GPS.lastNMEA())) // this also sets the newNMEAreceived() flag to false // flag to false
return; // we can fail to parse a sentence in which case we should just wait for another 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 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; static unsigned nextInterval = 2000;
if (millis() - timer > nextInterval) { if (millis() - timer > nextInterval) {
timer = millis(); // reset the timer 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. // Time in seconds keeps increasing after we get the NMEA sentence.
// This estimate will lag real time due to transmission and parsing delays, // This estimate will lag real time due to transmission and parsing delays,
// but the lag should be small and should also be consistent. // 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 m = GPS.minute;
int h = GPS.hour; int h = GPS.hour;
int d = GPS.day; int d = GPS.day;
// Adjust time and day forward to account for elapsed time. // 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. // This will break at month boundaries!!! Humans will have to cope with
while(s > 60){ s -= 60; m++; } // April 31,32 etc.
while(m > 60){ m -= 60; h++; } while (s > 60) {
while(h > 24){ h -= 24; d++; } s -= 60;
// ISO Standard Date Format, with leading zeros https://xkcd.com/1179/ m++;
Serial.print("\nDate: "); }
Serial.print(GPS.year+2000, DEC); Serial.print("-"); while (m > 60) {
if(GPS.month < 10) Serial.print("0"); m -= 60;
Serial.print(GPS.month, DEC); Serial.print("-"); h++;
if(d < 10) Serial.print("0"); }
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(d, DEC);
Serial.print(" Time: "); Serial.print(" Time: ");
if(h < 10) Serial.print("0"); if (h < 10)
Serial.print(h, DEC); Serial.print(':'); Serial.print("0");
if(m < 10) Serial.print("0"); Serial.print(h, DEC);
Serial.print(m, DEC); Serial.print(':'); Serial.print(':');
if(s < 10) Serial.print("0"); if (m < 10)
Serial.print("0");
Serial.print(m, DEC);
Serial.print(':');
if (s < 10)
Serial.print("0");
Serial.println(s, 3); Serial.println(s, 3);
Serial.print("Fix: "); Serial.print((int)GPS.fix); Serial.print("Fix: ");
Serial.print(" quality: "); Serial.println((int)GPS.fixquality); Serial.print((int)GPS.fix);
Serial.print("Time [s] since last fix: "); Serial.println(GPS.secondsSinceFix(),3); Serial.print(" quality: ");
Serial.print(" since last GPS time: "); Serial.println(GPS.secondsSinceTime(),3); Serial.println((int)GPS.fixquality);
Serial.print(" since last GPS date: "); Serial.println(GPS.secondsSinceDate(),3); 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) { if (GPS.fix) {
Serial.print("Location: "); 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(", ");
Serial.print(GPS.longitude, 4); Serial.println(GPS.lon); Serial.print(GPS.longitude, 4);
Serial.print("Speed (knots): "); Serial.println(GPS.speed); Serial.println(GPS.lon);
Serial.print("Angle: "); Serial.println(GPS.angle); Serial.print("Speed (knots): ");
Serial.print("Altitude: "); Serial.println(GPS.altitude); Serial.println(GPS.speed);
Serial.print("Satellites: "); Serial.println((int)GPS.satellites); 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 #ifdef NMEA_EXTENSIONS
char latestBoat[200] = ""; char latestBoat[200] = "";
updateBoat(); //create some test data in Boat updateBoat(); // create some test data in Boat
Boat.build(latestBoat,"GN","RMC"); //make a sentence from Boat data Boat.build(latestBoat, "GN", "RMC"); // make a sentence from Boat data
Serial.print("\nbuild() test output -->"); // Serial.print("\nbuild() test output -->"); //
Serial.print(latestBoat); // Serial.print(latestBoat); //
GPS.resetSentTime(); //make timing look like it came in on GPS GPS.resetSentTime(); // make timing look like it came in on GPS
GPS.parse(latestBoat); //parse the test data and store in GPS GPS.parse(latestBoat); // parse the test data and store in GPS
#endif #endif
} }
} }
#ifdef NMEA_EXTENSIONS #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 t = millis() / 1000.;
double theta = t / 100.; //slow double theta = t / 100.; // slow
double gamma = theta * 10; //faster double gamma = theta * 10; // faster
Boat.latitude = 4400 + sin(theta)*60; Boat.latitude = 4400 + sin(theta) * 60;
Boat.lat = 'N'; Boat.lat = 'N';
Boat.longitude = 7600 + cos(theta)*60; Boat.longitude = 7600 + cos(theta) * 60;
Boat.lon = 'W'; Boat.lon = 'W';
Boat.fixquality = 2; Boat.fixquality = 2;
Boat.speed = 3 + sin(gamma); Boat.speed = 3 + sin(gamma);
Boat.hour = abs(cos(theta)) * 24; 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.seconds = 30 + sin(gamma) * 30;
Boat.milliseconds = 500+ sin(gamma) * 500; Boat.milliseconds = 500 + sin(gamma) * 500;
Boat.year = 1+abs(sin(theta)) * 25; Boat.year = 1 + abs(sin(theta)) * 25;
Boat.month = 1+abs(sin(gamma)) * 11; Boat.month = 1 + abs(sin(gamma)) * 11;
Boat.day = 1+ abs(sin(gamma)) * 26; Boat.day = 1 + abs(sin(gamma)) * 26;
Boat.satellites = abs(cos(gamma)) * 10; Boat.satellites = abs(cos(gamma)) * 10;
} }
#endif #endif