Chế độ Deep Sleep trên ESP32 và Wake Up Sources

Bài viết hôm nay sẽ hướng dẫn đầy đủ cho chế độ Deep Sleep ESP32 trên board Node Wifi32 (Bạn sẽ lập trình ESP32 bằng Arduino IDE) Chúng tôi sẽ hướng dẫn bạn cách đặt ESP32 vào chế độ deep sleep và xem xét các chế độ khác nhau để đánh thức nó: timer wake up (hẹn giờ đánh thức), touch wake up (đánh thức bằng chạm) và external wake up (đánh thức bên ngoài). Hướng dẫn này cung cấp các ví dụ thực tế, sơ đồ và giải thích code.

Lập trình Esp32 vào chế độ deep sleep

GIỚI THIỆU CHẾ ĐỘ DEEP SLEEP

NodeWifi32 có thể chuyển đổi giữa các chế độ năng lượng khác nhau:

  • Active mode (Chế độ hoạt động)
  • Modem Sleep mode (Chế độ ngủ của modem)
  • Light Sleep mode (Chế độ ngủ nhẹ)
  • Deep Sleep mode (Chế độ ngủ sâu)
  • Hibernation mode (Chế độ ngủ đông)

Bạn có thể so sánh 5 chế độ khác nhau trên bảng bên dưới từ biểu dữ liệu ESP32 Espressif.

tiêu thụ điện năng esp32

Các ESP32 Espressif datasheet cũng cung cấp một bảng so sánh mức tiêu thụ năng lượng của chế độ năng lượng khác nhau.

esp32 chế độ ngủ khác nhau

So sánh mức tiêu thụ điện năng ở chế độ hoạt động như dưới Table 10:

tiêu thụ điện năng esp32 ở chế độ hoạt động

TẠI SAO CÓ CHẾ ĐỘ DEEP SLEEP?

Để ESP32 của bạn chạy ở chế độ hoạt động với pin, đó không phải là chế độ lý tưởng nhất, vì năng lượng từ pin sẽ hết rất nhanh.

Chế độ deep sleep

Nếu bạn đặt ESP32 của mình ở chế độ deep sleep, nó sẽ giảm mức tiêu thụ điện năng. Từ đó, pin của bạn sẽ hoạt động lâu hơn. Đặt ESP32 của bạn ở chế độ ngủ sâu có nghĩa là board mạch sẽ tự cắt giảm các hoạt động tiêu tốn nhiều điện năng, chỉ để lại hoạt động là đánh thức bộ xử lý khi có điều gì đó xảy ra.

Lưu ý: Ở chế độ ngủ sâu, các hoạt động của CPU hoặc Wi-Fi không diễn ra, nhưng vẫn có thể bật nguồn cho bộ đồng xử lý Ultra Low Power (ULP).

Trong khi ESP32 ở chế độ deep sleep, bộ nhớ RTC cũng vẫn được bật. Vì vậy, chúng tôi có thể viết chương trình cho bộ đồng 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ờ nội bộ và cảm biến bên trong.

Chế độ hoạt động này rất hữu ích nếu bạn cần đánh thức CPU chính bằng 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ụ điện năng tối thiểu.

CÁC CHÂN RTC_GPIO

Trong chế độ Deep Sleep, một số chân ESP32 có thể được sử dụng bởi bộ đồng xử lý ULP, cụ thể là chân RTC_GPIO và Chân cảm ứng. Biểu dữ liệu ESP32 cung cấp một bảng xác định các chân RTC_GPIO. 

Bạn có thể sử dụng bảng đó làm tài liệu tham khảo hoặc xem sơ đồ chân sau để xác định vị trí các chân RTC_GPIO khác nhau. 

Node Wifi32 - ESP32 DEV Module

WAKE UP SOURCES

Sau khi đặt NodeWifi32 vào chế độ ngủ sâu, có một số cách để đánh thức nó:

  1. Bạn có thể sử dụng bộ hẹn giờ(timer), đánh thức NodeWifi32 của mình bằng các khoảng thời gian được xác định trước;
  2. Bạn có thể sử dụng các chân cảm ứng(touch pins);
  3. Bạn có thể sử dụng hai khả năng đánh thức bên ngoài(external): bạn có thể sử dụng đánh thức bên ngoài hoặc một số lần đánh thức bên ngoài khác nhau;
  4. Bạn có thể sử dụng bộ đồng xử lý ULP để đánh thức – điều này sẽ không được đề cập trong hướng dẫn này.

