Skip to content
This repository was archived by the owner on Jan 28, 2021. It is now read-only.
This repository was archived by the owner on Jan 28, 2021. It is now read-only.

millis() does not work during sleep #44

@sslupsky

Description

@sslupsky

Subject of the issue

checkUbloxI2C() uses millis() to check time and this time can be unreliable if the mcu goes to sleep since the SysTick on which millis() is based is stopped during sleep. Since checkUbloxI2C() uses a global "lastcheck" to track time elapsed between calls to checkUbloxI2C(), this causes an undesirable additional delay when checking the module after waking from sleep resulting in increased power consumption.

millis() is also used in waitForResponse() but since that function only uses millis() for relative time elapsed within the function itself, it is not a problem here except that generally, it would be preferable if waitForResponse() was not blocking.

My workaround for this problem was to use a tick from the real time clock instead of millis(). In the code snippet below, I have replaced the call to millis() with a global variable (volatile) that keeps track of the time from the rtc.

I suggest perhaps the "proper" solution might be abstract millis() using a virtual function and if the user needs to replace it with something else, it can be replaced by instantiating your own millis() function.

boolean SFE_UBLOX_GPS::checkUbloxI2C()
{
  if (rtcTickMS - lastCheck >= I2C_POLLING_WAIT_MS)
  {
    //Get the number of bytes available from the module
    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.
      return (false);                          //Sensor did not ACK

    _i2cPort->requestFrom((uint8_t)_gpsI2Caddress, (uint8_t)2);
    if (_i2cPort->available())
    {
      uint8_t msb = _i2cPort->read();
      uint8_t lsb = _i2cPort->read();
      bytesAvailable = (uint16_t)msb << 8 | lsb;
    }

    if (bytesAvailable == 0)
    {
      if (_printDebug == true)
      {
        _debugSerial->println("No bytes available");
      }
      lastCheck = rtcTickMS; //Put off checking to avoid I2C bus traffic
      return true;
    }

I also noticed today commit e3e170e made in July to address an issue when the module is not ready. The commit adds a blocking delay in this event which causes additional power consumption. I would like to ask if there is something that can be done to eliminate the blocking delay.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions