reZach
reZach

Reputation: 9479

esp_deep_sleep doesn't work with large values

It is advertised/part of the defined parameter list that esp_deep_sleep takes in a uint64_t as a parameter, representing the amount of microseconds to sleep the ESP32, however I believe this is a bug. If you see this simple code below, using the maximum value of an uint64_t, 18446744073709551615, causes the ESP32 to reset prematurely. You can see this in the sample code below with output [that repeats indefinitely].

#include <esp_sleep.h>
#include <stdlib.h>
#include "RTClib.h"

RTC_DS3231 rtc;

void setup() {
  Serial.begin(115200);

  // Initialize the RTC
  if (!rtc.begin()) {
    while (1)
      delay(10);
  }

  // Works (uint64_t max value / 2)
  // Serial.println("before uint64_t / 2 sleep");  
  // esp_deep_sleep((uint64_t)9223372036854775807);  // yes
  // Serial.println("after uint64_t / 2 sleep");  

  // Doesn't work (unit64_t max value)
  Serial.println("before uint64_t sleep");
  esp_deep_sleep((uint64_t)18446744073709551615);  // no
  Serial.println("after uint64_t sleep");
}

void loop() {
}

Sample output

rst:0x5 (DEEPSLEEP_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0030,len:4832
load:0x40078000,len:16460
load:0x40080400,len:4
load:0x40080404,len:3504
entry 0x400805cc
E (57) esp_core�xump_flash: Core dump data check failed:
Calculated checksum='9d56f9c2'
Image checksum='ffffffff'
before uint64_t sleep
ets Jul 29 2019 12:21:46

rst:0x5 (DEEPSLEEP_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0030,len:4832
load:0x40078000,len:16460
load:0x40080400,len:4
load:0x40080404,len:3504
entry 0x400805cc
E (57) esp_corefxump_flash: Core dump data check failed:
Calculated checksum='9d56f9c2'
Image checksum='ffffffff'
before uint64_t sleep
ets Jul 29 2019 12:21:46

If you try to sleep the ESP32 with half of the maximum value, the ESP32 sleeps as expected.

#include <esp_sleep.h>
#include <stdlib.h>
#include "RTClib.h"

RTC_DS3231 rtc;

void setup() {
  Serial.begin(115200);

  // Initialize the RTC
  if (!rtc.begin()) {
    while (1)
      delay(10);
  }

  // Works (uint64_t max value / 2)
  Serial.println("before uint64_t / 2 sleep");  
  esp_deep_sleep((uint64_t)9223372036854775807);  // yes
  Serial.println("after uint64_t / 2 sleep");  

  // Doesn't work (unit64_t max value)
  // Serial.println("before uint64_t sleep");
  // esp_deep_sleep((uint64_t)18446744073709551615);  // no
  // Serial.println("after uint64_t sleep");
}

void loop() {
}

Sample output

rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0030,len:4832
load:0x40078000,len:16460
load:0x40080400,len:4
load:0x40080404,len:3504
entry 0x400805cc
E (152) esp_cor
�VW}���͡: Core dump data check failed:
Calculated checksum='9d56f9c2'
Image checksum='ffffffff'
before uint64_t / 2 sleep

In order to save battery for my purposes, I want to deep-sleep the ESP32 for a full 24 hours, but am unable to do so because of this limitation of esp_deep_sleep. I found some success in approaching this limitation with the workaround below, but would be interested if there was a more-supported/easy solution to this problem.

#include <esp_sleep.h>
#include <stdlib.h>
#include "RTClib.h"

RTC_DS3231 rtc;

RTC_DATA_ATTR int is_init = 0;
RTC_DATA_ATTR uint64_t multiply_sleep_time = 1;

void setup() {
  // Sleeps for 24 (2 * 12 hours) after module has been initialized
  if (is_init == 1 && multiply_sleep_time > 0){
    multiply_sleep_time--;
    esp_deep_sleep((uint64_t)9223372036854775807);
  }

  Serial.begin(115200);

  // Initialize the RTC
  if (!rtc.begin()) {
    while (1)
      delay(10);
  }

  // Some code that needs to run at startup, and every 24 hours after
  is_init = 1;

  Serial.println("init");

  // Works (uint64_t max value / 2)
  Serial.println("before uint64_t / 2 sleep");  
  esp_deep_sleep((uint64_t)9223372036854775807);
  Serial.println("after uint64_t / 2 sleep");
}

void loop() {
}

Upvotes: 0

Views: 60

Answers (0)

Related Questions