VIẾT SKETCH KÍCH HOẠT CHẾ ĐỘ DEEP SLEEP

Để viết một bản sketch để đưa Node Wifi32 của bạn vào chế độ ngủ sâu, rồi đánh thức nó, bạn cần lưu ý rằng:

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

HẸN GIỜ ĐÁNH THỨC

NodeWifi32 có thể chuyển sang chế độ ngủ sâu và sau đó thức dậy vào những khoảng thời gian 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 về thời gian hoặc các công việc hàng ngày, trong khi vẫn duy trì mức tiêu thụ điện năng thấp.

mức tiêu thụ điện năng thấp

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

BẬT HẸN GIỜ WAKE UP

Việc kích hoạt Node Wifi32 thức dậy sau một khoảng thời gian 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 hàm sau:

esp_sleep_enable_timer_wakeup(time_in_us)

CODE

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

#define uS_TO_S_FACTOR 1000000  /* Conversion factor for micro seconds to seconds */
#define TIME_TO_SLEEP  5        /* Time NodeWifi32 will go to sleep (in seconds) */
RTC_DATA_ATTR int bootCount = 0;
/*
Method to print the reason by which NodeWifi32
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(116200);
  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 NodeWifi32
  print_wakeup_reason();
  /*
  First we configure the wake up source
  We set our NodeWifi32 to wake up every 5 seconds
  */
  esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
  Serial.println("Setup NodeWifi32 to sleep for every" + String(TIME_TO_SLEEP) +
  " Seconds");
  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
}

Chúng ta hãy xem mã này. Nhận xét đầu tiên mô tả những gì được tắt trong khi ngủ sâu với tính năng hẹn giờ đánh thức.

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

Khi bạn sử dụng bộ hẹn giờ đánh thức, các bộ phận sẽ được bật nguồn là bộ điều khiển RTC, thiết bị ngoại vi RTC và bộ nhớ RTC.

XÁC ĐỊNH THỜI GIAN SLEEP

Hai dòng code đầu tiên này xác định khoảng thời gian NodeWifi32 sẽ ngủ.

#define uS_TO_S_FACTOR 1000000 /* Conversion factor for micro seconds to seconds */ 

#define TIME_TO_SLEEP 5 /* Time Node Wifi32 will go to sleep (in seconds) */

Ví dụ này sử dụng hệ số chuyển đổi từ micro giây sang giây để bạn có thể đặt thời gian ngủ trong TIME_TO_SLEEP biến tính bằng giây. Trong trường hợp này, ví dụ sẽ đặt Node Wifi32 vào chế độ ngủ sâu trong 5 giây.

LƯU DỮ LIỆU TRÊN RTC

Với Node Wifi32, bạn có thể lưu dữ liệu trên bộ nhớ RTC. Node Wifi32 có 8kB SRAM trên phần RTC, được gọi là bộ nhớ nhanh RTC. Dữ liệu được lưu ở đây không bị xóa khi ngủ sâu. Tuy nhiên, nó sẽ bị xóa khi bạn nhấn nút đặt lại (nút có nhãn EN trên bo mạch Node Wifi32).

Để lưu dữ liệu trên bộ nhớ RTC, bạn chỉ cần thêm RTC_DATA_ATTR trước một định nghĩa biến. Ví dụ lưu bootCount biến trên bộ nhớ RTC. Biến này sẽ đếm số lần Node Wifi32 đã thức dậy sau giấc ngủ sâu.

RTC_DATA_ATTR int bootCount = 0;

LÝ DO THỨC DẬY

Sau đó, mã xác định print_wakeup_reason () chức năng in ra lý do mà Node Wifi32 đã được đánh thức từ chế độ ngủ.

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

SETUP()

Bên trong setup() là nơi bạn nên đặt mã của mình. Trong giấc ngủ sâu, bản phác thảo không bao giờ đạt đến loop() tuyên bố. Vì vậy, bạn cần viết tất cả bản phác thảo trong setup().

Ví dụ này bắt đầu bằng cách khởi tạo giao tiếp nối tiếp với tốc độ truyền là 116200.

Serial.begin(116200);

Sau đó, bootCount biến được tăng lên một trong mỗi lần khởi động lại và số đó được in trong màn hình nối tiếp.

