mccloudaero / evpr

Electric Variable Pitch Rotor
http://mccloudaero.com
GNU General Public License v3.0
2 stars 1 forks source link

Deep Sleep Considerations #75

Open GeorgesOatesLarsen opened 3 years ago

GeorgesOatesLarsen commented 3 years ago

Firstly, there is the silly placement of the ESP32 power LED. This will bleed our power. Remove it. #73

See documentation on sleep modes for ESP32: https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/sleep_modes.html

We are namely interested in esp32 deep sleep. Wakeup can be triggered by any of the RTC_GPIO pins. It is unclear why these are named after the Real Time Clock, but in general RTC_GPIO are the only pins accessible in deep sleep or deeper.

See: https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/gpio.html

While I'm at it, here are the big three datasheets from esp32: https://www.espressif.com/sites/default/files/documentation/esp32_hardware_design_guidelines_en.pdf https://www.espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf https://www.espressif.com/sites/default/files/documentation/esp32_datasheet_en.pdf

And for the WROOM: https://www.espressif.com/sites/default/files/documentation/esp32-wroom-32_datasheet_en.pdf

Somewhere in those four documents lies documentation on what the RTC-GPIO pins actually are.

GeorgesOatesLarsen commented 3 years ago

Ah, yes, section 2.2 of the WROOM database. Pin definitions. Anything labeled "RTC_GPIOX", such as "RTC_GPIO0" or "RTC_GPIO1", so forth. Those are our RTC GPIO pins.

GeorgesOatesLarsen commented 3 years ago

We are interested in awakening on RAWSENSE. This is IO34, pin 6. Fortunately for us, this is, in fact, an RTC_GPIO. It is RTC_GPIO4.

We are interested in keeping our BAT_EN signal low. Currently, BAT_EN lives on IO21, pin 33. Unfortunately, this is not an RTC GPIO.

We have two options:

  1. Relocate BAT_EN to a GPIO pin that is RTC_GPIO.
  2. Some sources suggest that a special setting can keep the main GPIO active during deep sleep.

Namely:

gpio_hold_en(GPIO_NUM_25);
gpio_deep_sleep_hold_en();

https://github.com/espressif/arduino-esp32/issues/2712

Need to test what the power implications of that second option are. Will test now.

GeorgesOatesLarsen commented 3 years ago

The excellent news is that this approach does successfully maintain GPIO_21 in deep sleep mode. Here is a simple test:

void setup() {
  Serial.begin(115200);
  pinMode(GPIO_NUM_21,OUTPUT);
  digitalWrite(GPIO_NUM_21, LOW);
}

void loop() {
  for (int i = 0; i < 5; i++) {
    Serial.println("Going to sleep soon.");
    delay(1000);
  }
  gpio_hold_en((gpio_num_t) 21);
  gpio_deep_sleep_hold_en();
  delay(1000);
  esp_deep_sleep_start();
  Serial.println("This never prints");
}

Changing the digitalWRITE call to HIGH or LOW will cause the pin to maintain its state. Deep sleep is being entered. Second to next step is to manually remove the drainer diode and get some current measurements. But first, lets see if we can awaken from deep sleep.

GeorgesOatesLarsen commented 3 years ago

The ESP-IDF function for wakeup is esp_sleep_enable_ext0_wakeup. We want ext0 since we want only a single pin to wake us up. Documented here: https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/sleep_modes.html

Yes, wake from sleep functions perfectly:

void setup() {
  Serial.begin(115200);
  Serial.println("BOOT!");
  pinMode(GPIO_NUM_21,OUTPUT);
  digitalWrite(GPIO_NUM_21, LOW);
  esp_sleep_enable_ext0_wakeup((gpio_num_t) 34, HIGH);
}

void loop() {
  for (int i = 0; i < 5; i++) {
    Serial.println("Going to sleep soon.");
    delay(1000);
  }
  gpio_hold_en((gpio_num_t) 21);
  gpio_deep_sleep_hold_en();
  delay(1000);
  esp_deep_sleep_start();
  Serial.println("This never prints, since deep sleep resets memory.");
}
BOOT!
Going to sleep soon.
Going to sleep soon.
Going to sleep soon.
Going to sleep soon.
Going to sleep soon.
ets Jun  8 2016 00:22:57

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:0x3fff0018,len:4
load:0x3fff001c,len:1044
load:0x40078000,len:10044
load:0x40080400,len:5900
entry 0x400806ac
BOOT!
GeorgesOatesLarsen commented 3 years ago

Now I just need to characterize the power draw. I don't have very sensitive current measuring capabilities, but I'll do my best. I will deliver batteries to the battery pins, passed through voltmeter.

Yeeeeaaah, my multimeter can't even measure the current when in deep sleep mode. It's like, on the order of less than a microamp. I am pretty sure a full charge will last years with this current consumption,

GeorgesOatesLarsen commented 3 years ago

Just as a final summary:

Near start-up, call:

  esp_sleep_enable_ext0_wakeup((gpio_num_t) 34, HIGH);

to enable wakeup triggered by rising engine power.

To go into deep sleep: Bring GPIO21 to LOW (this disables use of the battery)

Then, call:


gpio_hold_en((gpio_num_t) 21);
gpio_deep_sleep_hold_en();```

Then wait a few hundred milliseconds for good measure.

Then, call:
```C
esp_deep_sleep_start();```

And as of that moment, the ESP32 will enter deep sleep.

Please note that deep sleep totally wipes ESP32 memory, so no variable values or anything of that sort will be retained after waking up. Waking up from deep sleep will be akin to experiencing a reset. So, if there is anything nontransient you want to return after deep sleep, you'll need to use the onboard flash to save it.