libretiny-eu / libretiny

PlatformIO development platform for IoT modules
http://docs.libretiny.eu/
MIT License
382 stars 55 forks source link

Deep sleep using timer limited to 2 minutes #230

Closed daniel-dona closed 3 months ago

daniel-dona commented 6 months ago

Looks like setting the wake up timer for deep sleep only works as expected up to about 120 seconds (~2 min). Setting a longer sleep time results on sleeping only for about 15 ~ 20 seconds.

With 150 seconds

[1703875377] (2023-12-29 19:42:57):  Type [C-a] [C-h] to see available commands
[1703875377] (2023-12-29 19:42:57):  Terminal ready
[1703875381] (2023-12-29 19:43:01):  Boot
[1703875381] (2023-12-29 19:43:01):  Deep sleep in 5
[1703875382] (2023-12-29 19:43:02):  Deep sleep in 4
[1703875383] (2023-12-29 19:43:03):  Deep sleep in 3
[1703875384] (2023-12-29 19:43:04):  Deep sleep in 2
[1703875385] (2023-12-29 19:43:05):  Deep sleep in 1
[1703875386] (2023-12-29 19:43:06):  Deep sleep for: 150 seconds
[1703875405] (2023-12-29 19:43:25):  Boot
[1703875405] (2023-12-29 19:43:25):  Deep sleep in 5
[1703875406] (2023-12-29 19:43:26):  Deep sleep in 4
[1703875407] (2023-12-29 19:43:27):  Deep sleep in 3
[1703875408] (2023-12-29 19:43:28):  Deep sleep in 2
[1703875409] (2023-12-29 19:43:29):  Deep sleep in 1
[1703875410] (2023-12-29 19:43:30):  Deep sleep for: 150 seconds
[1703875430] (2023-12-29 19:43:50):  Boot
[1703875430] (2023-12-29 19:43:50):  Deep sleep in 5
[1703875431] (2023-12-29 19:43:51):  Deep sleep in 4
[1703875432] (2023-12-29 19:43:52):  Deep sleep in 3
[1703875433] (2023-12-29 19:43:53):  Deep sleep in 2
[1703875434] (2023-12-29 19:43:54):  Deep sleep in 1
[1703875435] (2023-12-29 19:43:55):  Deep sleep for: 150 seconds
[1703875454] (2023-12-29 19:44:14):  Boot

With 120 seconds

[1703875499] (2023-12-29 19:44:59):  Type [C-a] [C-h] to see available commands
[1703875499] (2023-12-29 19:44:59):  Terminal ready
[1703875502] (2023-12-29 19:45:02):  Boot
[1703875502] (2023-12-29 19:45:02):  Deep sleep in 5
[1703875503] (2023-12-29 19:45:03):  Deep sleep in 4
[1703875504] (2023-12-29 19:45:04):  Deep sleep in 3
[1703875505] (2023-12-29 19:45:05):  Deep sleep in 2
[1703875506] (2023-12-29 19:45:06):  Deep sleep in 1
[1703875507] (2023-12-29 19:45:07):  Deep sleep for: 120 seconds
[1703875630] (2023-12-29 19:47:10):  Boot
[1703875630] (2023-12-29 19:47:10):  Deep sleep in 5
[1703875631] (2023-12-29 19:47:11):  Deep sleep in 4
[1703875632] (2023-12-29 19:47:12):  Deep sleep in 3
[1703875633] (2023-12-29 19:47:13):  Deep sleep in 2
[1703875634] (2023-12-29 19:47:14):  Deep sleep in 1
[1703875635] (2023-12-29 19:47:15):  Deep sleep for: 120 seconds
[1703875758] (2023-12-29 19:49:18):  Boot
[1703875758] (2023-12-29 19:49:18):  Deep sleep in 5
[1703875759] (2023-12-29 19:49:19):  Deep sleep in 4
[1703875760] (2023-12-29 19:49:20):  Deep sleep in 3
[1703875761] (2023-12-29 19:49:21):  Deep sleep in 2

Is in deep sleep in both cases, tested checking power consumption using a lab PSU.

Code:

#include <Arduino.h>

#define LT_UART_DEFAULT_PORT 1

void setup() {

  Serial.println("Boot");

  for(int i = 5; i > 0; i--){
    Serial.print("Deep sleep in ");
    Serial.println(i);
    delay(1000);
  }

  int seconds = 60 * 2;

  //int seconds = 60 * 3;

  Serial.print("Deep sleep for: ");
  Serial.print(seconds);
  Serial.println(" seconds");

  delay(100);

  lt_deep_sleep_config_timer(seconds * 1000);
    lt_deep_sleep_enter();

}

