This commit is contained in:
Rick Sellens 2020-01-29 12:57:20 -05:00
parent 7d889e3a9d
commit 8ae6a7b75a
4 changed files with 60 additions and 50 deletions

View File

@ -30,13 +30,13 @@
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 NMEA_EXTRAS // inject on the compile command line to force extensions #ifndef NMEA_EXTRAS // inject on the compile command line to force extensions
#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
#else #else
#if(NMEA_EXTRAS > 0) #if(NMEA_EXTRAS > 0)
#define NMEA_EXTENSIONS ///< if defined will include more NMEA sentences #define NMEA_EXTENSIONS ///< if defined will include more NMEA sentences
#endif #endif
#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
@ -64,8 +64,9 @@
/// type for resulting code from running check() /// type for resulting code from running check()
typedef enum { typedef enum {
NMEA_BAD = 0, ///< passed none of the checks NMEA_BAD = 0, ///< passed none of the checks
NMEA_HAS_DOLLAR = 1, ///< has a dollar sign or exclamation mark in the first position NMEA_HAS_DOLLAR =
1, ///< has a dollar sign or exclamation mark in the first position
NMEA_HAS_CHECKSUM = 2, ///< has a valid checksum at the end NMEA_HAS_CHECKSUM = 2, ///< has a valid checksum at the end
NMEA_HAS_NAME = 4, ///< there is a token after the $ followed by a comma NMEA_HAS_NAME = 4, ///< there is a token after the $ followed by a comma
NMEA_HAS_SOURCE = 10, ///< has a recognized source ID NMEA_HAS_SOURCE = 10, ///< has a recognized source ID
@ -91,7 +92,7 @@ public:
Adafruit_GPS(); // Constructor for no communications, just data storage Adafruit_GPS(); // Constructor for no communications, just data storage
void common_init(void); void common_init(void);
virtual ~Adafruit_GPS(); virtual ~Adafruit_GPS();
size_t available(void); size_t available(void);
size_t write(uint8_t); size_t write(uint8_t);
char read(void); char read(void);
@ -100,7 +101,7 @@ public:
void pause(bool b); void pause(bool b);
char *lastNMEA(void); char *lastNMEA(void);
bool waitForSentence(const char *wait, uint8_t max = MAXWAITSENTENCE, bool waitForSentence(const char *wait, uint8_t max = MAXWAITSENTENCE,
bool usingInterrupts = false); bool usingInterrupts = false);
bool LOCUS_StartLogger(void); bool LOCUS_StartLogger(void);
bool LOCUS_StopLogger(void); bool LOCUS_StopLogger(void);
bool LOCUS_ReadStatus(void); bool LOCUS_ReadStatus(void);
@ -110,7 +111,7 @@ public:
nmea_float_t secondsSinceTime(); nmea_float_t secondsSinceTime();
nmea_float_t secondsSinceDate(); nmea_float_t secondsSinceDate();
void resetSentTime(); void resetSentTime();
// NMEA_parse.cpp // NMEA_parse.cpp
bool parse(char *); bool parse(char *);
bool check(char *nmea); bool check(char *nmea);
@ -123,7 +124,7 @@ public:
char ref = 'R'); char ref = 'R');
#endif #endif
void addChecksum(char *buff); void addChecksum(char *buff);
// NMEA_data.cpp // NMEA_data.cpp
void newDataValue(nmea_index_t tag, nmea_float_t v); void newDataValue(nmea_index_t tag, nmea_float_t v);
#ifdef NMEA_EXTENSIONS #ifdef NMEA_EXTENSIONS
@ -229,10 +230,10 @@ public:
#endif // NMEA_EXTENSIONS #endif // NMEA_EXTENSIONS
private: private:
// void parseLat(char *); // void parseLat(char *);
// bool parseLatDir(char *); // bool parseLatDir(char *);
// void parseLon(char *); // void parseLon(char *);
// bool parseLonDir(char *); // bool parseLonDir(char *);
// NMEA_data.cpp // NMEA_data.cpp
void data_init(); void data_init();
// NMEA_parse.cpp // NMEA_parse.cpp
@ -246,8 +247,8 @@ private:
bool isEmpty(char *pStart); bool isEmpty(char *pStart);
// used by check() for validity tests, room for future expansion // used by check() for validity tests, room for future expansion
const char *sources[6] = {"II", "WI", "GP", "GN", const char *sources[6] = {"II", "WI", "GP",
"P", "ZZZ"}; ///< valid source ids "GN", "P", "ZZZ"}; ///< valid source ids
#ifdef NMEA_EXTENSIONS #ifdef NMEA_EXTENSIONS
const char const char
*sentences_parsed[20] = *sentences_parsed[20] =
@ -260,11 +261,10 @@ private:
"RPM", "RSA", "VDR", "VTG", "ZDA", "ZZZ"}; ///< known, but not parseable "RPM", "RSA", "VDR", "VTG", "ZDA", "ZZZ"}; ///< known, but not parseable
#else // make the lists short to save memory #else // make the lists short to save memory
const char const char
*sentences_parsed[5] = *sentences_parsed[5] = {"GGA", "GLL", "GSA", "RMC",
{ "ZZZ"}; ///< parseable sentence ids
"GGA", "GLL", "GSA", "RMC", "ZZZ"}; ///< parseable sentence ids const char *sentences_known[4] = {"DBT", "HDM", "HDT",
const char *sentences_known[4] = { "ZZZ"}; ///< known, but not parseable
"DBT", "HDM", "HDT", "ZZZ"}; ///< known, but not parseable
#endif #endif
// Make all of these times far in the past by setting them near the middle of // Make all of these times far in the past by setting them near the middle of

