Correct handling of millis() rollover

millis() returns an unsigned long integer, and C++ guarantees that
arithmetics on this type work modulo (ULONG_MAX+1). This behavior
ensures that computing a delay as

    millis() - previousMillis

yields the correct result across millis() rollover events, as long as
the time actually elapsed is less than about 49.7 days.
This commit is contained in:
Edgar Bonet 2020-02-20 19:03:13 +01:00
parent 96625de7d3
commit 939534d580
8 changed files with 12 additions and 25 deletions

View File

@ -58,7 +58,7 @@ void setup()
Serial.println(" no response :("); Serial.println(" no response :(");
} }
uint32_t updateTime = 1000; uint32_t timer = 0;
void loop() // run over and over again void loop() // run over and over again
{ {
@ -67,9 +67,9 @@ void loop() // run over and over again
if ((c) && (GPSECHO)) if ((c) && (GPSECHO))
Serial.write(c); Serial.write(c);
if (millis() > updateTime) if (millis() - timer > 1000)
{ {
updateTime = millis() + 1000; timer = millis();
if (GPS.LOCUS_ReadStatus()) { if (GPS.LOCUS_ReadStatus()) {
Serial.print("\n\nLog #"); Serial.print("\n\nLog #");
Serial.print(GPS.LOCUS_serial, DEC); Serial.print(GPS.LOCUS_serial, DEC);
@ -98,5 +98,5 @@ void loop() // run over and over again
Serial.print((int)GPS.LOCUS_percent); Serial.print("% Used "); Serial.print((int)GPS.LOCUS_percent); Serial.print("% Used ");
}//if (GPS.LOCUS_ReadStatus()) }//if (GPS.LOCUS_ReadStatus())
}//if (millis() > updateTime) }//if (millis() - timer > 1000)
}//loop }//loop

View File

@ -76,8 +76,6 @@ void loop() // run over and over again
if (!GPS.parse(GPS.lastNMEA())) // this also sets the newNMEAreceived() flag to false if (!GPS.parse(GPS.lastNMEA())) // this also sets the newNMEAreceived() flag to false
return; // we can fail to parse a sentence in which case we should just wait for another return; // we can fail to parse a sentence in which case we should just wait for another
} }
// if millis() or timer wraps around, we'll just reset it
if (timer > millis()) timer = millis();
// approximately every 2 seconds or so, print out the current stats // approximately every 2 seconds or so, print out the current stats
if (millis() - timer > 2000) { if (millis() - timer > 2000) {

View File

@ -101,9 +101,6 @@ void loop() // run over and over again
return; // we can fail to parse a sentence in which case we should just return; // we can fail to parse a sentence in which case we should just
// wait for another // wait for another
} }
// if millis() or timer wraps around, we'll just reset it
if (timer > millis())
timer = millis();
// approximately every 2 seconds or so, random intervals, print out the // approximately every 2 seconds or so, random intervals, print out the
// current stats // current stats

View File

@ -64,8 +64,6 @@ void loop() // run over and over again
if (!GPS.parse(GPS.lastNMEA())) // this also sets the newNMEAreceived() flag to false if (!GPS.parse(GPS.lastNMEA())) // this also sets the newNMEAreceived() flag to false
return; // we can fail to parse a sentence in which case we should just wait for another return; // we can fail to parse a sentence in which case we should just wait for another
} }
// if millis() or timer wraps around, we'll just reset it
if (timer > millis()) timer = millis();
// approximately every 2 seconds or so, print out the current stats // approximately every 2 seconds or so, print out the current stats
if (millis() - timer > 2000) { if (millis() - timer > 2000) {

View File

@ -68,7 +68,7 @@ void setup()
} }
} }
uint32_t updateTime = 1000; uint32_t timer = 0;
void loop() // run over and over again void loop() // run over and over again
{ {
@ -77,9 +77,9 @@ void loop() // run over and over again
if ((c) && (GPSECHO)) if ((c) && (GPSECHO))
Serial.write(c); Serial.write(c);
if (millis() > updateTime) if (millis() - timer > 1000)
{ {
updateTime = millis() + 1000; timer = millis();
if (GPS.LOCUS_ReadStatus()) { if (GPS.LOCUS_ReadStatus()) {
Serial.print("\n\nLog #"); Serial.print("\n\nLog #");
Serial.print(GPS.LOCUS_serial, DEC); Serial.print(GPS.LOCUS_serial, DEC);
@ -108,7 +108,7 @@ void loop() // run over and over again
Serial.print((int)GPS.LOCUS_percent); Serial.print("% Used "); Serial.print((int)GPS.LOCUS_percent); Serial.print("% Used ");
}//if (GPS.LOCUS_ReadStatus()) }//if (GPS.LOCUS_ReadStatus())
}//if (millis() > updateTime) }//if (millis() - timer > 1000)
}//loop }//loop

View File

@ -78,9 +78,6 @@ void loop() // run over and over again
return; // we can fail to parse a sentence in which case we should just wait for another return; // we can fail to parse a sentence in which case we should just wait for another
} }
// if millis() or timer wraps around, we'll just reset it
if (timer > millis()) timer = millis();
// approximately every 2 seconds or so, print out the current stats // approximately every 2 seconds or so, print out the current stats
if (millis() - timer > 2000) { if (millis() - timer > 2000) {
timer = millis(); // reset the timer timer = millis(); // reset the timer

View File

@ -637,8 +637,7 @@ bool Adafruit_GPS::wakeup(void) {
/**************************************************************************/ /**************************************************************************/
/*! /*!
@brief Time in seconds since the last position fix was obtained. Will @brief Time in seconds since the last position fix was obtained.
fail by rolling over to zero after one millis() cycle, about 6-1/2 weeks.
@return nmea_float_t value in seconds since last fix. @return nmea_float_t value in seconds since last fix.
*/ */
/**************************************************************************/ /**************************************************************************/
@ -648,8 +647,7 @@ nmea_float_t Adafruit_GPS::secondsSinceFix() {
/**************************************************************************/ /**************************************************************************/
/*! /*!
@brief Time in seconds since the last GPS time was obtained. Will fail @brief Time in seconds since the last GPS time was obtained.
by rolling over to zero after one millis() cycle, about 6-1/2 weeks.
@return nmea_float_t value in seconds since last GPS time. @return nmea_float_t value in seconds since last GPS time.
*/ */
/**************************************************************************/ /**************************************************************************/
@ -659,8 +657,7 @@ nmea_float_t Adafruit_GPS::secondsSinceTime() {
/**************************************************************************/ /**************************************************************************/
/*! /*!
@brief Time in seconds since the last GPS date was obtained. Will fail @brief Time in seconds since the last GPS date was obtained.
by rolling over to zero after one millis() cycle, about 6-1/2 weeks.
@return nmea_float_t value in seconds since last GPS date. @return nmea_float_t value in seconds since last GPS date.
*/ */
/**************************************************************************/ /**************************************************************************/

View File

@ -60,7 +60,7 @@ void Adafruit_GPS::newDataValue(nmea_index_t idx, nmea_float_t v) {
// weighting factor for smoothing depends on delta t / tau // weighting factor for smoothing depends on delta t / tau
nmea_float_t w = nmea_float_t w =
min((nmea_float_t)1.0, min((nmea_float_t)1.0,
((nmea_float_t)millis() - val[idx].lastUpdate) / val[idx].response); (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