void loop() {
}
daniel-dona commented 6 months ago

Seems to be more than one clock source available to be configured for sleep modes, not sure if all of them are available for deep sleep but I think at least the two based on 32kHz crystal imagen

daniel-dona commented 6 months ago

I think the problem is on this part:

uint64_t duration_math = 32768 * sleep_duration;

Looks like the variable is not capable (?) of holding a 64 bit unsigned int, not sure how to probe this in a better way but I tried testing with this piece of code:

void setup() {

  Serial.println("Boot");

  for(int s = 0; s < 300; s++){

    uint32_t sleep_duration = s*1000; //ms
    uint32_t sleep_time;  // From manual_ps_pub.h as UINT32
    uint64_t duration_math = 32768 * sleep_duration;

    if (duration_math / 1000 > 0xFFFFFFFF) {
      // Sleep forever
      sleep_time = 0xFFFFFFFF;
    } else {
      sleep_time = (duration_math / 1000) & 0xFFFFFFFF;
    }

    Serial.print("Seconds: ");
    Serial.print(s);
    Serial.print(" duration_math: ");
    Serial.print(duration_math);
    Serial.print(" sleep_time: ");
    Serial.println(sleep_time);
  }
}

And at about 131 seconds the variable for sleep_time overflow:

[1704116401] (2024-01-01 14:40:01):  Seconds: 124 duration_math: 4063232000 sleep_time: 4063232
[1704116401] (2024-01-01 14:40:01):  Seconds: 125 duration_math: 4096000000 sleep_time: 4096000
[1704116401] (2024-01-01 14:40:01):  Seconds: 126 duration_math: 4128768000 sleep_time: 4128768
[1704116401] (2024-01-01 14:40:01):  Seconds: 127 duration_math: 4161536000 sleep_time: 4161536
[1704116401] (2024-01-01 14:40:01):  Seconds: 128 duration_math: 4194304000 sleep_time: 4194304
[1704116401] (2024-01-01 14:40:01):  Seconds: 129 duration_math: 4227072000 sleep_time: 4227072
[1704116401] (2024-01-01 14:40:01):  Seconds: 130 duration_math: 4259840000 sleep_time: 4259840
[1704116401] (2024-01-01 14:40:01):  Seconds: 131 duration_math: 4292608000 sleep_time: 4292608
[1704116401] (2024-01-01 14:40:01):  Seconds: 132 duration_math: 30408704 sleep_time: 30408
[1704116401] (2024-01-01 14:40:01):  Seconds: 133 duration_math: 63176704 sleep_time: 63176
[1704116401] (2024-01-01 14:40:01):  Seconds: 134 duration_math: 95944704 sleep_time: 95944
[1704116401] (2024-01-01 14:40:01):  Seconds: 135 duration_math: 128712704 sleep_time: 128712
[1704116401] (2024-01-01 14:40:01):  Seconds: 136 duration_math: 161480704 sleep_time: 161480
[1704116401] (2024-01-01 14:40:01):  Seconds: 137 duration_math: 194248704 sleep_time: 194248
[1704116401] (2024-01-01 14:40:01):  Seconds: 138 duration_math: 227016704 sleep_time: 227016
[1704116401] (2024-01-01 14:40:01):  Seconds: 139 duration_math: 259784704 sleep_time: 259784
[1704116401] (2024-01-01 14:40:01):  Seconds: 140 duration_math: 292552704 sleep_time: 292552
[1704116401] (2024-01-01 14:40:01):  Seconds: 141 duration_math: 325320704 sleep_time: 325320

Using seconds and not milliseconds works fine, at least tested up to 15 minutes, but some precision is lost... Working on a PR

daniel-dona commented 6 months ago

Seems to work fine now with the change:

imagen

kuba2k2 commented 6 months ago

Since sleep_duration is an uint32_t, the line uint64_t duration_math = 32768 * sleep_duration; is probably using 32-bit math, and it's cast to 64-bit later. That probably causes the overflow.

Liionboy commented 5 months ago

Hello,

How did you fix this?

Do you use any external components or how?

Thanks

Bl00d-B0b commented 3 months ago

hello,

I use bk72xx boards in esphome home assistant integration. how I can add deep sleep to my bk72xx boards.

could you provide ,yaml example? or maybe something must be added before?

Ed

kuba2k2 commented 3 months ago

Fixed in #253.