++bootCount;

Serial.println(“Boot number: ” + String(bootCount));

Sau đó,  print_wakeup_reason () làm mã lệnh để bạn có thể gọi bất kỳ hàm nào bạn muốn để thực hiện một tác vụ mình cần. Ví dụ: bạn có thể đánh thức NodeWifi32 của mình mỗi ngày một lần để đọc giá trị từ cảm biến.

Tiếp theo, đánh thức mã nguồn bằng cách sử dụng hàm sau:

esp_sleep_enable_timer_wakeup(time_in_us)

Hàm này chấp nhận làm đối số thời gian ngủ tính bằng micro giây như chúng ta đã thấy trước đây.

Trong trường hợp của chúng tôi, chúng tôi sử dụng hàm sau:

esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);

Sau đó, sau khi tất cả các tác vụ được thực hiện, đặc biệt sẽ chuyển sang chế độ ngủ bằng cách gọi hàm sau:

esp_deep_sleep_start()

LOOP ()

Các loop() phần trống, vì Node Wifi32 sẽ chuyển sang chế độ ngủ trước khi đến phần này của code. Vì vậy, bạn cần viết tất cả bản phác thảo của mình trong setup().

Upload bản phác thảo ví dụ lên Node Wifi32 của bạn. Đảm bảo rằng bạn đã chọn đúng board và cổng COM.

KIỂM TRA BỘ HẸN GIỜ WAKE UP

Mở Serial Monitor với tốc độ truyền là 116200.

Kiểm tra bộ hẹn giờ Wake up

Cứ sau 5 giây, Node Wifi32 thức dậy, in một thông báo trên màn hình nối tiếp và lại đi vào giấc ngủ sâu.

Mỗi khi Node Wifi32 đánh thức bootCount biến tăng. Nó cũng in lý do đánh thức như trong hình bên dưới.

Đánh thức bootCount

Tuy nhiên, hãy lưu ý rằng nếu bạn nhấn nút EN trên board Node Wifi32, nó sẽ đặt lại số lần khởi động thành 1 lần nữa.

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

TOUCH WAKE UP

Bạn có thể đánh thức Node Wifi32 khỏi chế độ Deep Sleep bằng các chân cảm ứng. Phần này cho thấy cách thực hiện điều đó bằng Arduino IDE.

https://i1.wp.com/randomnerdtutorials.com/wp-content/uploads/2019/02/touch-wake-up.png?resize=151%2C152&quality=100&strip=all&ssl=1

BẬT TÍNH NĂNG TOUCH WAKE UP

Việc kích hoạt Node Wifi32 để đánh thức bằng cách sử dụng bàn ghim rất đơn giản. Trong Arduino IDE, bạn cần sử dụng chức năng sau:

esp_sleep_enable_touchpad_wakeup()

CODE

Hãy xem cách này hoạt động bằng cách sử dụng một ví dụ từ thư viện. Mở Arduino IDE của bạn và đi tới File >  Examples >  NodeWifi32  >  Deep Sleep và mở bản phác thảo TouchWakeUp .

#define Threshold 40 /* Greater the value, more the sensitivity */
RTC_DATA_ATTR int bootCount = 0;
touch_pad_t touchPin;
/*
Method to print the reason by which NodeWifi32
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 NodeWifi32
has been awaken from sleep
*/
void print_wakeup_touchpad(){
  touchPin = esp_sleep_get_touchpad_wakeup_status();
  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 16"); 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 32"); break;
    case 9  : Serial.println("Touch detected on GPIO 32"); break;
    default : Serial.println("Wakeup not by touchpad"); break;
  }
}
void callback(){
  //placeholder callback function
}
void setup(){
  Serial.begin(116200);
  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 NodeWifi32 and touchpad too
  print_wakeup_reason();
  print_wakeup_touchpad();
  //Setup interrupt on Touch Pad 3 (GPIO16)
  touchAttachInterrupt(T3, callback, Threshold);
  //Configure Touchpad as wakeup source
  esp_sleep_enable_touchpad_wakeup();
  //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
}

ĐẶT THRESHOLD

Điều đầu tiên bạn cần làm là đặt giá trị ngưỡng cho các chân cảm ứng. Trong trường hợp này, chúng tôi đang thiết lập Threshold thành 40. Bạn có thể cần thay đổi giá trị ngưỡng tùy thuộc vào dự án của mình.

