Skip to content

Commit e14ce73

Browse files
committed
Add set/getNMEALoggingMask. Allows selective logging of enabled NMEA messages
1 parent 1220ef2 commit e14ce73

File tree

4 files changed

+183
-17
lines changed

4 files changed

+183
-17
lines changed

examples/Data_Logging/DataLoggingExample6_NMEA/DataLoggingExample6_NMEA.ino

+3-1
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,9 @@ void setup()
144144
myGNSS.enableNMEAMessage(UBX_NMEA_GGA, COM_PORT_I2C, 1); // Ensure the GxGGA (Global positioning system fix data) message is enabled. Send every measurement.
145145
myGNSS.enableNMEAMessage(UBX_NMEA_GSA, COM_PORT_I2C, 1); // Ensure the GxGSA (GNSS DOP and Active satellites) message is enabled. Send every measurement.
146146
myGNSS.enableNMEAMessage(UBX_NMEA_GSV, COM_PORT_I2C, 1); // Ensure the GxGSV (GNSS satellites in view) message is enabled. Send every measurement.
147-
myGNSS.logNMEA(); // Enable NMEA logging
147+
148+
myGNSS.setNMEALoggingMask(SFE_UBLOX_LOG_NMEA_ALL); // Enable logging of all enabled NMEA messages
149+
//myGNSS.setNMEALoggingMask(SFE_UBLOX_LOG_NMEA_GGA | SFE_UBLOX_LOG_NMEA_GSA); // Or we can, for example, log only GxGGA and GxGSA. Ignore GxGSV
148150

149151
Serial.println(F("Press any key to stop logging."));
150152

keywords.txt

+27-1
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,8 @@ initPacketUBXHNRPVT KEYWORD2
382382
flushHNRPVT KEYWORD2
383383
logHNRPVT KEYWORD2
384384

385-
logNMEA KEYWORD2
385+
setNMEALoggingMask KEYWORD2
386+
getNMEALoggingMask KEYWORD2
386387

387388
setNavigationFrequency KEYWORD2
388389
getNavigationFrequency KEYWORD2
@@ -546,16 +547,41 @@ UBX_NMEA_GLQ LITERAL1
546547
UBX_NMEA_GNQ LITERAL1
547548
UBX_NMEA_GNS LITERAL1
548549
UBX_NMEA_GPQ LITERAL1
550+
UBX_NMEA_GQQ LITERAL1
549551
UBX_NMEA_GRS LITERAL1
550552
UBX_NMEA_GSA LITERAL1
551553
UBX_NMEA_GST LITERAL1
552554
UBX_NMEA_GSV LITERAL1
555+
UBX_NMEA_RLM LITERAL1
553556
UBX_NMEA_RMC LITERAL1
554557
UBX_NMEA_TXT LITERAL1
555558
UBX_NMEA_VLW LITERAL1
556559
UBX_NMEA_VTG LITERAL1
557560
UBX_NMEA_ZDA LITERAL1
558561

562+
SFE_UBLOX_LOG_NMEA_ALL LITERAL1
563+
SFE_UBLOX_LOG_NMEA_DTM LITERAL1
564+
SFE_UBLOX_LOG_NMEA_GAQ LITERAL1
565+
SFE_UBLOX_LOG_NMEA_GBQ LITERAL1
566+
SFE_UBLOX_LOG_NMEA_GBS LITERAL1
567+
SFE_UBLOX_LOG_NMEA_GGA LITERAL1
568+
SFE_UBLOX_LOG_NMEA_GLL LITERAL1
569+
SFE_UBLOX_LOG_NMEA_GLQ LITERAL1
570+
SFE_UBLOX_LOG_NMEA_GNQ LITERAL1
571+
SFE_UBLOX_LOG_NMEA_GNS LITERAL1
572+
SFE_UBLOX_LOG_NMEA_GPQ LITERAL1
573+
SFE_UBLOX_LOG_NMEA_GQQ LITERAL1
574+
SFE_UBLOX_LOG_NMEA_GRS LITERAL1
575+
SFE_UBLOX_LOG_NMEA_GSA LITERAL1
576+
SFE_UBLOX_LOG_NMEA_GST LITERAL1
577+
SFE_UBLOX_LOG_NMEA_GSV LITERAL1
578+
SFE_UBLOX_LOG_NMEA_RLM LITERAL1
579+
SFE_UBLOX_LOG_NMEA_RMC LITERAL1
580+
SFE_UBLOX_LOG_NMEA_TXT LITERAL1
581+
SFE_UBLOX_LOG_NMEA_VLW LITERAL1
582+
SFE_UBLOX_LOG_NMEA_VTG LITERAL1
583+
SFE_UBLOX_LOG_NMEA_ZDA LITERAL1
584+
559585
UBX_NAV_ATT LITERAL1
560586
UBX_NAV_CLOCK LITERAL1
561587
UBX_NAV_DOP LITERAL1

src/SparkFun_u-blox_GNSS_Arduino_Library.cpp

+79-8
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ SFE_UBLOX_GNSS::SFE_UBLOX_GNSS(void)
5050
pinMode((uint8_t)debugPin, OUTPUT);
5151
digitalWrite((uint8_t)debugPin, HIGH);
5252
}
53+
54+
_logNMEA.all = 0; // Default to logging no NMEA messages
5355
}
5456

5557
//Stop all automatic message processing. Free all used RAM
@@ -1020,6 +1022,7 @@ void SFE_UBLOX_GNSS::process(uint8_t incoming, ubxPacket *incomingUBX, uint8_t r
10201022
}
10211023
else if (incoming == '$')
10221024
{
1025+
nmeaByteCounter = 0; // Reset the NMEA byte counter
10231026
currentSentence = NMEA;
10241027
}
10251028
else if (incoming == 0xD3) //RTCM frames start with 0xD3
@@ -1241,20 +1244,83 @@ void SFE_UBLOX_GNSS::process(uint8_t incoming, ubxPacket *incomingUBX, uint8_t r
12411244
//Finally, increment the frame counter
12421245
ubxFrameCounter++;
12431246
}
1244-
else if (currentSentence == NMEA)
1247+
else if (currentSentence == NMEA) // Process incoming NMEA mesages. Selectively log if desired.
12451248
{
1246-
//If _logNMEA is true, attempt to store incoming in the file buffer
1247-
if (_logNMEA)
1248-
storeFileBytes(&incoming, 1);
1249+
if ((nmeaByteCounter == 0) && (incoming != '$'))
1250+
{
1251+
currentSentence = NONE; //Something went wrong. Reset. (Almost certainly redundant!)
1252+
}
1253+
else if ((nmeaByteCounter == 1) && (incoming != 'G'))
1254+
{
1255+
currentSentence = NONE; //Something went wrong. Reset.
1256+
}
1257+
else if ((nmeaByteCounter >= 0) && (nmeaByteCounter <= 5))
1258+
{
1259+
nmeaAddressField[nmeaByteCounter] = incoming; // Store the start character and NMEA address field
1260+
}
1261+
1262+
if (nmeaByteCounter == 5)
1263+
{
1264+
// We've just received the end of the address field. Check if it is selected for logging
1265+
if (logThisNMEA())
1266+
{
1267+
storeFileBytes(&nmeaAddressField[0], 6); // Add start character and address field to the file buffer
1268+
}
1269+
}
12491270

1250-
processNMEA(incoming); //Process each NMEA character
1271+
if ((nmeaByteCounter > 5) || (nmeaByteCounter < 0)) // Should we add incoming to the file buffer?
1272+
{
1273+
if (logThisNMEA())
1274+
storeFileBytes(&incoming, 1); // Add incoming to the file buffer
1275+
}
1276+
1277+
if (incoming == '*')
1278+
nmeaByteCounter = -5; // We are expecting * plus two checksum bytes plus CR and LF
1279+
1280+
nmeaByteCounter++; // Increment the byte counter
1281+
1282+
if (nmeaByteCounter == maxNMEAByteCount) // Check if we have processed too many bytes
1283+
currentSentence = NONE; //Something went wrong. Reset.
1284+
1285+
if (nmeaByteCounter == 0) // Check if we are done
1286+
currentSentence = NONE; // All done!
1287+
1288+
processNMEA(incoming); //Process each and every NMEA character
12511289
}
12521290
else if (currentSentence == RTCM)
12531291
{
12541292
processRTCMframe(incoming); //Deal with RTCM bytes
12551293
}
12561294
}
12571295

