Skip to content

Commit 0fdd0c3

Browse files
committed
Add fix check based on NMEA before starting binary
1 parent a68f37e commit 0fdd0c3

File tree

2 files changed

+119
-11
lines changed

2 files changed

+119
-11
lines changed

src/SparkFun_Unicore_GNSS_Arduino_Library.cpp

Lines changed: 107 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,7 @@ bool UM980::isConnected()
278278
// If isBlocking is true, external consumers should not read/write to the Serial hardware
279279
bool UM980::isBlocking()
280280
{
281-
return(unicoreLibrarySemaphoreBlock);
281+
return (unicoreLibrarySemaphoreBlock);
282282
}
283283

284284
// Calling this function with nothing sets the debug port to Serial
@@ -430,8 +430,8 @@ void um980ProcessMessage(SEMP_PARSE_STATE *parse, uint16_t type)
430430
switch (type)
431431
{
432432
case UM980_NMEA_PARSER_INDEX:
433-
ptrUM980->debugPrintf("Unicore Lib: Valid NMEA Sentence: %s, 0x%04x (%d) bytes", sempNmeaGetSentenceName(parse),
434-
parse->length, parse->length);
433+
ptrUM980->debugPrintf("Unicore Lib: Valid NMEA Sentence: %s, 0x%04x (%d) bytes",
434+
sempNmeaGetSentenceName(parse), parse->length, parse->length);
435435
break;
436436

437437
case UM980_UNICORE_HASH_PARSER_INDEX:
@@ -444,7 +444,8 @@ void um980ProcessMessage(SEMP_PARSE_STATE *parse, uint16_t type)
444444
break;
445445

446446
case UM980_UNICORE_BINARY_PARSER_INDEX:
447-
ptrUM980->debugPrintf("Unicore Lib: Valid Unicore message: 0x%04x (%d) bytes", parse->length, parse->length);
447+
ptrUM980->debugPrintf("Unicore Lib: Valid Unicore message: 0x%04x (%d) bytes", parse->length,
448+
parse->length);
448449
break;
449450
}
450451
}
@@ -473,13 +474,23 @@ void um980ProcessMessage(SEMP_PARSE_STATE *parse, uint16_t type)
473474
break;
474475

