Go Down

Topic: I2C state during sleep causes excessive power consumption (Read 1 time) previous topic - next topic

sslupsky

There is an issue with the I2C bus state when using low power deep sleep.  The problem occurs when the MCU is sleeping.  When the I2C master goes to sleep, the SCL and SDA lines are pulled low.  This causes excessive power consumption during sleep because of the I2C pull up resistors.  The next time the master wakes up, the SCL and SDA lines are pulled high and stay that way until the next I2C transaction.  This cycle repeats.  Here is an example sketch attached below.  In this example, the rtc alarm event fires every 10 seconds and the heart beat timeout is 30 seconds.  In this case, on the first heartbeat timeout at t=30 seconds, the I2C message is sent and the SCL and SDA lines are pulled low.  At t=40 seconds, the MCU wakes up and the SCL and SDA lines are pulled high.  At t=50 seconds the SCL and SDA remain high (no I2C message sent).  At t=60 seconds, an I2C message is sent and the SDA and SCL are pulled low ...


Code: [Select]
void loop() {
  Watchdog.reset();
  if ( rtcTick >= heartBeatTick ) {
    heartBeatTick += HEARTBEAT_PERIOD;
    hostWire.beginTransmission(2);
    hostWire.write("Blink");
    hostWire.endTransmission();
  }
  LowPower.deepSleep();
}

void rtcAlarmEvent() {
// RTC alarm wake interrupt callback
  rtcTick += RTC_ALARM_PERIOD;
  rtc.setAlarmEpoch( rtcTick );  //  Set the time for the next RTC Alarm
}


I have not determined why the SCL and SDA pins are being pulled low at the end of the I2C transaction.  If I insert a large delay(100) after the endTransmission() the SCL and SDA lines are pulled high properly at the end of the bus cycle.


sslupsky

I determined the source of this problem.  When the Wire tells the I2C to stop the bus cycle, the command is issued and synced to the peripheral.  The command to stop is non-blocking so program execution continues.  If you subsequently go to sleep right away before the stop sequence has not been completed by the peripheral, the master still owns the bus and keeps SCL and SDA low.  To fix this, you need to insert a short delay (about 20 us) after issuing the STOP command.

I'll submit a PR on Github for this issue.

pert

Great work identifying the problem and finding a solution. Thanks for your contributions to the Arduino project sslupsky!

Go Up