#define Threshold 40

Khi bạn chạm vào GPIO cảm ứng, giá trị mà cảm biến đọc được sẽ giảm. Vì vậy, bạn có thể đặt giá trị ngưỡng có thể xảy ra khi phát hiện chạm.

Giá trị ngưỡng được đặt ở đây có nghĩa là khi giá trị mà GPIO cảm ứng đọc được dưới 40, thì Node Wifi32 sẽ hoạt động. Bạn có thể điều chỉnh giá trị đó cho phù hợp với độ nhạy mong muốn.

ATTACH INTERRUPTS

Bạn cần gắn ngắt vào các chân cảm ứng. Khi phát hiện chạm trên một GPIO được chỉ định, một chức năng gọi lại sẽ được thực thi. Ví dụ, hãy xem dòng sau:

//Setup interrupt on Touch Pad 3 (GPIO16)

touchAttachInterrupt(T3, callback, Threshold); 

Khi giá trị đọc trên T3 (GPIO 16) thấp hơn giá trị được đặt trên Threshold biến, Node Wifi32 thức dậy và callback chức năng được thực thi.

Các callback() chức năng sẽ chỉ được thực thi nếu Node Wifi32 đang hoạt động.

  • Nếu Node Wifi32 ở chế độ ngủ và bạn chạm vào T3, Node Wifi32 sẽ thức dậy – callback() chức năng sẽ không được thực thi nếu bạn chỉ cần nhấn và thả chốt cảm ứng;
  • Nếu Node Wifi32 đang hoạt động và bạn chạm vào T3, chức năng gọi lại sẽ được thực thi. Vì vậy, nếu bạn muốn thực hiện callback() chức năng khi bạn đánh thức Node Wifi32, bạn cần giữ chạm vào chốt đó một lúc cho đến khi chức năng được thực thi.

Trong trường hợp này, callback() chức năng trống.

void callback(){
   //placeholder callback function
}

Nếu bạn muốn đánh thức Node Wifi32 bằng các chân cảm ứng khác nhau, bạn chỉ cần gắn các ngắt vào các chân đó.

Tiếp theo, bạn cần sử dụng esp_sleep_enable_touchpad_wakeup() đặt các chân cảm ứng làm nguồn đánh thức.

//Configure Touchpad as wakeup source
esp_sleep_enable_touchpad_wakeup()

SƠ ĐỒ

Để kiểm tra ví dụ này, hãy đấu dây cáp vào GPIO 16, như được hiển thị trong sơ đồ bên dưới.

Nối dây cáp vào ESp32

(Sơ đồ này sử dụng phiên bản ESP32 DEV Module với 30 GPIO – nếu bạn đang sử dụng mô hình khác, vui lòng kiểm tra sơ đồ chân của bảng bạn đang sử dụng.)

KIỂM TRA VÍ DỤ

Tải mã lên Node Wifi32 của bạn và mở Serial Monitor ở tốc độ truyền 116200.

Mở Serial Monitor

Node Wifi32 chuyển sang chế độ Deep Sleep.

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

Chạm vào dây như hình
Cham vào dây như hình

Khi bạn chạm vào chốt, Node Wifi32 hiển thị trên Serial Monitor: số khởi động, nguyên nhân đánh thức và phát hiện thấy chạm GPIO.

Lập trình esp32 bằng arduino IDE

ĐÁNH THỨC BÊN NGOÀI

Bên cạnh bộ hẹn giờ và các chân cảm ứng, chúng ta cũng có thể đánh thức NodeWifi32 khỏi chế độ Deep Sleep bằng cách chuyển đổi giá trị của tín hiệu trên một chân cắm, giống như nhấn nút. Đây được gọi là đánh thức bên ngoài. Bạn có hai khả năng đánh thức bên ngoài: ext0 và ext1.

https://i2.wp.com/randomnerdtutorials.com/wp-content/uploads/2019/02/external-wake-up.png?resize=263%2C188&quality=100&strip=all&ssl=1

ĐÁNH THỨC BÊN NGOÀI (ext0)

Nguồn đánh thức này cho phép bạn sử dụng một ghim để đánh thức Node Wifi32. Tùy chọn nguồn đánh thức ext0 sẽ sử dụng các GPIO RTC để đánh thức. Vì vậy, các thiết bị ngoại vi RTC sẽ được duy trì trong chế độ Deep Sleep 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 chức năng sau:

