ESP32 Deep Sleep với Arduino IDE

Chế độ ngủ sâu trên ESP32

Trong bài viết này, chúng ta sẽ tìm hiểu chế độ ngủ sâu của ESP32 với Arduino IDE. Chúng ta sẽ tìm cách để cho ESP32 vào deep sleep và xem xét các cách khác nhau để đánh thức nó như:

  • Timer Wakeup
  • Touch Wakeup
  • External Wakeup
esp32-deep-sleep-arduino-ide ESP32 Deep Sleep với Arduino IDE

Giới thiệu chế độ ngủ sâu – Deep Sleep

ESP32 có thể chuyển đổi giữa các chế độ hoạt động khác nhau:

  • Chế độ hoạt động bình thường
  • Chế độ ngủ Modem
  • Chế độ ngủ nhẹ
  • Chế độ ngủ sâu
  • Chế độ ngủ đông

Bạn có thể so sánh năm chế độ khác nhau theo bảng dưới đây

POWER-MODES ESP32 Deep Sleep với Arduino IDE

Với mỗi chế độ hoạt động sẽ có những thành phần khác nhau bên trong ESP32 hoạt động và mức tiêu thụ điện năng khác nhau.

power-consumption-1 ESP32 Deep Sleep với Arduino IDE

Và dưới đây là bảng so sánh mức tiêu thụ điện năng của từng chế độ RF

table-10-active-mode ESP32 Deep Sleep với Arduino IDE

Tại sao chúng ta cần chế độ ngủ sâu?

Khi ESP32 của bạn chạy ở chế độ hoạt động bình thường với pin, năng lượng từ pin sẽ tiêu hao rất nhanh và nhanh chóng cạn kiệt năng lượng.

drain-batteries ESP32 Deep Sleep với Arduino IDE

Nếu bạn để ESP32 của mình ở chế độ ngủ sâu, nó sẽ giảm mức tiêu thụ năng lượng và pin của bạn sẽ được giữ lâu hơn.

Khi ESP32 của bạn ở chế độ ngủ sâu có nghĩa là nó sẽ cắt giảm các hoạt động tiêu thụ nhiều năng lượng so với khi nó hoạt động bình thường. Trong chế độ này, ESP32 hoạt động vừa đủ để đánh thức bộ xử lý khi có điều gì đó xảy ra.

Trong chế độ ngủ sâu, tất cả các hoạt động CPU và Wi-Fi đều không diễn ra. Tuy nhiên, bộ xử lý Ultra Low Power (ULP) vẫn có thể được cấp điện để có thể hoạt động.

Mặc dù ESP32 ở chế độ ngủ sâu, bộ nhớ RTC cũng vẫn được cấp nguồn, vì vậy chúng ta có thể viết chương trình cho bộ xử lý ULP và lưu trữ nó trong bộ nhớ RTC để truy cập các thiết bị ngoại vi, bộ hẹn giờ bên trong và cảm biến nội bộ.

Chế độ hoạt động này sẽ rất hữu ích nếu bạn cần đánh thức CPU chính bởi một sự kiện bên ngoài, bộ hẹn giờ hoặc cả hai, trong khi vẫn duy trì mức tiêu thụ năng lượng tối thiểu.

RTC_GPIO PIN

Trong khi ngủ sâu, một số chân ESP32 có thể được sử dụng bởi bộ xử lý ULP, các chân này gọi là RTC_GPIO và các chân cảm ứng.

Bạn có thể xác định vị trí các chân RTC_GPIO theo hình bên dưới

ESP32-DOIT-DEVKIT-V1-Board-Pinout-36-GPIOs-updated-2 ESP32 Deep Sleep với Arduino IDE

Các cách để đánh thức ESP32

Sau khi đưa ESP32 vào chế độ ngủ sâu, có một số phương pháp để có thể đánh thức nó lên:

  1. Bạn có thể sử dụng bộ hẹn giờ, đánh thức bằng thời gian được xác định trước;
  2. Bạn có thể sử dụng Touch trên RTC_GPIO
  3. Bạn có thể sử dụng External Wakeup
  4. Bạn có thể sử dụng lõi ULP đánh thức

