T-vK / ESP32-BLE-Keyboard

Bluetooth LE Keyboard library for the ESP32 (Arduino IDE compatible)
2.44k stars 408 forks source link

Question: battery life improvement/ sleep mode #43

Open nikolayrantsev opened 4 years ago

nikolayrantsev commented 4 years ago

Hi everyone, Did anyone try to improve battery life using the library? I've connected 2000 mAh rechargeable battery and left the module simply paired with my computer. It took approx 15h to consume all the capacity. I've seen several deep sleep examples but were not able to combine it with the library? Appreciate any feedback, thank you!

T-vK commented 4 years ago

The ESP32 is very power hungry, even if just using BLE. Automatically putting it in deep sleep when no key was pressed for a while and then waking it up again using a gpio pin could work though. But if you don't share your code it's hard to say what you may have done wrong.

nikolayrantsev commented 4 years ago

It wouldn't mind -please take a look at this sample. It works correctly with your library (thanks again for the effort and sharing this very-very useful thing). But when I added elements of "deep sleep"- marked as "//code block from the deep sleep sample:" - module can't even be found by BT. I'm a beginner, so, possibly did something incorrectly with the implementation. I'm trying to increase battery life and turn on the module on each click of the button functioning as Page Down, and go to sleep after some time of inactivity in order to reduce power consumption.

Thank you!

/*
Deep Sleep with External Wake Up sample source here:
https://github.com/espressif/arduino-esp32/blob/master/libraries/ESP32/examples/DeepSleep/ExternalWakeUp/ExternalWakeUp.ino
*/

#include <BleKeyboard.h> // https://github.com/T-vK/ESP32-BLE-Keyboard

//code block from the deep sleep sample:
#define BUTTON_PIN_BITMASK 0x100000000 // 2^32 in hex 

BleKeyboard bleKeyboard("Name");
int PushButtonDown = 32; 

  //code blocks pasted from the deep sleep sample:
RTC_DATA_ATTR int bootCount = 0;

/*
Method to print the reason by which ESP32
has been awaken from sleep
*/

void print_wakeup_reason(){
  esp_sleep_wakeup_cause_t wakeup_reason;

  wakeup_reason = esp_sleep_get_wakeup_cause();

  switch(wakeup_reason)
  {
    case ESP_SLEEP_WAKEUP_EXT0 : Serial.println("Wakeup caused by external signal using RTC_IO"); break;
    case ESP_SLEEP_WAKEUP_EXT1 : Serial.println("Wakeup caused by external signal using RTC_CNTL"); break;
    case ESP_SLEEP_WAKEUP_TIMER : Serial.println("Wakeup caused by timer"); break;
    case ESP_SLEEP_WAKEUP_TOUCHPAD : Serial.println("Wakeup caused by touchpad"); break;
    case ESP_SLEEP_WAKEUP_ULP : Serial.println("Wakeup caused by ULP program"); break;
    default : Serial.printf("Wakeup was not caused by deep sleep: %d\n",wakeup_reason); break;
  }
}

void setup(){

  pinMode(PushButtonDown, INPUT); // acts as PgDown keyboard button
  pinMode(LED_BUILTIN, OUTPUT);   // defines built led
  Serial.begin(115200);

  bleKeyboard.begin();

  //code block pasted from the deep sleep sample:

  //Increment boot number and print it every reboot
  ++bootCount;
  Serial.println("Boot number: " + String(bootCount));

  //Print the wakeup reason for ESP32
  print_wakeup_reason();

  /*
  First we configure the wake up source
  We set our ESP32 to wake up for an external trigger.
  There are two types for ESP32, ext0 and ext1 .
  ext0 uses RTC_IO to wakeup thus requires RTC peripherals
  to be on while ext1 uses RTC Controller so doesnt need
  peripherals to be powered on.
  Note that using internal pullups/pulldowns also requires
  RTC peripherals to be turned on.
  */
  esp_sleep_enable_ext0_wakeup(GPIO_NUM_32,1); //1 = High, 0 = Low
 delay(10000);

}