475476
case UM980_NMEA_PARSER_INDEX:
476-
//$command,MODE,response: OK*5D
477+
478+
// Is this a NMEA response or command response?
479+
477480
if (strcasecmp((char *)scratchPad->nmea.sentenceName, "command") != 0 &&
478481
strcasecmp((char *)scratchPad->nmea.sentenceName, "MASK") != 0 &&
479-
strcasecmp((char *)scratchPad->nmea.sentenceName, "CONFIG") != 0) // Found
482+
strcasecmp((char *)scratchPad->nmea.sentenceName, "CONFIG") != 0)
483+
{
484+
// command, MASK, CONFIG not found
485+
486+
if (strcasecmp((char *)scratchPad->nmea.sentenceName, "GNGGA") == 0)
487+
{
488+
ptrUM980->debugPrintf("um980ProcessMessage GNGGA");
489+
}
480490

481491
// Unknown response, ignore this message
482492
ptrUM980->debugPrintf("Unicore Lib: Message ignored: %s", parse->buffer);
493+
}
483494
else
484495
{
485496
// Does this response contain the command we are looking for?
@@ -1154,7 +1165,7 @@ void UM980::unicoreHandler(uint8_t *response, uint16_t length)
11541165
}
11551166
else if (messageID == messageIdBestnavXyz)
11561167
{
1157-
// debugPrintf("BestNavXyz Handler");
1168+
debugPrintf("BestNavXyz Handler");
11581169
CHECK_POINTER_VOID(packetBESTNAVXYZ, initBestnavXyz); // Check that RAM has been allocated
11591170

11601171
lastUpdateEcef = millis(); // Update stale marker
@@ -1172,7 +1183,7 @@ void UM980::unicoreHandler(uint8_t *response, uint16_t length)
11721183
}
11731184
else if (messageID == messageIdVersion)
11741185
{
1175-
// debugPrintf("Version Handler");
1186+
debugPrintf("Version Handler");
11761187
CHECK_POINTER_VOID(packetVERSION, initVersion); // Check that RAM has been allocated
11771188

11781189
lastUpdateVersion = millis(); // Update stale marker
@@ -1188,7 +1199,48 @@ void UM980::unicoreHandler(uint8_t *response, uint16_t length)
11881199
}
11891200
else
11901201
{
1191-
debugPrintf("Unknown message id: %d\r\n", messageID);
1202+
// Is this a NMEA sentence?
1203+
if (response[0] == '$')
1204+
{
1205+
response[length] = '\0'; // Force terminator because strncasestr does not exist
1206+
1207+
// The UM980 does not respond to binary requests when there is no GNSS reception.
1208+
// Block BestNavB, etc commands if there is no fix.
1209+
// Look for GNGGA NMEA then extract GNSS position status (spot 6).
1210+
// $GNGGA,181535.00,,,,,0,00,9999.0,,,,,,*43
1211+
char *responsePointer = strcasestr((char *)response, "GNGGA");
1212+
if (responsePointer != nullptr) // Found
1213+
{
1214+
char gngga[100];
1215+
strncpy(gngga, (const char *)response, length); // Make copy before strtok
1216+
1217+
debugPrintf("Unicore Lib: GNGGA message: %s\r\n", gngga);
1218+
1219+
char *pt;
1220+
pt = strtok(gngga, ",");
1221+
int counter = 0;
1222+
while (pt != NULL)
1223+
{
1224+
int spotValue = atoi(pt);
1225+
// Serial.printf("counter: %d spot: %s spotvalue: %d\r\n", counter, pt, spotValue);
1226+
if (counter++ == 6)
1227+
{
1228+
nmeaPositionStatus = spotValue;
1229+
debugPrintf("nmeaPositionStatus: %d\r\n", nmeaPositionStatus);
1230+
}
1231+
pt = strtok(NULL, ",");
1232+
}
1233+
}
1234+
else
1235+
{
1236+
// Unhandled NMEA message
1237+
// debugPrintf("Unicore Lib: Unhandled NMEA sentence (%d bytes): %s\r\n", length, (char *)response);
1238+
}
1239+
}
1240+
else
1241+
{
1242+
debugPrintf("Unicore Lib: Unknown message id: %d\r\n", messageID);
1243+
}
11921244
}
11931245
}
11941246