1296+
// PRIVATE: Return true if we should log this NMEA message
1297+
boolean SFE_UBLOX_GNSS::logThisNMEA()
1298+
{
1299+
if (_logNMEA.bits.all == 1) return (true);
1300+
if ((nmeaAddressField[3] == 'D') && (nmeaAddressField[4] == 'T') && (nmeaAddressField[5] == 'M') && (_logNMEA.bits.UBX_NMEA_DTM == 1)) return (true);
1301+
if ((nmeaAddressField[3] == 'G') && (nmeaAddressField[4] == 'A') && (nmeaAddressField[5] == 'Q') && (_logNMEA.bits.UBX_NMEA_GAQ == 1)) return (true);
1302+
if ((nmeaAddressField[3] == 'G') && (nmeaAddressField[4] == 'B') && (nmeaAddressField[5] == 'Q') && (_logNMEA.bits.UBX_NMEA_GBQ == 1)) return (true);
1303+
if ((nmeaAddressField[3] == 'G') && (nmeaAddressField[4] == 'B') && (nmeaAddressField[5] == 'S') && (_logNMEA.bits.UBX_NMEA_GBS == 1)) return (true);
1304+
if ((nmeaAddressField[3] == 'G') && (nmeaAddressField[4] == 'G') && (nmeaAddressField[5] == 'A') && (_logNMEA.bits.UBX_NMEA_GGA == 1)) return (true);
1305+
if ((nmeaAddressField[3] == 'G') && (nmeaAddressField[4] == 'L') && (nmeaAddressField[5] == 'L') && (_logNMEA.bits.UBX_NMEA_GLL == 1)) return (true);
1306+
if ((nmeaAddressField[3] == 'G') && (nmeaAddressField[4] == 'L') && (nmeaAddressField[5] == 'Q') && (_logNMEA.bits.UBX_NMEA_GLQ == 1)) return (true);
1307+
if ((nmeaAddressField[3] == 'G') && (nmeaAddressField[4] == 'N') && (nmeaAddressField[5] == 'Q') && (_logNMEA.bits.UBX_NMEA_GNQ == 1)) return (true);
1308+
if ((nmeaAddressField[3] == 'G') && (nmeaAddressField[4] == 'N') && (nmeaAddressField[5] == 'S') && (_logNMEA.bits.UBX_NMEA_GNS == 1)) return (true);
1309+
if ((nmeaAddressField[3] == 'G') && (nmeaAddressField[4] == 'P') && (nmeaAddressField[5] == 'Q') && (_logNMEA.bits.UBX_NMEA_GPQ == 1)) return (true);
1310+
if ((nmeaAddressField[3] == 'G') && (nmeaAddressField[4] == 'Q') && (nmeaAddressField[5] == 'Q') && (_logNMEA.bits.UBX_NMEA_GQQ == 1)) return (true);
1311+
if ((nmeaAddressField[3] == 'G') && (nmeaAddressField[4] == 'R') && (nmeaAddressField[5] == 'S') && (_logNMEA.bits.UBX_NMEA_GRS == 1)) return (true);
1312+
if ((nmeaAddressField[3] == 'G') && (nmeaAddressField[4] == 'S') && (nmeaAddressField[5] == 'A') && (_logNMEA.bits.UBX_NMEA_GSA == 1)) return (true);
1313+
if ((nmeaAddressField[3] == 'G') && (nmeaAddressField[4] == 'S') && (nmeaAddressField[5] == 'T') && (_logNMEA.bits.UBX_NMEA_GST == 1)) return (true);
1314+
if ((nmeaAddressField[3] == 'G') && (nmeaAddressField[4] == 'S') && (nmeaAddressField[5] == 'V') && (_logNMEA.bits.UBX_NMEA_GSV == 1)) return (true);
1315+
if ((nmeaAddressField[3] == 'R') && (nmeaAddressField[4] == 'L') && (nmeaAddressField[5] == 'M') && (_logNMEA.bits.UBX_NMEA_RLM == 1)) return (true);
1316+
if ((nmeaAddressField[3] == 'R') && (nmeaAddressField[4] == 'M') && (nmeaAddressField[5] == 'C') && (_logNMEA.bits.UBX_NMEA_RMC == 1)) return (true);
1317+
if ((nmeaAddressField[3] == 'T') && (nmeaAddressField[4] == 'X') && (nmeaAddressField[5] == 'T') && (_logNMEA.bits.UBX_NMEA_TXT == 1)) return (true);
1318+
if ((nmeaAddressField[3] == 'V') && (nmeaAddressField[4] == 'L') && (nmeaAddressField[5] == 'W') && (_logNMEA.bits.UBX_NMEA_VLW == 1)) return (true);
1319+
if ((nmeaAddressField[3] == 'V') && (nmeaAddressField[4] == 'T') && (nmeaAddressField[5] == 'G') && (_logNMEA.bits.UBX_NMEA_VTG == 1)) return (true);
1320+
if ((nmeaAddressField[3] == 'Z') && (nmeaAddressField[4] == 'D') && (nmeaAddressField[5] == 'A') && (_logNMEA.bits.UBX_NMEA_ZDA == 1)) return (true);
1321+
return (false);
1322+
}
1323+
12581324
//This is the default or generic NMEA processor. We're only going to pipe the data to serial port so we can see it.
12591325
//User could overwrite this function to pipe characters to nmea.process(c) of tinyGPS or MicroNMEA
12601326
//Or user could pipe each character to a buffer, radio, etc.
@@ -9079,10 +9145,15 @@ void SFE_UBLOX_GNSS::logHNRPVT(boolean enabled)
90799145