void loop(){

  // digitalRead function stores the PushButtonDown/PushButtonUp  state
  // in variable Push_button_Down_state
  int Push_button_Down_state = digitalRead(PushButtonDown);

  // if condition checks if push button is pressed
  // if pressed LED_BUILTIN will turn on otherwise remain off
  if (Push_button_Down_state == HIGH)
  {
    digitalWrite(LED_BUILTIN, HIGH);  //led turns on
    bleKeyboard.write(KEY_PAGE_DOWN); //the core command - it actually perform PgDown action
    delay(200);                       // very close to the real keyboard PgDown button behavior. Value 100 is too small
  }
  else
  {
    digitalWrite(LED_BUILTIN, LOW); //turning led off - default state
  }

  //code block pasted from the deep sleep sample:

  //Go to sleep now
  Serial.println("Going to sleep now");

  delay(60000);

  esp_deep_sleep_start();
  Serial.println("This will never be printed");

}
T-vK commented 4 years ago

Light sleep appears to be possible according to this guy: https://www.esp32.com/viewtopic.php?t=15492 Deep sleep however seem to require more hoops to jump through. Maybe this would do the job: https://github.com/nkolban/esp32-snippets/issues/354#issuecomment-356879507

These sdk functions are wrapped in here: https://github.com/nkolban/esp32-snippets/blob/810aeb810a15ff6cf8742080ea5a413447cd0b92/cpp_utils/BLEDevice.cpp#L616

So maybe before entering sleep, you should just call the static deinit method.

#include <BLEDevice.h>
// maybe like this
BLEDevice::deinit(true);
// or maybe like this
BLEDevice::deinit(false);
pepsi-zero commented 4 years ago

Hi everyone, Did anyone try to improve battery life using the library? I've connected 2000 mAh rechargeable battery and left the module simply paired with my computer. It took approx 15h to consume all the capacity. I've seen several deep sleep examples but were not able to combine it with the library? Appreciate any feedback, thank you!

Strange. For me it takes 5 days with about 700 clicks before it turns off. That with a 2200mAh battery. The only modification i’ve done is lower the cpu speed to 80Mhz

vogler commented 2 years ago

I guess many wonder if an ESP32-based keyboard on battery is a viable option. Of course there's a lot of variation between boards, but maybe add some best case estimate to the readme? https://electronics.stackexchange.com/questions/615765/why-is-esp32-ble-so-power-hungry Assuming 100mA, a 2200mA cell would give 22h of typing. I have some boards that already consume 10mA in deep sleep which would be 9 days, some that are around 1mA which would be 3 months, a bare ESP32 should be only at 10µA which is around 4x Li-ion self-discharge current. How long does it need to wake up? I guess it only makes sense to put it into deep sleep after a couple of seconds.

pepsi-zero commented 2 years ago

I guess many wonder if an ESP32-based keyboard on battery is a viable option. Of course there's a lot of variation between boards, but maybe add some best case estimate to the readme? https://electronics.stackexchange.com/questions/615765/why-is-esp32-ble-so-power-hungry Assuming 100mA, a 2200mA cell would give 22h of typing. I have some boards that already consume 10mA in deep sleep which would be 9 days, some that are around 1mA which would be 3 months, a bare ESP32 should be only at 10µA which is around 4x Li-ion self-discharge current. How long does it need to wake up? I guess it only makes sense to put it into deep sleep after a couple of seconds.

You can extend the battery live by reducing the clock speed. I have a few ESP32 that are used by people with a disability. Those boards stay on. And never goto sleep. They run from 2200mAh powerbanks. So not power efficient by converting from 3v7 to 5v and in the esp32 boards I use change it back from 5v to 3v3. But the powerbanks are widely availble and cheap in some Dutch stores. For only a few bucks. The powerbanks do get replaced every 3 days. And still have 40% batterylife left.

I used the code from the following website for 2 years. Keep in mind that if the powerbank turn itself off after 30 sec. The powerconsumption is to low. And increasing the clockspeed will precent that. And do not go below 80MHz otherwise BT (but also wifi) is not stable anymore.

https://www.savjee.be/2019/12/esp32-tips-to-increase-battery-life/#tip-4-reduce-the-clock-speed