Trước khi đặt ESP32 vào chế độ ngủ sâu

Trước khi bạn đặt ESP32 của bạn vào chế độ ngủ sâu, bạn cần phải nhớ rằng:

  1. Đầu tiên, bạn cần cấu hình các nguồn thức dậy. Điều này có nghĩa là cấu hình những gì sẽ đánh thức ESP32. Bạn có thể sử dụng một hoặc kết hợp nhiều hơn một nguồn thức dậy.
  2. Bạn có thể quyết định những gì thiết bị ngoại vi nào sẽ được tắt hoặc tiếp tục trong khi ngủ sâu.Tuy nhiên, theo mặc định, ESP32 tự động cung cấp năng lượng cho các thiết bị ngoại vi không cần thiết với nguồn thức dậy mà bạn xác định.
  3. Cuối cùng, khi bạn gọi câu lệnh ESP_DEEP_SLEEP_START (), ESP32 của bạn sẽ lập tức tiến vào chế độ ngủ sâu.

Hẹn giờ thức dậy

ESP32 có thể chuyển sang chế độ ngủ sâu, và sau đó thức dậy vào các khoảng thời gian được xác định trước. Tính năng này đặc biệt hữu ích nếu bạn đang chạy các dự án yêu cầu thời gian làm việc ngắn hoặc nhiệm vụ hàng ngày, trong khi vẫn duy trì mức tiêu thụ năng lượng thấp.

timer-wake-up ESP32 Deep Sleep với Arduino IDE

Bộ điều khiển RTC ESP32 có bộ đếm thời gian tích hợp mà bạn có thể sử dụng để đánh thức ESP32 sau một khoảng thời gian được xác định trước.

Bật hẹn giờ thức dậy

Việc cho phép ESP32 thức dậy sau một khoảng thời gian được xác định trước là rất đơn giản. Trong Arduino IDE, bạn chỉ cần chỉ định thời gian ngủ tính bằng micro giây trong chức năng sau:

ESP_SLEEP_ENABLE_TIMER_WAKEUP (Time_in_us)

Code mẫu

Hãy cùng xem cách thức hoạt động của nó bằng cách sử dụng một ví dụ từ thư viện. Mở Arduino IDE của bạn và trỏ đến  File > Examples > ESP32 > Deep Sleep và mở TimerWakeUp .

/*
Simple Deep Sleep with Timer Wake Up
=====================================
ESP32 offers a deep sleep mode for effective power
saving as power is an important factor for IoT
applications. In this mode CPUs, most of the RAM,
and all the digital peripherals which are clocked
from APB_CLK are powered off. The only parts of
the chip which can still be powered on are:
RTC controller, RTC peripherals ,and RTC memories

This code displays the most basic deep sleep with
a timer to wake it up and how to store data in
RTC memory to use it over reboots

This code is under Public Domain License.

Author:
Pranav Cherukupalli <[email protected]>
*/

#define uS_TO_S_FACTOR 1000000/* Conversion factor for micro seconds to seconds */
#define TIME_TO_SLEEP  5/* Time ESP32 will go to sleep (in seconds) */

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(){
  Serial.begin(115200);
  delay(1000); //Take some time to open up the Serial Monitor

  //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 every 5 seconds
  */
  esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
  Serial.println("Setup ESP32 to sleep for every " + String(TIME_TO_SLEEP) +
  " Seconds");

  /*
  Next we decide what all peripherals to shut down/keep on
  By default, ESP32 will automatically power down the peripherals
  not needed by the wakeup source, but if you want to be a poweruser
  this is for you. Read in detail at the API docs
  http://esp-idf.readthedocs.io/en/latest/api-reference/system/deep_sleep.html
  Left the line commented as an example of how to configure peripherals.
  The line below turns off all RTC peripherals in deep sleep.
  */
  //esp_deep_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_OFF);
  //Serial.println("Configured all RTC Peripherals to be powered down in sleep");

  /*
  Now that we have setup a wake cause and if needed setup the
  peripherals state in deep sleep, we can now start going to
  deep sleep.
  In the case that no wake up sources were provided but deep
  sleep was started, it will sleep forever unless hardware
  reset occurs.
  */
  Serial.println("Going to sleep now");
  delay(1000);
  Serial.flush(); 
  esp_deep_sleep_start();
  Serial.println("This will never be printed");
}