90809146
// ***** Helper Functions for NMEA Logging
90819147

9082-
//Log NMEA data in file buffer - if it exists! User needs to call setFileBufferSize before .begin
9083-
void SFE_UBLOX_GNSS::logNMEA(boolean enabled)
9148+
// Log selected NMEA messages to file buffer - if the messages are enabled and if the file buffer exists
9149+
// User needs to call setFileBufferSize before .begin
9150+
void SFE_UBLOX_GNSS::setNMEALoggingMask(uint32_t messages)
9151+
{
9152+
_logNMEA.all = messages;
9153+
}
9154+
uint32_t SFE_UBLOX_GNSS::getNMEALoggingMask()
90849155
{
9085-
_logNMEA = enabled;
9156+
return (_logNMEA.all);
90869157
}
90879158

90889159
// ***** CFG RATE Helper Functions

src/SparkFun_u-blox_GNSS_Arduino_Library.h

+74-7
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,66 @@ typedef enum
9999
SFE_UBLOX_PACKET_PACKETAUTO
100100
} sfe_ublox_packet_buffer_e;
101101

102+
// Define a struct to allow selective logging of NMEA messages
103+
typedef struct
104+
{
105+
union
106+
{
107+
uint32_t all;
108+
struct
109+
{
110+
uint32_t all : 1;
111+
uint32_t UBX_NMEA_DTM : 1;
112+
uint32_t UBX_NMEA_GAQ : 1;
113+
uint32_t UBX_NMEA_GBQ : 1;
114+
uint32_t UBX_NMEA_GBS : 1;
115+
uint32_t UBX_NMEA_GGA : 1;
116+
uint32_t UBX_NMEA_GLL : 1;
117+
uint32_t UBX_NMEA_GLQ : 1;
118+
uint32_t UBX_NMEA_GNQ : 1;
119+
uint32_t UBX_NMEA_GNS : 1;
120+
uint32_t UBX_NMEA_GPQ : 1;
121+
uint32_t UBX_NMEA_GQQ : 1;
122+
uint32_t UBX_NMEA_GRS : 1;
123+
uint32_t UBX_NMEA_GSA : 1;
124+
uint32_t UBX_NMEA_GST : 1;
125+
uint32_t UBX_NMEA_GSV : 1;
126+
uint32_t UBX_NMEA_RLM : 1;
127+
uint32_t UBX_NMEA_RMC : 1;
128+
uint32_t UBX_NMEA_TXT : 1;
129+
uint32_t UBX_NMEA_VLW : 1;
130+
uint32_t UBX_NMEA_VTG : 1;
131+
uint32_t UBX_NMEA_ZDA : 1;
132+
} bits;
133+
};
134+
} sfe_ublox_nmea_logging_t;
135+
// Define an enum to make it easy to enable/disable selected NMEA messages for logging
136+
typedef enum
137+
{
138+
SFE_UBLOX_LOG_NMEA_ALL = 0x00000001,
139+
SFE_UBLOX_LOG_NMEA_DTM = 0x00000002,
140+
SFE_UBLOX_LOG_NMEA_GAQ = 0x00000004,
141+
SFE_UBLOX_LOG_NMEA_GBQ = 0x00000008,
142+
SFE_UBLOX_LOG_NMEA_GBS = 0x00000010,
143+
SFE_UBLOX_LOG_NMEA_GGA = 0x00000020,
144+
SFE_UBLOX_LOG_NMEA_GLL = 0x00000040,
145+
SFE_UBLOX_LOG_NMEA_GLQ = 0x00000080,
146+
SFE_UBLOX_LOG_NMEA_GNQ = 0x00000100,
147+
SFE_UBLOX_LOG_NMEA_GNS = 0x00000200,
148+
SFE_UBLOX_LOG_NMEA_GPQ = 0x00000400,
149+
SFE_UBLOX_LOG_NMEA_GQQ = 0x00000800,
150+
SFE_UBLOX_LOG_NMEA_GRS = 0x00001000,
151+
SFE_UBLOX_LOG_NMEA_GSA = 0x00002000,
152+
SFE_UBLOX_LOG_NMEA_GST = 0x00004000,
153+
SFE_UBLOX_LOG_NMEA_GSV = 0x00008000,
154+
SFE_UBLOX_LOG_NMEA_RLM = 0x00010000,
155+
SFE_UBLOX_LOG_NMEA_RMC = 0x00020000,
156+
SFE_UBLOX_LOG_NMEA_TXT = 0x00040000,
157+
SFE_UBLOX_LOG_NMEA_VLW = 0x00080000,
158+
SFE_UBLOX_LOG_NMEA_VTG = 0x00100000,
159+
SFE_UBLOX_LOG_NMEA_ZDA = 0x00200000
160+
} sfe_ublox_nmea_logging_selective_e;
161+
102162
//Registers
103163
const uint8_t UBX_SYNCH_1 = 0xB5;
104164
const uint8_t UBX_SYNCH_2 = 0x62;
@@ -159,7 +219,7 @@ const uint8_t UBX_CFG_VALSET = 0x8A; //Used for config of higher version u-blox
159219