@@ -1238,6 +1290,19 @@ bool UM980::initVersion()
12381290
// Allocate RAM for packetBESTNAV and initialize it
12391291
bool UM980::initBestnav(uint8_t rate)
12401292
{
1293+
if ((startBinaryBeforeFix == false) && (isNmeaFixed() == false))
1294+
{
1295+
debugPrintf("Unicore Lib: BestNav no fix");
1296+
return (false);
1297+
}
1298+
else
1299+
{
1300+
if(startBinaryBeforeFix == true)
1301+
Serial.println("startBinaryBeforeFix is true");
1302+
if(isNmeaFixed() == true)
1303+
Serial.println("isNmeaFixed() is true");
1304+
}
1305+
12411306
packetBESTNAV = new UNICORE_BESTNAV_t; // Allocate RAM for the main struct
12421307
if (packetBESTNAV == nullptr)
12431308
{
@@ -1283,6 +1348,12 @@ bool UM980::initBestnav(uint8_t rate)
12831348
// Allocate RAM for packetBESTNAVXYZ and initialize it
12841349
bool UM980::initBestnavXyz(uint8_t rate)
12851350
{
1351+
if ((startBinaryBeforeFix == false) && (isNmeaFixed() == false))
1352+
{
1353+
debugPrintf("Unicore Lib: BestNavXyz no fix");
1354+
return (false);
1355+
}
1356+
12861357
packetBESTNAVXYZ = new UNICORE_BESTNAVXYZ_t; // Allocate RAM for the main struct
12871358
if (packetBESTNAVXYZ == nullptr)
12881359
{
@@ -1328,6 +1399,12 @@ bool UM980::initBestnavXyz(uint8_t rate)
13281399
// Allocate RAM for packetRECTIME and initialize it
13291400
bool UM980::initRectime(uint8_t rate)
13301401
{
1402+
if ((startBinaryBeforeFix == false) && (isNmeaFixed() == false))
1403+
{
1404+
debugPrintf("Unicore Lib: RecTime no fix");
1405+
return (false);
1406+
}
1407+
13311408
packetRECTIME = new UNICORE_RECTIME_t; // Allocate RAM for the main struct
13321409
if (packetRECTIME == nullptr)
13331410
{
@@ -1618,3 +1695,24 @@ char *UM980::getVersionFull(uint16_t maxWaitMs)
16181695
return ((char *)"Error1");
16191696
return ((char *)"Error2");
16201697
}
1698+
1699+
// Returns true when GNGGA NMEA reports position status >= 2
1700+
bool UM980::isNmeaFixed()
1701+
{
1702+
if (nmeaPositionStatus >= 2)
1703+
return (true);
1704+
return (false);
1705+
}
1706+
1707+
// By default, library will attempt to start RECTIME and BESTNAV regardless of GNSS fix
1708+
// This may lead to command timeouts as the UM980 does not appear to respond to BESTNAVB commands if 3D fix is not
1709+
// achieved. Set startBinartBeforeFix = false via disableBinaryBeforeFix() to block binary commands before a fix is
1710+
// achieved
1711+
void UM980::enableBinaryBeforeFix()
1712+
{
1713+
startBinaryBeforeFix = true;
1714+
}
1715+
void UM980::disableBinaryBeforeFix()
1716+
{
1717+
startBinaryBeforeFix = false;
1718+
}

src/SparkFun_Unicore_GNSS_Arduino_Library.h

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,8 +137,8 @@ class UM980
137137
unsigned long lastUpdateDateTime = 0;
138138
unsigned long lastUpdateVersion = 0;
139139

140-
bool staleDateTime();
141-
bool staleEcef();
140+
bool isNmeaFixed(); // Returns true when GNGGA NMEA reports position status >= 2
141+
142142
void stopAutoReports(); // Delete all pointers to force reinit next time a helper function is called
143143

144144
Um980Result getGeodetic(uint16_t maxWaitMs = 1500);
@@ -161,6 +161,13 @@ class UM980
161161
bool _printRxMessages = false; // Display the received message summary
162162
bool _dumpRxMessages = false; // Display the received message hex dump
163163

164+
uint8_t nmeaPositionStatus = 0; // Position psition status obtained from GNGGA NMEA
165+
166+
// By default, library will attempt to start RECTIME and BESTNAV regardless of GNSS fix.
167+
// This may lead to command timeouts as the UM980 does not appear to respond to BESTNAVB commands if 3D fix is not achieved.
168+
// Set startBinartBeforeFix = false via disableBinaryBeforeFix() to block binary commands before a fix is achieved
169+
bool startBinaryBeforeFix = true;
170+
164171
bool begin(HardwareSerial &serialPort, Print *parserDebug = nullptr, Print *parserError = &Serial);
165172
bool isConnected();
166173
bool isBlocking();
@@ -176,6 +183,9 @@ class UM980
176183
void enableParserErrors(Print *print = &Serial);
177184
void disableParserErrors();
178185

186+
void enableBinaryBeforeFix();
187+
void disableBinaryBeforeFix();
188+
179189
void enablePrintBadChecksums();
180190
void disablePrintBadChecksums();
181191
void enablePrintParserTransitions();

0 commit comments

Comments
 (0)