esp_sleep_enable_ext0_wakeup(GPIO_NUM_X, level)

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

Đối số thứ hai, cấp độ, có thể là 1 hoặc 0. Điều này thể hiện 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à GPIO RTC.

ĐÁNH THỨC BÊN NGOÀI (ext1)

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

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

Nguồn đánh thức này được thực hiện bởi bộ điều khiển RTC. Vì vậy, thiết bị ngoại vi RTC và bộ nhớ RTC có thể được tắt ở chế độ này.

Để sử dụng nguồn đánh thức này, bạn sử dụng mã lập trình sau:

esp_sleep_enable_ext1_wakeup(bitmask, mode)

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

  • Mặt nạ bit của các số GPIO sẽ gây ra đánh thức;
  • Chế độ: logic để đánh thức Node Wifi32. Nó có thể:
    • ESP_EXT1_WAKEUP_ALL_LOW: thức dậy khi tất cả các GPIO xuống thấp;
    • ESP_EXT1_WAKEUP_ANY_HIGH: thức dậy nếu bất kỳ GPIO nào tăng 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à GPIO RTC.

CODE

Hãy cùng khám phá ví dụ đi kèm với thư viện Node Wifi32. Đi tới File > Examples > NodeWifi32 > Deep Sleep > ExternalWakeUp :

