ESP32 深度睡眠定時器喚醒

本課程將展示如何將 ESP32 置於深度睡眠模式,並在預定時間後使用定時器將其喚醒。

ESP32 可以進入深度睡眠模式,然後在預定的時間段後喚醒。如果您正在運行需要時間戳或日常任務的項目,同時保持低功耗,此功能特別有用。

要了解有關深度睡眠和其他喚醒來源的更多信息,您可以按照以下教程進行操作:

[完整指南]帶有 Arduino IDE 和喚醒源的 ESP32 深度睡眠
ESP32 從深度睡眠中喚醒外部
ESP32 Touch 從深度睡眠中喚醒

寫一個深度睡眠素描

要編寫一個草稿圖以使您的 ESP32 進入深度睡眠模式,然後將其喚醒,您需要:

  1. 首先,配置喚醒源。意思是要配置將喚醒 ESP32 的內容。您可以使用一個或組合多個喚醒源。在本課程中,我們將向您展示如何使用定時器喚醒。
  2. 您可以決定在深度睡眠期間關閉或繼續使用哪些外圍設備。但是,預設情況下,ESP32 會自動關閉您定義的喚醒源不需要的外圍設備。
  3. 最後,您使用esp_deep_sleep_start()使您的 ESP32 進入深度睡眠模式的功能。

定時器喚醒

ESP32 可以進入深度睡眠模式,然後在預定義的時間段喚醒。如果您正在運行需要時間戳或日常任務的項目,同時保持低功耗,則此功能特別有用。

ESP32 RTC 控制器有一個內置定時器,您可以使用它在預定義的時間後喚醒 ESP32。

啟用定時器喚醒

讓 ESP32 在預定義的時間後喚醒非常簡單。在 Arduino IDE 中,您只需在以下函數中指定睡眠時間(以微秒為單位):

esp_sleep_enable_timer_wakeup(time_in_us)

程式碼

要對 ESP32 進行編程,我們將使用 Arduino IDE。因此,您需要確保已安裝 ESP32 外掛。如果您還沒有安裝 ESP32 外掛,請按照以下教程之一安裝:

讓我們使用程式庫中的範例來看看深度睡眠與定時器喚醒是如何工作的。打開您的 Arduino IDE,然後轉到檔案 > 範例 > ESP32 > Deep Sleep,然後打開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 <cherukupallip@gmail.com>
*/

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

讓我們看一下這段程式碼。第一段說明描述了在深度睡眠期間通過定時器喚醒關閉的內容。

在這種模式下,CPU、大部分 RAM
和所有由 APB_CLK 提供時鐘的數字外設都
將斷電。晶片中唯一
仍可以上電的部分是:
RTC 控制器、RTC 外設和 RTC 存儲器

當您使用定時器喚醒時,將被上電的部分是 RTC 控制器、RTC 外設和 RTC 存儲器。

定義睡眠時間

前兩行程式碼定義了 ESP32 休眠的時間段。

#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) */

此範例使用從微秒到秒的轉換因子,以便您可以在 TIME_TO_SLEEP 以秒為單位的變量。在這種情況下,該範例將使 ESP32 進入深度睡眠模式 5 秒。

將數據保存在 RTC 存儲器上

使用 ESP32,您可以將數據儲存在 RTC 存儲器中。ESP32 在 RTC 部分有 8kB SRAM,稱為 RTC 快閃存儲器。此處保存的數據在深度睡眠期間不會被刪除。但是,當您按下reset按鈕(ESP32 板上標記為 EN 的按鈕)時,它會被刪除。

要將數據保存在 RTC 記憶體中,您只需新增RTC_DATA_ATTR在變量定義之前。該範例保存引導計數RTC 記憶體上的變量。該變量將計算 ESP32 從深度睡眠中喚醒的次數。

RTC_DATA_ATTR int bootCount = 0;

喚醒原因

然後,程式碼定義print_wakeup_reason()函數,印出 ESP32 從睡眠中喚醒的原因。

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()

在setup()裡是您應該放置程式碼的地方。在深眠中,草稿圖永遠不會跑loop()函數。所以,你需要把所有的草稿圖程式碼都寫在setup()裡.

此範例首先以 115200 的鮑率初始化串行通信。

Serial.begin(115200);

然後,引導計數每次重新啟動時變量都會增加1,並且該數字會列印在序列埠監控視窗中。

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

然後,程式碼調用print_wakeup_reason()函數,但您可以調用任何要執行所需任務的函數。例如,您可能希望每天喚醒 ESP32 一次以從感測器讀取值。

接下來,程式碼使用以下函數定義喚醒源:

esp_sleep_enable_timer_wakeup(time_in_us)

正如我們之前所見,此函數接受以微秒為單位的睡眠時間作為參數。

在這個例子中,我們有以下內容:

esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);

然後,在執行完所有任務後,esp 通過調用以下函數進入睡眠狀態:

esp_deep_sleep_start()

loop()

loop()函數部分內程式碼是空的,因為 ESP32 將在到達這部分程式碼之前進入睡眠狀態。所以,你需要把你所有的草稿圖程式碼都寫在setup()內.

將範例草稿圖上傳到您的 ESP32。確保您選擇了正確的開發板和 COM 端口。

測試定時器喚醒

以 115200 的鮑率打開序列埠監控視窗。

每 5 秒,ESP 喚醒,在序列埠監控視窗上列印一條訊息,然後再次進入深度睡眠。

每次 ESP 喚醒引導計數變量增加。它還列印喚醒原因,如下圖所示。

螢幕擷取畫面 2022-06-13 074657-1

但是,請注意,如果您按下 ESP32 板上的 EN 按鈕,它會將引導計數再次重置為 1。

總結

我們希望您發現本教程很有用。現在,您可以修改提供的範例,而不是只是列印訊息,您可以讓 ESP32 執行任何其他任務。

定時器喚醒對於使用 ESP32 執行週期性任務而不會消耗太多電量很有用。

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *