diff --git a/library.properties b/library.properties index 79ac233..0a1e61b 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=SparkFun u-blox GNSS Arduino Library -version=2.0.11 +version=2.0.12 author=SparkFun Electronics maintainer=SparkFun Electronics sentence=Library for I2C and Serial Communication with u-blox GNSS modules

diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp index a6068ec..22b2d6a 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.cpp @@ -715,11 +715,28 @@ boolean SFE_UBLOX_GNSS::checkUbloxI2C(ubxPacket *incomingUBX, uint8_t requestedC uint16_t bytesAvailable = 0; _i2cPort->beginTransmission(_gpsI2Caddress); _i2cPort->write(0xFD); //0xFD (MSB) and 0xFE (LSB) are the registers that contain number of bytes available - if (_i2cPort->endTransmission(false) != 0) //Send a restart command. Do not release bus. + uint8_t i2cError = _i2cPort->endTransmission(false); //Send a restart command. Do not release bus. + if (i2cError != 0) + { + if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging + { + _debugSerial->print(F("checkUbloxI2C: I2C error: endTransmission returned ")); + _debugSerial->println(i2cError); + } return (false); //Sensor did not ACK + } - _i2cPort->requestFrom((uint8_t)_gpsI2Caddress, (uint8_t)2); - if (_i2cPort->available()) + uint8_t bytesReturned = _i2cPort->requestFrom((uint8_t)_gpsI2Caddress, (uint8_t)2); + if (bytesReturned != 2) + { + if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging + { + _debugSerial->print(F("checkUbloxI2C: I2C error: requestFrom 0xFD returned ")); + _debugSerial->println(bytesReturned); + } + return (false); //Sensor did not return 2 bytes + } + //if (_i2cPort->available()) { uint8_t msb = _i2cPort->read(); uint8_t lsb = _i2cPort->read(); @@ -728,7 +745,8 @@ boolean SFE_UBLOX_GNSS::checkUbloxI2C(ubxPacket *incomingUBX, uint8_t requestedC //I believe this is a u-blox bug. Device should never present an 0xFF. if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging { - _debugSerial->println(F("checkUbloxI2C: u-blox bug, length lsb is 0xFF")); + _debugSerial->print(F("checkUbloxI2C: u-blox bug? Length lsb is 0xFF. i2cPollingWait is ")); + _debugSerial->println(i2cPollingWait); } if (debugPin >= 0) { @@ -739,6 +757,23 @@ boolean SFE_UBLOX_GNSS::checkUbloxI2C(ubxPacket *incomingUBX, uint8_t requestedC lastCheck = millis(); //Put off checking to avoid I2C bus traffic return (false); } + // if (msb == 0xFF) + // { + // //I believe this is a u-blox bug. Device should never present an 0xFF. + // if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging + // { + // _debugSerial->print(F("checkUbloxI2C: u-blox bug? Length msb is 0xFF. i2cPollingWait is ")); + // _debugSerial->println(i2cPollingWait); + // } + // if (debugPin >= 0) + // { + // digitalWrite((uint8_t)debugPin, LOW); + // delay(10); + // digitalWrite((uint8_t)debugPin, HIGH); + // } + // lastCheck = millis(); //Put off checking to avoid I2C bus traffic + // return (false); + // } bytesAvailable = (uint16_t)msb << 8 | lsb; } @@ -762,17 +797,17 @@ boolean SFE_UBLOX_GNSS::checkUbloxI2C(ubxPacket *incomingUBX, uint8_t requestedC //Clear the MSbit bytesAvailable &= ~((uint16_t)1 << 15); - if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging - { - _debugSerial->print(F("checkUbloxI2C: Bytes available error: ")); - _debugSerial->println(bytesAvailable); - if (debugPin >= 0) - { - digitalWrite((uint8_t)debugPin, LOW); - delay(10); - digitalWrite((uint8_t)debugPin, HIGH); - } - } + // if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging + // { + // _debugSerial->print(F("checkUbloxI2C: Bytes available error: ")); + // _debugSerial->println(bytesAvailable); + // if (debugPin >= 0) + // { + // digitalWrite((uint8_t)debugPin, LOW); + // delay(10); + // digitalWrite((uint8_t)debugPin, HIGH); + // } + // } } #ifndef SFE_UBLOX_REDUCED_PROG_MEM @@ -9615,10 +9650,13 @@ uint32_t SFE_UBLOX_GNSS::getProcessNMEAMask() //Max is 40Hz(?!) boolean SFE_UBLOX_GNSS::setNavigationFrequency(uint8_t navFreq, uint16_t maxWait) { - //if(updateRate > 40) updateRate = 40; //Not needed: module will correct out of bounds values + if (navFreq > 40) + navFreq = 40; // Limit navFreq to 40Hz so i2cPollingWait is set correctly //Adjust the I2C polling timeout based on update rate - i2cPollingWait = 1000 / (((int)navFreq) * 4); //This is the number of ms to wait between checks for new I2C data + //Do this even if the sendCommand fails + i2cPollingWaitNAV = 1000 / (((int)navFreq) * 4); //This is the number of ms to wait between checks for new I2C data + i2cPollingWait = i2cPollingWaitNAV < i2cPollingWaitHNR ? i2cPollingWaitNAV : i2cPollingWaitHNR; // Set i2cPollingWait to the lower of NAV and HNR //Query the module packetCfg.cls = UBX_CLASS_CFG; @@ -9664,8 +9702,12 @@ uint8_t SFE_UBLOX_GNSS::getNavigationFrequency(uint16_t maxWait) //Set the elapsed time between GNSS measurements in milliseconds, which defines the rate boolean SFE_UBLOX_GNSS::setMeasurementRate(uint16_t rate, uint16_t maxWait) { + if (rate < 25) // "Measurement rate should be greater than or equal to 25 ms." + rate = 25; + //Adjust the I2C polling timeout based on update rate - i2cPollingWait = rate / 4; //This is the number of ms to wait between checks for new I2C data + i2cPollingWaitNAV = rate / 4; //This is the number of ms to wait between checks for new I2C data + i2cPollingWait = i2cPollingWaitNAV < i2cPollingWaitHNR ? i2cPollingWaitNAV : i2cPollingWaitHNR; // Set i2cPollingWait to the lower of NAV and HNR //Query the module packetCfg.cls = UBX_CLASS_CFG; @@ -10950,6 +10992,14 @@ boolean SFE_UBLOX_GNSS::getSensorFusionStatus(UBX_ESF_STATUS_sensorStatus_t *sen // Returns true if the setHNRNavigationRate is successful boolean SFE_UBLOX_GNSS::setHNRNavigationRate(uint8_t rate, uint16_t maxWait) { + if (rate > 40) + rate = 40; // Limit rate to 40Hz so i2cPollingWait is set correctly + + //Adjust the I2C polling timeout based on update rate + //Do this even if the sendCommand is not ACK'd + i2cPollingWaitHNR = 1000 / (((int)rate) * 4); //This is the number of ms to wait between checks for new I2C data + i2cPollingWait = i2cPollingWaitNAV < i2cPollingWaitHNR ? i2cPollingWaitNAV : i2cPollingWaitHNR; // Set i2cPollingWait to the lower of NAV and HNR + packetCfg.cls = UBX_CLASS_CFG; packetCfg.id = UBX_CFG_HNR; packetCfg.len = 0; @@ -10965,10 +11015,6 @@ boolean SFE_UBLOX_GNSS::setHNRNavigationRate(uint8_t rate, uint16_t maxWait) //Update the navigation rate sfe_ublox_status_e result = sendCommand(&packetCfg, maxWait); // We are only expecting an ACK - //Adjust the I2C polling timeout based on update rate - if (result == SFE_UBLOX_STATUS_DATA_SENT) - i2cPollingWait = 1000 / (((int)rate) * 4); //This is the number of ms to wait between checks for new I2C data - return (result == SFE_UBLOX_STATUS_DATA_SENT); } diff --git a/src/SparkFun_u-blox_GNSS_Arduino_Library.h b/src/SparkFun_u-blox_GNSS_Arduino_Library.h index 47a38fc..91c2321 100644 --- a/src/SparkFun_u-blox_GNSS_Arduino_Library.h +++ b/src/SparkFun_u-blox_GNSS_Arduino_Library.h @@ -1351,6 +1351,8 @@ class SFE_UBLOX_GNSS //If we are expecting an update every X Hz then we should check every quarter that amount of time //Otherwise we may block ourselves from seeing new data uint8_t i2cPollingWait = 100; //Default to 100ms. Adjusted when user calls setNavigationFrequency() or setHNRNavigationRate() or setMeasurementRate() + uint8_t i2cPollingWaitNAV = 100; //We need to record the desired polling rate for standard nav messages + uint8_t i2cPollingWaitHNR = 100; //and for HNR too so we can set i2cPollingWait to the lower of the two //The SPI polling wait is a little different. checkUbloxSpi will delay for this amount before returning if //there is no data waiting to be read. This prevents waitForACKResponse from pounding the SPI bus too hard.