void loop(){
  //This is not going to be called
}

Kiểm tra Timer Wake Up

Bạn mở Serial Monitor với mức baudrate 115200.

serial-monitor-1 ESP32 Deep Sleep với Arduino IDE

Mỗi 5 giây, ESP sẽ tỉnh dậy, in một thông điệp trên cổng nối tiếp và sau đó lại đi vào chế độ ngủ sâu.

Mỗi khi ESP tỉnh dậy, biến bootCount sẽ tăng lên. Nó cũng in ra lý do tỉnh dậy như được thể hiện trong hình dưới đây.

timer-wake-up-serial-monitor ESP32 Deep Sleep với Arduino IDE

Tuy nhiên, lưu ý rằng nếu bạn nhấn nút EN trên bo mạch ESP32, nó sẽ đặt lại boot count về 1.

Bạn có thể sửa đổi ví dụ đã cung cấp, và thay vì in một thông điệp, bạn có thể làm cho ESP của bạn thực hiện bất kỳ công việc nào khác. Tính năng đánh thức bằng hẹn giờ rất hữu ích để thực hiện các công việc định kỳ với ESP32, như các công việc hàng ngày, mà không tiêu tốn nhiều năng lượng.

Wake Up với cảm ứng chạm

Bạn có thể đánh thức ESP32 từ chế độ ngủ sâu bằng cách sử dụng các chân cảm ứng. Phần này sẽ hướng dẫn cách thực hiện điều đó bằng việc sử dụng Arduino IDE.

touch-wake-up ESP32 Deep Sleep với Arduino IDE

Enable Touch Wake Up

Kích hoạt việc đánh thức ESP32 bằng cách sử dụng một chân cảm ứng. Trong Arduino IDE, bạn cần sử dụng hàm sau:

esp_sleep_enable_touchpad_wakeup()

Code

Mở Arduino IDE và chọn File Examples ESP32 Deep Sleep, sau đó mở TouchWakeUp.

/*
  Deep Sleep with Touch Wake Up
  This code displays how to use deep sleep with a touch as a wake up source and how to store data in RTC memory to use it over reboots
  ESP32 can have multiple touch pads enabled as wakeup source
  ESP32-S2 and ESP32-S3 supports only 1 touch pad as wakeup source enabled
  This code is under Public Domain License. Author: Pranav Cherukupalli <[email protected]>
*/

#if CONFIG_IDF_TARGET_ESP32
  #define THRESHOLD   40/* Greater the value, more the sensitivity */
#else //ESP32-S2 and ESP32-S3 + default for other chips (to be adjusted) */
  #define THRESHOLD   5000/* Lower the value, more the sensitivity */
#endif

RTC_DATA_ATTR int bootCount = 0;
touch_pad_t touchPin;
/*
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;
  }
}

/*
Method to print the touchpad by which ESP32
has been awaken from sleep
*/
void print_wakeup_touchpad(){
  touchPin = esp_sleep_get_touchpad_wakeup_status();

  #if CONFIG_IDF_TARGET_ESP32
    switch(touchPin)
    {
      case 0  : Serial.println("Touch detected on GPIO 4"); break;
      case 1  : Serial.println("Touch detected on GPIO 0"); break;
      case 2  : Serial.println("Touch detected on GPIO 2"); break;
      case 3  : Serial.println("Touch detected on GPIO 15"); break;
      case 4  : Serial.println("Touch detected on GPIO 13"); break;
      case 5  : Serial.println("Touch detected on GPIO 12"); break;
      case 6  : Serial.println("Touch detected on GPIO 14"); break;
      case 7  : Serial.println("Touch detected on GPIO 27"); break;
      case 8  : Serial.println("Touch detected on GPIO 33"); break;
      case 9  : Serial.println("Touch detected on GPIO 32"); break;
      default : Serial.println("Wakeup not by touchpad"); break;
    }
  #else
    if(touchPin < TOUCH_PAD_MAX)
    {
      Serial.printf("Touch detected on GPIO %d\n", touchPin); 
    }
    else
    {
      Serial.println("Wakeup not by touchpad");
    }
  #endif
}

void setup(){
  Serial.begin(115200);
  delay(1000); //Take some time to open up the Serial Monitor

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

  //Print the wakeup reason for ESP32 and touchpad too
  print_wakeup_reason();
  print_wakeup_touchpad();

  #if CONFIG_IDF_TARGET_ESP32 
  //Setup sleep wakeup on Touch Pad 3 + 7 (GPIO15 + GPIO 27) 
  touchSleepWakeUpEnable(T3,THRESHOLD);
  touchSleepWakeUpEnable(T7,THRESHOLD);
  
  #else //ESP32-S2 + ESP32-S3
  //Setup sleep wakeup on Touch Pad 3 (GPIO3) 
  touchSleepWakeUpEnable(T3,THRESHOLD);

  #endif

  //Go to sleep now
  Serial.println("Going to sleep now");
  esp_deep_sleep_start();
  Serial.println("This will never be printed");
}

void loop(){
  //This will never be reached
}

Sơ đồ mạch điện
Zero_Touch_Wake_Up_bb ESP32 Deep Sleep với Arduino IDE

Kiểm tra hoạt động

Mở Serial Monitor với mức baudrate 115200.

serial-monitor-2 ESP32 Deep Sleep với Arduino IDE

Khi ESP32 chuyển sang chế độ ngủ sâu.

Bạn có thể đánh thức nó bằng cách chạm vào dây kết nối với chân cảm ứng 3.

touch-pin ESP32 Deep Sleep với Arduino IDE

Khi bạn chạm vào chân cảm ứng, ESP32 sẽ hiển thị trên Màn hình Nối tiếp: số lần khởi động, nguyên nhân đánh thức, và chân GPIO mà cảm ứng đã phát hiện.

touch-wake-up-serial-monitor ESP32 Deep Sleep với Arduino IDE

External Wake Up

Ngoài việc sử dụng hẹn giờ và các chân cảm ứng, chúng ta cũng có thể đánh thức ESP32 từ chế độ ngủ sâu bằng cách thay đổi giá trị của một tín hiệu trên một chân, như việc nhấn một nút. Điều này được gọi là đánh thức từ bên ngoài. Bạn có hai khả năng đánh thức từ bên ngoài: ext0 và ext1.

external-wake-up ESP32 Deep Sleep với Arduino IDE

External Wake Up (ext0)

Nguồn đánh thức này cho phép bạn sử dụng một chân để đánh thức ESP32.

Tùy chọn nguồn đánh thức ext0 sử dụng các GPIO RTC để đánh thức. Do đó, các bộ phận RTC sẽ được duy trì trong suốt thời gian ngủ sâu nếu nguồn đánh thức này được yêu cầu.

Để sử dụng nguồn đánh thức này, bạn sử dụng hàm sau:

esp_sleep_enable_ext0_wakeup(GPIO_NUM_X, level)

Hàm này chấp nhận như đối số đầu tiên là chân bạn muốn sử dụng, theo định dạng GPIO_NUM_X, trong đó X đại diện cho số GPIO của chân đó.

Đối số thứ hai, level, có thể là 1 hoặc 0. Điều này đại diện cho trạng thái của GPIO sẽ kích hoạt đánh thức.

Lưu ý: với nguồn đánh thức này, bạn chỉ có thể sử dụng các chân là RTC GPIOs.

External Wake Up (ext1)

Nguồn đánh thức này cho phép bạn sử dụng nhiều RTC GPIOs khác nhau. Bạn có thể sử dụng hai hàm logic khác nhau:

  • Đánh thức ESP32 nếu bất kỳ chân nào bạn đã chọn là cao;
  • Đánh thức ESP32 nếu tất cả các chân bạn đã chọn là thấp.

Nguồn đánh thức này được triển khai bởi bộ điều khiển RTC. Do đó, các bộ phận RTC và bộ nhớ RTC có thể được tắt nguồn trong chế độ này.

Để sử dụng nguồn đánh thức này, bạn sử dụng hàm sau:

esp_sleep_enable_ext1_wakeup(bitmask, mode)

Hàm này chấp nhận hai đối số:

Một bitmask của các số GPIO sẽ gây ra đánh thức;

Chế độ: logic để đánh thức ESP32. Nó có thể là:

  • ESP_EXT1_WAKEUP_ALL_LOW: đánh thức khi tất cả các GPIO đều thấp;
  • ESP_EXT1_WAKEUP_ANY_HIGH: đánh thức nếu bất kỳ GPIO nào đều cao.

Lưu ý: với nguồn đánh thức này, bạn chỉ có thể sử dụng các chân là RTC GPIOs.

Code

Mở Arduino IDE, chọn File > Examples > ESP32 > Deep Sleep > ExternalWakeUp:

/*
Deep Sleep with External Wake Up
=====================================
This code displays how to use deep sleep with
an external trigger as a wake up source and how
to store data in RTC memory to use it over reboots

This code is under Public Domain License.

Hardware Connections
======================
Push Button to GPIO 33 pulled down with a 10K Ohm
resistor

NOTE:
======
Only RTC IO can be used as a source for external wake
source. They are pins: 0,2,4,12-15,25-27,32-39.

Author:
Pranav Cherukupalli <[email protected]>
*/

#define BUTTON_PIN_BITMASK 0x200000000// 2^33 in hex

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(){
  Serial.begin(115200);
  delay(1000); //Take some time to open up the Serial Monitor

  //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_33,1); //1 = High, 0 = Low

  //If you were to use ext1, you would use it like
  //esp_sleep_enable_ext1_wakeup(BUTTON_PIN_BITMASK,ESP_EXT1_WAKEUP_ANY_HIGH);

  //Go to sleep now
  Serial.println("Going to sleep now");
  delay(1000);
  esp_deep_sleep_start();
  Serial.println("This will never be printed");
}

void loop(){
  //This is not going to be called
}

external_wake_up_button_bb ESP32 Deep Sleep với Arduino IDE

Kiểm tra hoạt động

Sau khi upload code, bạn mở Serial Monitor với mức baudrate 115200.

serial-monitor-3 ESP32 Deep Sleep với Arduino IDE

nhấn nút nhấn để đánh thức ESP32.

external_wakeup_button ESP32 Deep Sleep với Arduino IDE

Số lần boot sẽ tăng sau mỗi lần nhấn

external-wake-up-serial-monitor_f ESP32 Deep Sleep với Arduino IDE

Sử dụng phương pháp này rất hữu ích để đánh thức ESP32 bằng cách sử dụng một nút nhấn, ví dụ, để thực hiện một nhiệm vụ cụ thể. Tuy nhiên, với phương pháp này, bạn chỉ có thể sử dụng một GPIO làm nguồn đánh thức.

Nếu bạn muốn có nhiều nút nhấn khác nhau, tất cả đều đánh thức ESP, nhưng thực hiện các nhiệm vụ khác nhau, bạn cần sử dụng phương pháp ext1.

ext1

Phương pháp ext1 cho phép bạn đánh thức ESP bằng cách sử dụng các nút nhấn khác nhau và thực hiện các nhiệm vụ khác nhau tùy thuộc vào nút bạn nhấn.

Thay vì sử dụng hàm esp_sleep_enable_ext0_wakeup(), bạn sử dụng hàm esp_sleep_enable_ext1_wakeup(). Trong mã, hàm đó được chú thích:

//If you were to use ext1, you would use it like
//esp_sleep_enable_ext1_wakeup(BUTTON_PIN_BITMASK,ESP_EXT1_WAKEUP_ANY_HIGH);

Uncomment hàm này, bạn sẽ có được:

esp_sleep_enable_ext1_wakeup(BUTTON_PIN_BITMASK,ESP_EXT1_WAKEUP_ANY_HIGH);

Đối số đầu tiên của hàm là một bitmask của các GPIO mà bạn sẽ sử dụng làm nguồn đánh thức, và đối số thứ hai xác định logic để đánh thức ESP32.

Trong ví dụ này, chúng ta đang sử dụng biến BUTTON_PIN_BITMASK, đã được định nghĩa ở đầu mã nguồn:

#define BUTTON_PIN_BITMASK 0x200000000 // 2^33 in hex

Code đang xác định một chân làm nguồn đánh thức, GPIO 33. Bạn cần sửa đổi bitmask để cấu hình thêm GPIOs khác làm nguồn đánh thức.

GPIOs Bitmask

Để có được bitmask của các GPIO, bạn có thể tuân theo các bước sau:

  1. Tính toán 2 mũ GPIO_NUMBER. Lưu kết quả dưới dạng số thập phân.
  2. Điều hướng đến một trang chuyển đổi từ thập phân sang thập lục phân, chẳng hạn như rapidtables.com/convert/number/decimal-to-hex.html, và chuyển đổi số thập phân sang số thập lục phân.
  3. Thay thế số thập lục phân bạn nhận được vào biến BUTTON_PIN_BITMASK.

Mask for a single GPIO

Để bạn hiểu cách lấy bitmask của các GPIO, chúng ta sẽ đi qua một ví dụ. Trong mã từ thư viện, nút được kết nối với GPIO 33. Để lấy mask cho GPIO 33:

  1. Tính 2^33. Bạn sẽ nhận được 8589934592;
  2. Chuyển đổi số đó (8589934592) sang hệ thập lục phân. Bạn có thể sử dụng trang chuyển đổi sau:
decimal_to_hex ESP32 Deep Sleep với Arduino IDE

3. Sao chép số hệ thập lục phân vào biến BUTTON_PIN_BITMASK, và bạn sẽ nhận được:

#define BUTTON_PIN_BITMASK 0x200000000 // 2^33 in hex

Mask cho một số GPIOs

Nếu bạn muốn sử dụng GPIO 2 và GPIO 15 làm nguồn đánh thức, bạn nên thực hiện như sau:

  1. Tính 2^2 + 2^15. Bạn sẽ nhận được 32772
  2. Chuyển đổi số đó sang hệ thập lục phân. Bạn sẽ nhận được: 8004

Thay thế số đó trong BUTTON_PIN_BITMASK như sau:

#define BUTTON_PIN_BITMASK 0x8004

Xác định GPIO để sử dụng làm nguồn đánh thức ESP32

Khi bạn sử dụng nhiều chân để đánh thức ESP32, việc biết chính xác chân nào đã gây ra sự đánh thức là rất hữu ích. Để làm điều đó, bạn có thể sử dụng hàm sau:

esp_sleep_get_ext1_wakeup_status()

Hàm này trả về một số cơ số 2, với số GPIO làm số mũ: 2^(GPIO). Vì vậy, để lấy GPIO ở dạng thập phân, bạn cần thực hiện phép tính sau:

GPIO = log(RETURNED_VALUE)/log(2)

External Wake Up – Nhiều GPIOs

Bây giờ, bạn nên có thể đánh thức ESP32 bằng cách sử dụng các nút nhấn khác nhau và xác định chính xác nút nào đã gây ra sự đánh thức. Trong ví dụ này, chúng ta sẽ sử dụng GPIO 2 và GPIO 15 làm nguồn đánh thức.

Sơ đồ mạch điện