160220
//Class: NMEA
161221
//The following are used to enable NMEA messages. Descriptions come from the NMEA messages overview in the ZED-F9P Interface Description
162-
const uint8_t UBX_NMEA_MSB = 0xF0; //All NMEA enable commands have 0xF0 as MSB
222+
const uint8_t UBX_NMEA_MSB = 0xF0; //All NMEA enable commands have 0xF0 as MSB. Equal to UBX_CLASS_NMEA
163223
const uint8_t UBX_NMEA_DTM = 0x0A; //GxDTM (datum reference)
164224
const uint8_t UBX_NMEA_GAQ = 0x45; //GxGAQ (poll a standard message (if the current talker ID is GA))
165225
const uint8_t UBX_NMEA_GBQ = 0x44; //GxGBQ (poll a standard message (if the current Talker ID is GB))
@@ -169,11 +229,13 @@ const uint8_t UBX_NMEA_GLL = 0x01; //GxGLL (latitude and long, whith time of pos
169229
const uint8_t UBX_NMEA_GLQ = 0x43; //GxGLQ (poll a standard message (if the current Talker ID is GL))
170230
const uint8_t UBX_NMEA_GNQ = 0x42; //GxGNQ (poll a standard message (if the current Talker ID is GN))
171231
const uint8_t UBX_NMEA_GNS = 0x0D; //GxGNS (GNSS fix data)
172-
const uint8_t UBX_NMEA_GPQ = 0x040; //GxGPQ (poll a standard message (if the current Talker ID is GP))
232+
const uint8_t UBX_NMEA_GPQ = 0x40; //GxGPQ (poll a standard message (if the current Talker ID is GP))
233+
const uint8_t UBX_NMEA_GQQ = 0x47; //GxGQQ (poll a standard message (if the current Talker ID is GQ))
173234
const uint8_t UBX_NMEA_GRS = 0x06; //GxGRS (GNSS range residuals)
174235
const uint8_t UBX_NMEA_GSA = 0x02; //GxGSA (GNSS DOP and Active satellites)
175236
const uint8_t UBX_NMEA_GST = 0x07; //GxGST (GNSS Pseudo Range Error Statistics)
176237
const uint8_t UBX_NMEA_GSV = 0x03; //GxGSV (GNSS satellites in view)
238+
const uint8_t UBX_NMEA_RLM = 0x0B; //GxRMC (Return link message (RLM))
177239
const uint8_t UBX_NMEA_RMC = 0x04; //GxRMC (Recommended minimum data)
178240
const uint8_t UBX_NMEA_TXT = 0x41; //GxTXT (text transmission)
179241
const uint8_t UBX_NMEA_VLW = 0x0F; //GxVLW (dual ground/water distance)
@@ -928,8 +990,9 @@ class SFE_UBLOX_GNSS
928990
void flushHNRPVT(); //Mark all the data as read/stale
929991
void logHNRPVT(boolean enabled = true); // Log data to file buffer
930992