View File

@ -44,8 +44,8 @@
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.
Floating point arguments to sprintf() are explicitly cast to double to Floating point arguments to sprintf() are explicitly cast to double to
avoid warnings in some compilers. avoid warnings in some compilers.
build() adds Carriage Return and Line Feed to sentences to conform to build() adds Carriage Return and Line Feed to sentences to conform to
@ -72,7 +72,8 @@
/**************************************************************************/ /**************************************************************************/
char *Adafruit_GPS::build(char *nmea, const char *thisSource, char *Adafruit_GPS::build(char *nmea, const char *thisSource,
const char *thisSentence, char ref) { const char *thisSentence, char ref) {
sprintf(nmea, "%6.2f", (double)123.45); // fail if sprintf() doesn't handle floats sprintf(nmea, "%6.2f",
(double)123.45); // fail if sprintf() doesn't handle floats
if (strcmp(nmea, "123.45")) if (strcmp(nmea, "123.45"))
return NULL; return NULL;
*nmea = '$'; *nmea = '$';
@ -112,9 +113,10 @@ char *Adafruit_GPS::build(char *nmea, const char *thisSource,
// 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,,", sprintf(p, "%09.2f,%09.4f,%c,%010.4f,%c,%d,%02d,%f,%f,M,%f,M,,",
(double)hour * 10000L + minute * 100L + seconds + milliseconds / 1000., (double)hour * 10000L + minute * 100L + seconds +
(double)latitude, lat, (double)longitude, lon, fixquality, satellites, milliseconds / 1000.,
(double)HDOP, (double)altitude, (double)geoidheight); (double)latitude, lat, (double)longitude, lon, fixquality,
satellites, (double)HDOP, (double)altitude, (double)geoidheight);
} else if (!strcmp(thisSentence, "GLL")) { //*****************************GLL } else if (!strcmp(thisSentence, "GLL")) { //*****************************GLL
// GLL Geographic Position Latitude/Longitude // GLL Geographic Position Latitude/Longitude
@ -129,8 +131,9 @@ char *Adafruit_GPS::build(char *nmea, const char *thisSource,
// 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", (double)latitude, lat, sprintf(p, "%09.4f,%c,%010.4f,%c,%09.2f,A", (double)latitude, lat,
(double)longitude, lon, (double)hour * 10000L + minute * 100L + (double)longitude, lon,
seconds + milliseconds / 1000.); (double)hour * 10000L + minute * 100L + seconds +
milliseconds / 1000.);
} else if (!strcmp(thisSentence, "GSA")) { //*****************************GSA } else if (!strcmp(thisSentence, "GSA")) { //*****************************GSA
// GSA GPS DOP and active satellites // GSA GPS DOP and active satellites
@ -168,9 +171,11 @@ char *Adafruit_GPS::build(char *nmea, const char *thisSource,
// 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", sprintf(p, "%09.2f,A,%09.4f,%c,%010.4f,%c,%f,%f,%06d,%f,%c",
(double)hour * 10000L + minute * 100L + seconds + milliseconds / 1000., (double)hour * 10000L + minute * 100L + seconds +
(double)latitude, lat, (double)longitude, lon, (double)speed, milliseconds / 1000.,
(double)angle, day * 10000 + month * 100 + year, (double)magvariation, mag); (double)latitude, lat, (double)longitude, lon, (double)speed,
(double)angle, day * 10000 + month * 100 + year,
(double)magvariation, mag);
} else if (!strcmp(thisSentence, "APB")) { //*****************************APB } else if (!strcmp(thisSentence, "APB")) { //*****************************APB
// APB Autopilot Sentence "B" // APB Autopilot Sentence "B"

View File

@ -58,8 +58,9 @@ void Adafruit_GPS::newDataValue(nmea_index_t idx, nmea_float_t v) {
newDataValue((nmea_index_t)(idx + 2), cos(v / RAD_TO_DEG)); newDataValue((nmea_index_t)(idx + 2), cos(v / RAD_TO_DEG));
} }
// weighting factor for smoothing depends on delta t / tau // weighting factor for smoothing depends on delta t / tau
nmea_float_t w = min((nmea_float_t)1.0, ((nmea_float_t)millis() - val[idx].lastUpdate) / nmea_float_t w =
val[idx].response); min((nmea_float_t)1.0,
((nmea_float_t)millis() - val[idx].lastUpdate) / val[idx].response);
// default smoothing // default smoothing
val[idx].smoothed = (1.0 - w) * val[idx].smoothed + w * v; val[idx].smoothed = (1.0 - w) * val[idx].smoothed + w * v;
// special smoothing for some angle types // special smoothing for some angle types
@ -437,7 +438,8 @@ void Adafruit_GPS::removeHistory(nmea_index_t idx) {
/**************************************************************************/ /**************************************************************************/
void Adafruit_GPS::showDataValue(nmea_index_t idx, int n) { void Adafruit_GPS::showDataValue(nmea_index_t idx, int n) {
Serial.print("idx: "); Serial.print("idx: ");
if(idx < 10) Serial.print(" "); if(idx < 10)
Serial.print(" ");
Serial.print(idx); Serial.print(idx);
Serial.print(", "); Serial.print(", ");
Serial.print(val[idx].label); Serial.print(val[idx].label);
@ -458,8 +460,9 @@ void Adafruit_GPS::showDataValue(nmea_index_t idx, int n) {
Serial.print(val[idx].hist->historyInterval); Serial.print(val[idx].hist->historyInterval);
Serial.print(" second intervals: "); Serial.print(" second intervals: ");
Serial.print(val[idx].hist->data[val[idx].hist->n - 1]); Serial.print(val[idx].hist->data[val[idx].hist->n - 1]);
for (unsigned i = val[idx].hist->n - 2; i >= max(val[idx].hist->n - n, (unsigned)0); for (unsigned i = val[idx].hist->n - 2;
i--) { // most recent first i >= max(val[idx].hist->n - n, (unsigned)0);
i--) { // most recent first
Serial.print(", "); Serial.print(", ");
Serial.print(val[idx].hist->data[i]); Serial.print(val[idx].hist->data[i]);
} }
@ -471,7 +474,7 @@ void Adafruit_GPS::showDataValue(nmea_index_t idx, int n) {
Serial.print(", lat: "); Serial.print(", lat: ");
Serial.print(lat); Serial.print(lat);
Serial.print(", latitudeDegrees: "); Serial.print(", latitudeDegrees: ");
Serial.print(latitudeDegrees,8); Serial.print(latitudeDegrees, 8);
Serial.print(", latitude_fixed: "); Serial.print(", latitude_fixed: ");
Serial.println(latitude_fixed); Serial.println(latitude_fixed);
} }
@ -481,7 +484,7 @@ void Adafruit_GPS::showDataValue(nmea_index_t idx, int n) {
Serial.print(", lon: "); Serial.print(", lon: ");
Serial.print(lon); Serial.print(lon);
Serial.print(", longitudeDegrees: "); Serial.print(", longitudeDegrees: ");
Serial.print(longitudeDegrees,8); Serial.print(longitudeDegrees, 8);
Serial.print(", longitude_fixed: "); Serial.print(", longitude_fixed: ");
Serial.println(longitude_fixed); Serial.println(longitude_fixed);
} }

View File

@ -41,8 +41,8 @@
build() function and http://fort21.ru/download/NMEAdescription.pdf for build() function and http://fort21.ru/download/NMEAdescription.pdf for
sentence descriptions. sentence descriptions.
Encapsulated data sentences are supported by NMEA-183, and start with ! Encapsulated data sentences are supported by NMEA-183, and start with !
instead of $. https://gpsd.gitlab.io/gpsd/AIVDM.html provides details instead of $. https://gpsd.gitlab.io/gpsd/AIVDM.html provides details
about encapsulated data sentences used in AIS. about encapsulated data sentences used in AIS.
parse() permits, but does not require Carriage Return and Line Feed at the parse() permits, but does not require Carriage Return and Line Feed at the
@ -641,7 +641,7 @@ bool Adafruit_GPS::onList(char *nmea, const char **list) {
Works for either DDMM.mmmm,N (latitude) or DDDMM.mmmm,W (longitude) format. Works for either DDMM.mmmm,N (latitude) or DDDMM.mmmm,W (longitude) format.
Insensitive to number of decimal places present. Only fills the variables Insensitive to number of decimal places present. Only fills the variables
if it succeeds and the variable pointer is not NULL. This allows calling if it succeeds and the variable pointer is not NULL. This allows calling
to fill only the variables of interest. Does rudimentary validation on to fill only the variables of interest. Does rudimentary validation on
angle range. angle range.
Supersedes private functions parseLat(), parseLon(), parseLatDir(), Supersedes private functions parseLat(), parseLon(), parseLatDir(),
@ -652,7 +652,7 @@ bool Adafruit_GPS::onList(char *nmea, const char **list) {
@param angle_fixed Pointer to the fix point version latitude in decimal @param angle_fixed Pointer to the fix point version latitude in decimal
degrees * 10000000, signed degrees * 10000000, signed
@param angleDegrees Pointer to the angle to fill with decimal degrees, @param angleDegrees Pointer to the angle to fill with decimal degrees,
signed. As actual double on SAMD, etc. resolution is better than the signed. As actual double on SAMD, etc. resolution is better than the
fixed point version. fixed point version.
@param dir Pointer to character to fill the direction N/S/E/W @param dir Pointer to character to fill the direction N/S/E/W
@return true if successful, false if failed or no value @return true if successful, false if failed or no value
@ -662,7 +662,7 @@ bool Adafruit_GPS::parseCoord(char *pStart, nmea_float_t *angleDegrees,
nmea_float_t *angle, int32_t *angle_fixed, nmea_float_t *angle, int32_t *angle_fixed,
char *dir) { char *dir) {
char *p = pStart; char *p = pStart;
if (!isEmpty(p)) { if (!isEmpty(p)) {
// get the number in DDDMM.mmmm format and break into components // get the number in DDDMM.mmmm format and break into components
char degreebuff[10]; char degreebuff[10];
char *e = strchr(p, '.'); char *e = strchr(p, '.');
@ -674,7 +674,7 @@ bool Adafruit_GPS::parseCoord(char *pStart, nmea_float_t *angleDegrees,
long minutes = dddmm - degrees * 100; // remove the degrees long minutes = dddmm - degrees * 100; // remove the degrees
p = e; // start from the decimal point p = e; // start from the decimal point
nmea_float_t decminutes = atof(e); // the fraction after the decimal point nmea_float_t decminutes = atof(e); // the fraction after the decimal point
p = strchr(p, ',') + 1; // go to the next field p = strchr(p, ',') + 1; // go to the next field
// get the NSEW direction as a character // get the NSEW direction as a character
char nsew = 'X'; char nsew = 'X';
@ -697,11 +697,13 @@ bool Adafruit_GPS::parseCoord(char *pStart, nmea_float_t *angleDegrees,
// reject directions that are not NSEW // reject directions that are not NSEW
if (nsew != 'N' && nsew != 'S' && nsew != 'E' && nsew != 'W') if (nsew != 'N' && nsew != 'S' && nsew != 'E' && nsew != 'W')
return false; return false;
// reject angles that are out of range // reject angles that are out of range
if (nsew == 'N' || nsew == 'S') if (nsew == 'N' || nsew == 'S')
if(abs(deg) > 90) return false; if(abs(deg) > 90)
if(abs(deg) > 180) return false; return false;
if(abs(deg) > 180)
return false;
// store in locations passed as args // store in locations passed as args
if (angle != NULL) if (angle != NULL)