#define BUTTON_PIN_BITMASK 0x200000000 // 2^32 in hex
RTC_DATA_ATTR int bootCount = 0;
/*
Method to print the reason by which NodeWifi32
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(116200);
  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 NodeWifi32
  print_wakeup_reason();
  esp_sleep_enable_ext0_wakeup(GPIO_NUM_32,1); //1 = High, 0 = Low
  //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
}

Ví dụ này đánh thức Node Wifi32 khi bạn kích hoạt GPIO 32 thành GPIO mang giá trị HIGH. Ví dụ mã cho thấy cách sử dụng cả hai phương thức: ext0 và ext1. Nếu bạn tải lên mã như hiện tại, bạn sẽ sử dụng ext0. Chúng tôi sẽ chỉ cho bạn cách hoạt động của cả hai phương pháp và cách sử dụng chúng.

Mã này rất giống với những cái trước trong bài viết này. Bên trong setup(), bạn bắt đầu bằng cách khởi tạo giao tiếp nối tiếp:

Serial.begin(116200); 
delay(1000); //Take some time to open up the Serial Monitor

Sau đó, bạn tăng một đến bootCount và in biến đó trong Serial Monitor.

++bootCount;
Serial.println("Boot number: " + String(bootCount));

Tiếp theo, bạn in lý do đánh thức bằng cách sử dụng print_wakeup_reason () chức năng được xác định trước đó.

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

Sau đó, bạn cần bật các nguồn đánh thức. Chúng tôi sẽ kiểm tra từng nguồn đánh thức, ext0 và ext1, riêng biệt.

EXT0

Trong ví dụ này, Node Wifi32 thức dậy khi GPIO 32 được kích hoạt lên cao:

esp_sleep_enable_ext0_wakeup(GPIO_NUM_32,1); //1 = High, 0 = Low

Thay vì GPIO 32, bạn có thể sử dụng bất kỳ chân GPIO RTC nào khác.

SƠ ĐỒ

Để kiểm tra ví dụ này, hãy nối một nút nhấn vào Node Wifi32 của bạn bằng cách làm theo sơ đồ tiếp theo. Nút được kết nối với GPIO 32 bằng cách sử dụng một điện trở 10K Ohm kéo xuống.

(Sơ đồ này sử dụng phiên bản ESP32 DEV Module với 30 GPIO – nếu bạn đang sử dụng mô hình khác, vui lòng kiểm tra sơ đồ chân của bảng bạn đang sử dụng.)

Lưu ý: chỉ GPIO RTC mới có thể được sử dụng làm nguồn đánh thức. Thay vì GPIO 32, bạn cũng có thể sử dụng bất kỳ chân GPIO RTC nào để kết nối nút của mình.

KIỂM TRA VÍ DỤ

Hãy kiểm tra ví dụ này. Upload ví dụ lên Node Wifi32 của bạn. Đảm bảo rằng bạn đã chọn đúng board và cổng COM. 

Mở Serial Monitor với tốc độ truyền là 116200.

https://i2.wp.com/randomnerdtutorials.com/wp-content/uploads/2019/02/serial-monitor.png?resize=745%2C109&quality=100&strip=all&ssl=1

Nhấn nút để đánh thức Node Wifi32.

Hãy thử điều này vài lần và thấy số lần khởi động tăng lên trong mỗi lần nhấn nút.

https://i0.wp.com/randomnerdtutorials.com/wp-content/uploads/2019/02/external-wake-up-serial-monitor_f.png?resize=598%2C373&quality=100&strip=all&ssl=1

Sử dụng phương pháp này rất hữu ích để đánh thức Node Wifi32 của bạn bằng cách sử dụng một nút bấm, chẳng hạn, để thực hiện một tác vụ nhất định. 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.

Điều gì sẽ xảy ra nếu bạn muốn có các nút khác nhau, tất cả chúng đều đánh thức Node Wifi32, nhưng thực hiện các nhiệm vụ khác nhau? Đối với điều đó, bạn cần sử dụng phương thức ext1.

ext1

Ext1 cho phép bạn đánh thức Node Wifi32 bằng các nút khác nhau và thực hiện các tác vụ khác nhau tùy thuộc vào nút bạn đã nhấn.

Thay vì sử dụng esp_sleep_enable_ext0_wakeup(), bạn sử dụng esp_sleep_enable_ ext1_wakeup(). Trong code, chức năng đó được nhận xét:

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

Bỏ ghi chú chức năng đó để bạn 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 Node Wifi32.

Trong ví dụ này, chúng tôi đang sử dụng biến BUTTON_PIN_BITMASK, được xác định ở đầu code:

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

Đây chỉ là xác định một ghim làm nguồn đánh thức GPIO 32. Bạn cần sửa đổi bitmask để định cấu hình nhiều GPIO hơn làm nguồn WAKE UP.

GPIO Bitmask

Để nhận Bitmask GPIO, hãy làm theo các bước tiếp theo:

  1. Tính 2 ^ (GPIO_NUMBER). Lưu kết quả dưới dạng số thập phân;
  2. Chuyển đổi số thập phân để hex;
  3. Thay thế số hex bạn đã nhận được trong BUTTON_PIN_BITMASK Biến đổi.

Mask cho một GPIO duy nhất

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

1. Tính 2 ^ 32. Bạn sẽ nhận được  8589934592 ;

2. Chuyển số đó (8589934592) sang hệ thập lục phân.

Chuyển đổi thành hệ lập phân

3. Sao chép số Hex vào BUTTON_PIN_BITMASK và bạn sẽ nhận được:

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

Mask cho một số GPIO

Nếu bạn muốn sử dụng GPIO 22 và GPIO 16 như một nguồn đánh thức, bạn nên làm như sau:

  1. Tính 2 ^ 2 + 2 ^ 16. Bạn sẽ nhận được 32772
  2. Chuyển số đó thành hex. Bạn sẽ nhận được: 8004
  3. Thay thế số đó trong BUTTON_PIN_BITMASK như sau:

#define BUTTON_PIN_BITMASK 0x8004

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

Khi bạn sử dụng nhiều chân để đánh thức Node Wifi32, sẽ rất hữu ích khi biết chân nào đã gây ra đánh thức. Để làm được điều đó, bạn có thể sử dụng đoạn 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à số mũ: 2 ^ (GPIO_NUMBER). 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(GPIO_NUMBER)/log(2)

ĐÁNH THỨC BÊN NGOÀI – NHIỀU GPIO

Bây giờ, bạn sẽ có thể đánh thức Node Wifi32 bằng các nút khác nhau và xác định nút nào đã gây ra đánh thức. Trong ví dụ này, chúng tôi sẽ sử dụng GPIO 22 và GPIO 16 như một nguồn đánh thức.

SƠ ĐỒ

Nối hai nút với Node Wifi32 của bạn. Trong ví dụ này, chúng tôi đang sử dụng GPIO22 và GPIO 16, nhưng bạn có thể kết nối các nút của mình với bất kỳ GPIO RTC nào.

Kết nối GPIO

CODE

Bạn cần thực hiện một số sửa đổi đối với mã mẫu mà chúng tôi đã sử dụng trước đây:

  • tạo một Bitmask để sử dụng GPIO 16 và GPIO 22. Chúng tôi đã chỉ cho bạn cách làm điều này trước đây;
  • Kích hoạt ext1 làm nguồn đánh thức;
  • Sử dụng esp_sleep_get_ext1_wakeup_status () để nhận GPIO đã kích hoạt đánh thức.

Bản phác thảo tiếp theo đã thực hiện tất cả những thay đổi đó.

#define BUTTON_PIN_BITMASK 0x8004 // GPIOs 22 and 16
RTC_DATA_ATTR int bootCount = 0;
/*
Method to print the reason by which Node Wifi32
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(){
  int GPIO_reason = esp_sleep_get_ext1_wakeup_status();
  Serial.print("GPIO that triggered the wake up: GPIO ");
  Serial.println((log(GPIO_reason))/log(22), 0);
}
void setup(){
  Serial.begin(116200);
  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 NodeWifi32
  print_wakeup_reason();
  //Print the GPIO used to wake up
  print_GPIO_wake_up();
  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
}

Bạn xác định Bitmask GPIO ở đầu mã:

#define BUTTON_PIN_BITMASK 0x8004 // GPIOs 22 and 16

Bạn tạo một hàm để in GPIO gây ra đánh thức:

void print_GPIO_wake_up(){
  int GPIO_reason = esp_sleep_get_ext1_wakeup_status();
  Serial.print("GPIO that triggered the wake up: GPIO ");
  Serial.println((log(GPIO_reason))/log(22), 0);
}

Và cuối cùng, bạn bật ext1 làm nguồn đánh thức:

esp_sleep_enable_ext1_wakeup(BUTTON_PIN_BITMASK,ESP_EXT1_WAKEUP_ANY_HIGH);

Kiểm tra Sketch

Có hai nút được kết nối với GPIO 22 và GPIO 16, bạn có thể uplaod code được cung cấp lên Node Wifi32 của mình. Đảm bảo rằng bạn đã chọn đúng board và cổng COM.

Node Wifi32 hiện đang ở chế độ deep sleep. Bạn có thể đánh thức nó bằng cách nhấn các nút.

Nhấn nút để đánh thức Esp32
Mở Serial Monitor ở tốc độ truyền 116200. Nhấn các nút để đánh thức Node Wifi32.

Bạn sẽ nhận được kết quả như hình trên màn hình nối tiếp.

Giao diện trên màn hình

Kết luận,

Trong bài viết này, chúng tôi đã hướng dẫn bạn cách sử dụng chế độ deep sleep với Node Wifi32 và các cách khác nhau để đánh thức nó. Bạn có thể đánh thức Node Wifi32 bằng cách sử dụng bộ đếm thời gian, chân cảm ứng hoặc thay đổi trạng thái GPIO.

Hãy tóm tắt những gì chúng ta đã thấy về cách đánh thức:

Hẹn giờ đánh thức

  • Để bật bộ hẹn giờ đánh thức, bạn sử dụng esp_sleep_enable_timer_wakeup (time_in_us) chức năng;
  • Sử dụng esp_deep_sleep_start () có chức năng bắt đầu giấc ngủ sâu.

Đánh thức bằng cách chạm vào chân cảm ứng

  • Để sử dụng các chân cảm ứng làm nguồn đánh thức, trước tiên, bạn cần gắn vào các chân cảm ứng bằng cách sử dụng: touchAttachInterrupt (Touchpin, callback, Threshold)
  • 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 esp_deep_sleep_start () để đặt NodeWifi32 ở chế độ ngủ sâu.

Đánh thức bên ngoài

  • Bạn chỉ có thể sử dụng RTC GPIO như một lầ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 NodeWifi32 bằng một chân GPIO;
  • ext1 cho phép bạn đánh thức NodeWifi32 bằng một số chân GPIO.

Để xem tất cả các bài hướng dẫn về lập trình Arduino, bạn truy cập vào đây nhé: Tổng hợp các bài hướng dẫn về Arduino. Nếu bạn có bất kỳ ý kiến đóng góp hoặc thắc mắc gì, bạn có thể để lại comment phía dưới hoặc liên hệ với OhStem qua Fanpage để được hỗ trợ nhé

Tags: deep sleep, lập trình esp32 bằng arduino ide, wake up sources

Những bài liên quan

Trả lời

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *

Fill out this field
Fill out this field
Vui lòng nhập địa chỉ email hợp lệ.
You need to agree with the terms to proceed