931-
// Helper function for NMEA logging
932-
void logNMEA(boolean enabled = true); // Log NMEA data to file buffer
993+
// Helper functions for NMEA logging
994+
void setNMEALoggingMask(uint32_t messages = SFE_UBLOX_LOG_NMEA_ALL); // Log selected NMEA messages to file buffer - if enabled
995+
uint32_t getNMEALoggingMask(); // Return which NMEA messages are selected for logging to the file buffer - if enabled
933996

934997
// Helper functions for CFG RATE
935998

@@ -1186,7 +1249,7 @@ class SFE_UBLOX_GNSS
11861249

11871250
boolean ubx7FcheckDisabled = false; // Flag to indicate if the "7F" check should be ignored in checkUbloxI2C
11881251

1189-
boolean _logNMEA = false; // Flag to indicate if NMEA data should be added to the file buffer
1252+
sfe_ublox_nmea_logging_t _logNMEA; // Flags to indicate which NMEA messages should be added to the file buffer for logging
11901253

11911254
//The packet buffers
11921255
//These are pointed at from within the ubxPacket
@@ -1218,11 +1281,15 @@ class SFE_UBLOX_GNSS
12181281

12191282
unsigned long lastCheck = 0;
12201283

1221-
uint16_t ubxFrameCounter; //It counts all UBX frame. [Fixed header(2bytes), CLS(1byte), ID(1byte), length(2bytes), payload(x bytes), checksums(2bytes)]
1222-
1284+
uint16_t ubxFrameCounter; //Count all UBX frame bytes. [Fixed header(2bytes), CLS(1byte), ID(1byte), length(2bytes), payload(x bytes), checksums(2bytes)]
12231285
uint8_t rollingChecksumA; //Rolls forward as we receive incoming bytes. Checked against the last two A/B checksum bytes
12241286
uint8_t rollingChecksumB; //Rolls forward as we receive incoming bytes. Checked against the last two A/B checksum bytes
12251287

1288+
int16_t nmeaByteCounter; //Count all NMEA message bytes.
1289+
const int16_t maxNMEAByteCount = 1024; // Abort NMEA message reception if nmeaByteCounter exceeds this
1290+
uint8_t nmeaAddressField[6]; // NMEA Address Field - includes the start character (*)
1291+
boolean logThisNMEA(); // Return true if we should log this NMEA message
1292+
12261293
uint16_t rtcmLen = 0;
12271294

12281295
// Flag to prevent reentry into checkCallbacks

0 commit comments

Comments
 (0)