Kết nối hai nút nhấn vào ESP32 của bạn. Trong ví dụ này, chúng ta sẽ sử dụng GPIO 2 và GPIO 15, nhưng bạn có thể kết nối nút nhấn của mình vào bất kỳ RTC GPIO nào và sửa lại code.

external_wake_up_2buttons_bb ESP32 Deep Sleep với Arduino IDE

Code

You need to make some modifications to the example code we’ve used before:

  • create a bitmask to use GPIO 15 and GPIO 2. We’ve shown you how to do this before;
  • enable ext1 as a wake up source;
  • use the esp_sleep_get_ext1_wakeup_status() function to get the GPIO that triggered wake up.

The next sketch has all those changes implemented.

/*
Deep Sleep with External Wake Up
=====================================
This code displays how to use deep sleep with
an external trigger as a wake up source and how
to store data in RTC memory to use it over reboots

This code is under Public Domain License.

Hardware Connections
======================
Push Button to GPIO 33 pulled down with a 10K Ohm
resistor

NOTE:
======
Only RTC IO can be used as a source for external wake
source. They are pins: 0,2,4,12-15,25-27,32-39.

Author:
Pranav Cherukupalli <[email protected]>
*/

#define BUTTON_PIN_BITMASK 0x8004// GPIOs 2 and 15

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;
  }
}

/*
Method to print the GPIO that triggered the wakeup
*/
void print_GPIO_wake_up(){
  uint64_t GPIO_reason = esp_sleep_get_ext1_wakeup_status();
  Serial.print("GPIO that triggered the wake up: GPIO ");
  Serial.println((log(GPIO_reason))/log(2), 0);
}
  
void setup(){
  Serial.begin(115200);
  delay(1000); //Take some time to open up the Serial Monitor

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

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

  //Print the GPIO used to wake up
  print_GPIO_wake_up();

  /*
  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_deep_sleep_enable_ext0_wakeup(GPIO_NUM_15,1); //1 = High, 0 = Low

  //If you were to use ext1, you would use it like
  esp_sleep_enable_ext1_wakeup(BUTTON_PIN_BITMASK,ESP_EXT1_WAKEUP_ANY_HIGH);

  //Go to sleep now
  Serial.println("Going to sleep now");
  delay(1000);
  esp_deep_sleep_start();
  Serial.println("This will never be printed");
}

void loop(){
  //This is not going to be called
}

external-wake-up-serial-monitor_2 ESP32 Deep Sleep với Arduino IDE

Kết luận

Trong bài viết này, chúng ta đã tìm hiểu cách để đặt ESP32 vào chế độ ngủ sâu và đánh thức bằng nhiều nguồn khác nhau:

Timer Wake Up

  • Để kích hoạt đánh thức bằng hẹn giờ, bạn sử dụng hàm esp_sleep_enable_timer_wakeup(time_in_us);
  • Sử dụng hàm esp_deep_sleep_start() để bắt đầu chế độ ngủ sâu.

Touch Wake Up

  • Để sử dụng các chân cảm ứng làm nguồn đánh thức, trước hết, bạn cần gắn các ngắt vào các chân cảm ứng bằng cách sử dụng: touchAttachInterrupt(ChânCảmỨng, callback, Ngưỡng)
  • Sau đó, bạn kích hoạt các chân cảm ứng làm nguồn đánh thức bằng cách sử dụng: esp_sleep_enable_touchpad_wakeup()
  • Cuối cùng, bạn sử dụng hàm esp_deep_sleep_start() để đưa ESP32 vào chế độ ngủ sâu.

External Wake Up

  • Bạn chỉ có thể sử dụng các RTC GPIO làm nguồn đánh thức bên ngoài;
  • Bạn có thể sử dụng hai phương pháp khác nhau: ext0 và ext1;
  • ext0 cho phép bạn đánh thức ESP32 bằng cách sử dụng một chân GPIO duy nhất;
  • ext1 cho phép bạn đánh thức ESP32 bằng cách sử dụng nhiều chân GPIO.

Nguồn:  Tại đây