processUBXpacket() does not handle NACK #45
Description
Subject of the issue
The processUBXpacket() method does not handle a NACK from the module. This is possible response from the module that needs to be handled otherwise it can result in unreliable processing of the module response.
The following was taken from the UBlox protocol specification:
32.5.1 Acknowledgement
When messages from the class CFG are sent to the receiver, the receiver will send an "acknowledge" (UBX-ACK-ACK) or a "not acknowledge" (UBX-ACK-NAK) message back to the sender, depending on whether or not the message was processed correctly.
I have corrected the issue and can submit a PR if you would like me to. The modified code is copied below. I am not sure how to highlight the changes inside a code block as bolding doesn't seem to work inside the code block.
The changes also address another issue with the indication of a valid packet. This is now more reliable as well.
SparkFun_Ublox_Arduino_Library.cpp
void SFE_UBLOX_GPS::processUBXpacket(ubxPacket *msg)
{
switch (msg->cls)
{
case UBX_CLASS_ACK:
//We don't want to store ACK packets, just set commandAck flag
if (msg->id == UBX_ACK_ACK && msg->payload[0] == packetCfg.cls && msg->payload[1] == packetCfg.id)
{
//The ack we just received matched the CLS/ID of last packetCfg sent
if (_printDebug == true)
{
_debugSerial->println("UBX ACK: Acknowledged");
}
commandAck = UBX_ACK_ACK;
}
else if (msg->id == UBX_ACK_NACK && msg->payload[0] == packetCfg.cls && msg->payload[1] == packetCfg.id)
{
//The ack we just received matched the CLS/ID of last packetCfg sent
if (_printDebug == true)
{
_debugSerial->println("UBX ACK: Not-Acknowledged");
}
commandAck = UBX_ACK_NACK;
}
boolean SFE_UBLOX_GPS::waitForResponse(uint8_t requestedClass, uint8_t requestedID, uint16_t maxTime)
{
commandAck = UBX_ACK_NONE; //Reset flag
packetCfg.valid = false; //This will go true when we receive a response to the packet we sent
packetAck.valid = false;
unsigned long startTime = millis();
while (millis() - startTime < maxTime)
{
checkUblox(); //See if new data is available. Process bytes as they come in.
if (packetAck.valid == true)
{
if (commandAck == UBX_ACK_ACK) {
return (true); // Received an ACK
}
else if (commandAck == UBX_ACK_NACK) {
return (false); // Received a NACK
}
boolean SFE_UBLOX_GPS::getPVT(uint16_t maxWait)
{
if (autoPVT)
{
//The GPS is automatically reporting, we just check whether we got unread data
checkUblox();
return moduleQueried.all;
}
else
{
//The GPS is not automatically reporting navigation position so we have to poll explicitly
packetCfg.cls = UBX_CLASS_NAV;
packetCfg.id = UBX_NAV_PVT;
packetCfg.len = 0;
//packetCfg.startingSpot = 20; //Begin listening at spot 20 so we can record up to 20+MAX_PAYLOAD_SIZE = 84 bytes Note:now hard-coded in processUBX
packetCfg.valid = false;
SparkFun_Ublox_Arduino_Library.h
const uint8_t I2C_POLLING_WAIT_MS = 25; //Limit checking of new characters to every X ms
unsigned long lastCheck = 0;
boolean autoPVT = false; //Whether autoPVT is enabled or not
uint8_t commandAck = UBX_ACK_NONE; //This goes true after we send a command and it's ack'd
uint8_t ubxFrameCounter;