paperdink / PaperdInk-Library

Arduino Library to interact with Paperd.Ink
MIT License
21 stars 8 forks source link

External wake-up from deep sleep #21

Closed semyonsh closed 1 year ago

semyonsh commented 1 year ago

Hi there,

Is there a way to enable wake-up from deep sleep mode using external wake-up using esp_sleep_enable_ext1_wakeup() (docs)?

This would allow to assign different actions based on button press by reading out the pin that was pressed with esp_sleep_get_ext1_wakeup_status().

I've tried creating a function that could handle this, but no luck so far:

int8_t PaperdinkDeviceBaseClass::deep_sleep_timer_button_multi_wakeup(uint64_t sleep_time_us, uint8_t gpio_num)
{
    // Turn off everything
    disable_everything();
    esp_sleep_enable_timer_wakeup(sleep_time_us);

    uint64_t ext_wakeup_pin_mask = 1ULL << gpio_num;
    esp_sleep_enable_ext1_wakeup(ext_wakeup_pin_mask, ESP_EXT1_WAKEUP_ANY_HIGH);

    Serial.printf("Timer wakeup after %lld us or button on pin %d", sleep_time_us, gpio_num);
    // Go to sleep
    esp_deep_sleep_start();

    return 0;
}

Setting the wake-up mode to ESP_EXT1_WAKEUP_ALL_LOW just results in looping because the button seems to be in low state by default. The docs also seem to suggest RTC peripherals should be powered and set to pullup, but I haven't had any luck with setting it manually:

esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
//BUTTON_3_PIN
gpio_pullup_dis(GPIO_NUM_4);

I'm not that experienced with ESP32, C++ programming and this board in particular, so I might just try something that isn't supported by hardware or having a big oversight, please correct me if I'm wrong. If there is any alternative way to check for button pins that were pressed in setup() coming from deep sleep i'd love to hear about it.

timendum commented 1 year ago

You need the esp_sleep_get_ext1_wakeup_status method. There is no need of esp_sleep_pd_config or gpio_pullup_dis.

Check this:

/*
Method to get the GPIO that triggered the wakeup
*/
int get_GPIO_wake_up() {
  uint64_t GPIO_reason;
  int pin_id;
  esp_sleep_wakeup_cause_t wakeup_reason = esp_sleep_get_wakeup_cause();
  switch (wakeup_reason) {
    case ESP_SLEEP_WAKEUP_EXT0:
      DEBUG.println("Wakeup caused by external signal using RTC_IO");
      break;
    case ESP_SLEEP_WAKEUP_EXT1:
      DEBUG.println("Wakeup caused by external signal using RTC_CNTL");
      GPIO_reason = esp_sleep_get_ext1_wakeup_status();
      if (GPIO_reason > 0) {
        pin_id = round(log(GPIO_reason) / log(2));
        DEBUG.printf("Button PIN that triggered the wake up: %d\n", pin_id);
        return pin_id;
      }
      break;
    case ESP_SLEEP_WAKEUP_TIMER:
      DEBUG.println("Wakeup caused by timer");
      break;
    default:
      DEBUG.printf("Wakeup was not caused by deep sleep: %d\n", wakeup_reason);
      break;
  }
  return 0;
}

It works only with esp_sleep_enable_ext1_wakeup and not esp_sleep_enable_ext0_wakeup (or the standard method in library).

semyonsh commented 1 year ago

Cheers, thank you for this snippet.

The real challenge I stated is putting the board in deep sleep for ext1 with esp_sleep_enable_ext1_wakeup so i'm able to read out a pin. Doing what you're describing would be the next step, atleast if I don't misunderstand.

Do you have any pointers on how to proceed with putting the board in deep sleep with ext1?

timendum commented 1 year ago

I think there is nothing in the library, but I've done this:

#define BUTTON_PIN_BITMASK 0x8004014

int8_t deep_sleep_timer_buttons_wakeup() {
  /* Sleep till update time.
   * Align updates to 12am so that date change aligns
   * with actual day change.
   */
  uint64_t sleep_time = (86400 / (UPDATES_PER_DAY)) -
                 (((Paperdink_Date.mil_hour * 3600) +
                   (Paperdink_Date.min * 60) + (Paperdink_Date.sec)) %
                  (86400 / UPDATES_PER_DAY));
    sleep_time += 1;
  }
  DEBUG.println("Turning off everything");
  delay(1000);
  // Turn off everything
  Paperdink.disable_everything();

  esp_sleep_enable_timer_wakeup(sleep_time * S_TO_uS_FACTOR);
  esp_sleep_enable_ext1_wakeup((uint64_t)BUTTON_PIN_BITMASK,
                               ESP_EXT1_WAKEUP_ANY_HIGH);  // 1 = High, 0 = Low
  DEBUG.printf("Timer wakeup after %lld s or button is pressed",
                sleep_time);
  // Go to sleep
  esp_deep_sleep_start();

  return 0;
}

The BUTTON_PIN_BITMASK is the hex form of 2^BUTTON_1_PIN + 2^BUTTON_2_PIN + ...

semyonsh commented 1 year ago

This boils down to the exact same function I've put in the starting post.

After testing a bit more I think my issue comes down to the expectations I was having regarding the ext1 deep sleep. It just takes a lot longer than the ext0 deep sleep to be reactive to a (new) pin being pressed it seems in my case. It either processes it with a long delay, or queues up the pins pressed it looks like. Sometimes it does not react at all, until pressed again after a minute or two.

I'll do some more tests such as powering off completely and starting from scratch to exclude some other causes as to why it's so slow or else just accept it. But now at least I have some confirmation this is the way to go. Thank you :)!

lumenlunae commented 10 months ago

@semyonsh Any other luck on this? I know it's almost a year old but I'm trying for the same thing, I think. Once I tried moving to ext1 nothing seems to work. ANY_HIGH just keeps restarting the device in a loop. I can't read any of the buttons at all this way. Checking if you figured anything on this. Thank you!

semyonsh commented 10 months ago

@semyonsh Any other luck on this? I know it's almost a year old but I'm trying for the same thing, I think. Once I tried moving to ext1 nothing seems to work. ANY_HIGH just keeps restarting the device in a loop. I can't read any of the buttons at all this way. Checking if you figured anything on this. Thank you!

Unfortunately not! I kind of gave up on this way of loading screens. Seeing the developer of the board also did not care to reply I suspected it just was not possible to do it this way or there is some kind of hardware limitation not allowing us to do it.

lumenlunae commented 10 months ago

I appreciate the response! A shame to hear, but gives me some calm after pulling my hair. Thank you 🙏