风筝
发表于: 2022-11-6 21:12:41 | 显示全部楼层

当您的IoT项目由电源适配器供电时,您不会太关心功耗。但是,如果您要使用电池为项目供电,则需要计算每个MA电流。


ESP32可能是相对功耗较高的设备,具体取决于其处于哪种状态。通常,在通过WiFi传输数据时240mA左右,它的正常操作时约75mA。


这里的解决方案是通过利用深度睡眠模式来降低ESP32的功耗。


ESP32深度睡眠

在深度睡眠模式下,CPU、大多数RAM和所有数字外围设备都可以关闭。芯片唯一保持运行的部分是:

●   ULP协处理器

●   RTC控制器

●   RTC外围设备

●   RTC内存


芯片将消耗约0.15 mA(如果ULP协处理器打开)至10µA。

ESP32-Deep-Sleep-Functional-Block-Diagram.jpg


在深度睡眠模式下,主CPU被关闭,而ULP协处理器可以采用传感器读数,并在必要时唤醒CPU。这种睡眠模式称为ULP传感器监控模式。这对于设计应用程序需要由外部事件或计时器或两者组合唤醒的应用程序很有用,同时保持最少的功耗。


与CPU一起,芯片的主要内存也被禁用。因此,存储在该内存中的所有内容都被删除且无法访问。


由于RTC存储持续供电,因此即使在深度睡眠期间也保留了其内容,并且可以在芯片唤醒后检索。这就是为什么芯片在进入深度睡眠之前将Wi-Fi和蓝牙连接数据存储在RTC内存中的原因。


如果要在重新启动后使用数据,请通过使用RTC_DATA_ATTR属性来定义全局变量,将其存储在RTC内存中。例如,RTC_DATA_ATTR int myVar = 0。


从深度睡眠中出来后,芯片通过复位重新启动,并从一开始就开始执行程序。


与其他睡眠模式不同,系统无法自动进入深度睡眠模式。 esp_deep_sleep_start()函数用于配置唤醒源后立即进入深度睡眠。


ESP32深度睡眠唤醒源

ESP32可以使用多个源从深度睡眠模式唤醒。这些源是:

●   定时器

●   触摸引脚

●   外部唤醒(Ext0&Ext1)

可以组合多个唤醒源,当触发其中一个源时,芯片将被唤醒。


ESP32唤醒源:定时器

ESP32 RTC控制器具有一个内置定时器,您可以在预定义的时间后用来唤醒ESP32。


此功能在需要时间戳或日常任务的同时保持低功耗的项目中特别有用。


esp_sleep_enable_timer_wakeup(time_in_us)函数用于将计时器配置为唤醒源。


示例代码

让我们使用库中的示例来看看它的工作原理。打开您的Arduino IDE,然后导航到File > Examples > ESP32 > Deep Sleep,然后打开TimerWakeup草图。


该草图演示了最基本的深度睡眠示例,其中定时器是唤醒源,以及如何将数据存储在RTC内存中以在复位后使用它。

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

  3. RTC_DATA_ATTR int bootCount = 0;

  4. /*
  5. Method to print the reason by which ESP32
  6. has been awaken from sleep
  7. */
  8. void print_wakeup_reason(){
  9.   esp_sleep_wakeup_cause_t wakeup_reason;

  10.   wakeup_reason = esp_sleep_get_wakeup_cause();

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

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

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

  27.   //Print the wakeup reason for ESP32
  28.   print_wakeup_reason();

  29.   /*
  30.   First we configure the wake up source
  31.   We set our ESP32 to wake up every 5 seconds
  32.   */
  33.   esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
  34.   Serial.println("Setup ESP32 to sleep for every " + String(TIME_TO_SLEEP) +
  35.   " Seconds");

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

  47.   /*
  48.   Now that we have setup a wake cause and if needed setup the
  49.   peripherals state in deep sleep, we can now start going to
  50.   deep sleep.
  51.   In the case that no wake up sources were provided but deep
  52.   sleep was started, it will sleep forever unless hardware
  53.   reset occurs.
  54.   */
  55.   Serial.println("Going to sleep now");
  56.   Serial.flush();
  57.   esp_deep_sleep_start();
  58.   Serial.println("This will never be printed");
  59. }

  60. void loop(){
  61.   //This is not going to be called
  62. }
复制代码

上传草图后,打开串口显示器,将波特率设置为115200 bps。


ESP32每5秒醒来一次,打印出唤醒原因并在串口显示器上启动,然后再次入睡。

ESP32-Deep-Sleep-Timer-Wakeup-Output.jpg


现在,按下EN按钮复位ESP32,它应该再次将启动器重置为1,以表明RTC内存已完全擦除。


代码说明

前两行代码定义了ESP32入睡的时间。


此示例使用从微秒到秒的转换系数,因此您可以在time_to_sleep变量中以秒为单位设置睡眠时间。在这里,ESP32进入深度睡眠模式5秒钟。

  1. #define uS_TO_S_FACTOR 1000000ULL  /* Conversion factor for micro seconds to seconds */
  2. #define TIME_TO_SLEEP  5        /* Time ESP32 will go to sleep (in seconds) */
复制代码

如前所述,您可以将数据保存在ESP32的RTC内存(8KB SRAM)中,该内存在深度睡眠期间未删除。但是,当ESP32复位时,它将被删除。


要将数据保存在RTC内存上,您只需要在定义变量之前添加RTC_DATA_ATTR 属性即可。在此示例中,bootCount变量保存在RTC内存中。它将计算ESP32从深度睡眠中醒来的次数。

  1. RTC_DATA_ATTR int bootCount = 0;
复制代码

接下来,定义了print_wakeup_reason()函数,该函数打印出ESP32从深度睡眠中唤醒的原因。

  1. void print_wakeup_reason(){
  2.   esp_sleep_wakeup_cause_t wakeup_reason;

  3.   wakeup_reason = esp_sleep_get_wakeup_cause();

  4.   switch(wakeup_reason)
  5.   {
  6.     case ESP_SLEEP_WAKEUP_EXT0 : Serial.println("Wakeup caused by external signal using RTC_IO"); break;
  7.     case ESP_SLEEP_WAKEUP_EXT1 : Serial.println("Wakeup caused by external signal using RTC_CNTL"); break;
  8.     case ESP_SLEEP_WAKEUP_TIMER : Serial.println("Wakeup caused by timer"); break;
  9.     case ESP_SLEEP_WAKEUP_TOUCHPAD : Serial.println("Wakeup caused by touchpad"); break;
  10.     case ESP_SLEEP_WAKEUP_ULP : Serial.println("Wakeup caused by ULP program"); break;
  11.     default : Serial.printf("Wakeup was not caused by deep sleep: %d\n",wakeup_reason); break;
  12.   }
  13. }
复制代码

在setup()函数中,我们首先将串口通信初始化。

  1. Serial.begin(115200);
复制代码

然后将bootCount变量加1,然后打印到串口显示器上,以显示ESP32从深度睡眠中醒来的次数。

  1. ++bootCount;
  2. Serial.println("Boot number: " + String(bootCount));
复制代码

然后调用print_wakeup_reason()函数,但是您也可以调用要执行所需任务的任何函数,例如,读取传感器的值。

  1. print_wakeup_reason();
复制代码

接下来,我们使用esp_sleep_enable_timer_wakeup(time_in_us)函数配置定时器唤醒源。在这里,ESP32将每5秒醒来一次。

  1. esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
复制代码

最后,通过调用esp_deep_sleep_start()函数来使ESP32进入睡眠模式。

  1. esp_deep_sleep_start();
复制代码

在此草图中,ESP32在setup()函数本身中进入深度睡眠,因此它永远不会达到loop()函数。因此,loop()函数是空的。

  1. void loop(){
  2.   //This is not going to be called
  3. }
复制代码

跳转到指定楼层
风筝
发表于: 2022-11-6 21:29:50 | 显示全部楼层

ESP32唤醒源:触摸引脚

您可以使用以下触摸引脚从深度睡眠中唤醒ESP32。

ESP32-Touch-Pins.jpg


使用触摸引脚唤醒ESP32很简单。在Arduino IDE中,您只需要使用esp_sleep_enable_touchpad_wakeup()函数。


硬件连接

让我们将线缆连接到GPIO#15(触摸#3),该线缆将充当触摸唤醒源。 您可以将任何导电物体连接到电线、铝箔、导电布、导电涂料等,并将其转换为触摸面板。

Connecting-Wire-to-ESP32-for-Touch-Wakeup-Source.jpg


示例代码

让我们使用库中的示例来看看它的工作原理。 打开您的Arduino IDE,然后导航到File > Examples > ESP32 > Deep Sleep,然后打开TouchWakeup草图。


该草图演示了最基本的深度睡眠示例,触摸作为唤醒源以及如何将数据存储在RTC内存中以在重新启动后使用它。

  1. #define Threshold 40 /* Greater the value, more the sensitivity */

  2. RTC_DATA_ATTR int bootCount = 0;
  3. touch_pad_t touchPin;
  4. /*
  5. Method to print the reason by which ESP32
  6. has been awaken from sleep
  7. */
  8. void print_wakeup_reason(){
  9.   esp_sleep_wakeup_cause_t wakeup_reason;

  10.   wakeup_reason = esp_sleep_get_wakeup_cause();

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

  21. /*
  22. Method to print the touchpad by which ESP32
  23. has been awaken from sleep
  24. */
  25. void print_wakeup_touchpad(){
  26.   touchPin = esp_sleep_get_touchpad_wakeup_status();

  27.   switch(touchPin)
  28.   {
  29.     case 0  : Serial.println("Touch detected on GPIO 4"); break;
  30.     case 1  : Serial.println("Touch detected on GPIO 0"); break;
  31.     case 2  : Serial.println("Touch detected on GPIO 2"); break;
  32.     case 3  : Serial.println("Touch detected on GPIO 15"); break;
  33.     case 4  : Serial.println("Touch detected on GPIO 13"); break;
  34.     case 5  : Serial.println("Touch detected on GPIO 12"); break;
  35.     case 6  : Serial.println("Touch detected on GPIO 14"); break;
  36.     case 7  : Serial.println("Touch detected on GPIO 27"); break;
  37.     case 8  : Serial.println("Touch detected on GPIO 33"); break;
  38.     case 9  : Serial.println("Touch detected on GPIO 32"); break;
  39.     default : Serial.println("Wakeup not by touchpad"); break;
  40.   }
  41. }

  42. void callback(){
  43.   //placeholder callback function
  44. }

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

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

  51.   //Print the wakeup reason for ESP32 and touchpad too
  52.   print_wakeup_reason();
  53.   print_wakeup_touchpad();

  54.   //Setup interrupt on Touch Pad 3 (GPIO15)
  55.   touchAttachInterrupt(T3, callback, Threshold);

  56.   //Configure Touchpad as wakeup source
  57.   esp_sleep_enable_touchpad_wakeup();

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

  63. void loop(){
  64.   //This will never be reached
  65. }
复制代码

上传草图后,打开串口显示器,将波特率设置为115200bps。


现在,当触摸引脚时,ESP32将在串口显示器上显示启动次数、唤醒原因以及触摸哪个GPIO。

ESP32-Deep-Sleep-Touch-Wakeup-Output.jpg


代码说明

第一行代码将触摸引脚的阈值设置为40。阈值越高,灵敏度越高。您可以根据项目更改此值。

  1. #define Threshold 40 /* Greater the value, more the sensitivity */
复制代码

如前所述,您可以将数据保存在ESP32的RTC内存(8KB SRAM)中,该内存在深度睡眠期间未删除。但是,当ESP32复位时,它将被删除。


要将数据保存在RTC内存上,您只需要在定义变量之前添加RTC_DATA_ATTR属性即可。在此示例中,BbootCount变量保存在RTC内存中。它将计算ESP32从深度睡眠中唤醒的次数。

  1. RTC_DATA_ATTR int bootCount = 0;
复制代码

在此之后,定义了一个名为touch_pad_t(枚举类型)的touchPin变量,后来将帮助我们打印哪个GPIO从睡眠中唤醒ESP32。

  1. touch_pad_t touchPin;
复制代码

接下来,定义了print_wakeup_reason()函数,该函数打印出ESP32从深度睡眠中唤醒的原因。

  1. void print_wakeup_reason(){
  2.   esp_sleep_wakeup_cause_t wakeup_reason;

  3.   wakeup_reason = esp_sleep_get_wakeup_cause();

  4.   switch(wakeup_reason)
  5.   {
  6.     case ESP_SLEEP_WAKEUP_EXT0 : Serial.println("Wakeup caused by external signal using RTC_IO"); break;
  7.     case ESP_SLEEP_WAKEUP_EXT1 : Serial.println("Wakeup caused by external signal using RTC_CNTL"); break;
  8.     case ESP_SLEEP_WAKEUP_TIMER : Serial.println("Wakeup caused by timer"); break;
  9.     case ESP_SLEEP_WAKEUP_TOUCHPAD : Serial.println("Wakeup caused by touchpad"); break;
  10.     case ESP_SLEEP_WAKEUP_ULP : Serial.println("Wakeup caused by ULP program"); break;
  11.     default : Serial.printf("Wakeup was not caused by deep sleep: %d\n",wakeup_reason); break;
  12.   }
  13. }
复制代码

还定义了print_wakeup_touchpad()函数,该函数是打印ESP32从深度睡眠中唤醒的GPIO编号。

  1. void print_wakeup_touchpad(){
  2.   touchPin = esp_sleep_get_touchpad_wakeup_status();

  3.   switch(touchPin)
  4.   {
  5.     case 0  : Serial.println("Touch detected on GPIO 4"); break;
  6.     case 1  : Serial.println("Touch detected on GPIO 0"); break;
  7.     case 2  : Serial.println("Touch detected on GPIO 2"); break;
  8.     case 3  : Serial.println("Touch detected on GPIO 15"); break;
  9.     case 4  : Serial.println("Touch detected on GPIO 13"); break;
  10.     case 5  : Serial.println("Touch detected on GPIO 12"); break;
  11.     case 6  : Serial.println("Touch detected on GPIO 14"); break;
  12.     case 7  : Serial.println("Touch detected on GPIO 27"); break;
  13.     case 8  : Serial.println("Touch detected on GPIO 33"); break;
  14.     case 9  : Serial.println("Touch detected on GPIO 32"); break;
  15.     default : Serial.println("Wakeup not by touchpad"); break;
  16.   }
  17. }
复制代码

接下来,定义了一个callback()函数。这不过是中断服务例程(ISR),每当触发中断时,它都会调用。但是不幸的是,如果ESP32处于深度睡眠状态,则不会执行此函数。因此,此函数留为空。

  1. void callback(){
  2.   //placeholder callback function
  3. }
复制代码

在setup()函数中,我们首先初始化串口通信。

  1. Serial.begin(115200);
复制代码

然后将bootCount 变量自增1,并打印到串口显示器上,以显示ESP32从深度睡眠中醒来的次数。

  1. ++bootCount;
  2. Serial.println("Boot number: " + String(bootCount));
复制代码

然后调用print_wakeup_reason()print_wakeup_touchpad()函数,但是您也可以调用要执行所需任务的任何函数,例如,读取传感器的值。

  1. print_wakeup_reason();
  2. print_wakeup_touchpad();
复制代码

现在,中断必须连接到带有所需灵敏度阈值的触摸引脚之一。在这里,中断附着在触摸引脚3(GPIO15)上。

  1. touchAttachInterrupt(T3, callback, Threshold);
复制代码

接下来,我们使用esp_sleep_enable_touchpad_wakeup()函数配置触摸唤醒源。

  1. esp_sleep_enable_touchpad_wakeup();
复制代码

最后,调用esp_deep_sleep_start()函数使ESP32进入睡眠。

  1. esp_deep_sleep_start();
复制代码

在此草图中,ESP32在setup()函数中进入深度睡眠,因此它永远不会达到loop()函数。因此,loop()函数为空。

  1. void loop(){
  2.   //This is not going to be called
  3. }
复制代码

回复

使用道具 举报

风筝
发表于: 2022-11-6 21:44:19 | 显示全部楼层

ESP32唤醒源:外部唤醒

有两种外部触发器可以从深度睡眠中唤醒ESP32。

●    ext0  - 仅通过特定的GPIO引脚唤醒芯片时使用此功能。

●    ext1  - 当您想使用多个GPIO引脚唤醒芯片时,请使用此功能。


如果您想使用中断引脚从深度睡眠中唤醒ESP32,则必须使用所谓的RTC_GPIO引脚。这些GPIO被连接到RTC低功耗系统,因此当ESP32处于深度睡眠状态时,可以使用它们。


RTC_GPIO引脚是:

ESP32-RTC-GPIO-Pins.jpg


ext0外部唤醒源

当RTC_GPIO引脚之一更改其逻辑电平时,ESP32可以配置为从深度睡眠中唤醒。


esp_sleep_enable_ext0_wakeup(GPIO_PIN, LOGIC_LEVEL)函数用于启用此唤醒源。此函数需要两个参数。第一个是GPIO引脚编号,第二个是我们要触发唤醒的逻辑电平(低或高)。


由于ext0使用RTC IO唤醒ESP32,因此在深度睡眠期间,RTC外围设备保持运行。


而且,由于启用了RTC IO模块,因此您可以利用内部下拉或下拉电阻。他们需要在调用esp_deep_sleep_start()函数之前使用rtc_gpio_pullup_en()和rtc_gpio_pulldown_en()函数进行配置。


硬件连接

我们使用一个10k下拉电阻将按钮连接到GPIO#33。

Connecting-Button-to-ESP32-for-ext0-External-Wakeup-Source.jpg


示例代码

让我们使用库中的示例来看看它的工作原理。打开您的Arduino IDE,然后导航到File > Examples > ESP32 > Deep Sleep,然后打开ExternalWakeUp草图。


该草图展示了最基本的深度睡眠示例,其中ext0作为唤醒源。

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

  2. RTC_DATA_ATTR int bootCount = 0;

  3. /*
  4. Method to print the reason by which ESP32
  5. has been awaken from sleep
  6. */
  7. void print_wakeup_reason(){
  8.   esp_sleep_wakeup_cause_t wakeup_reason;

  9.   wakeup_reason = esp_sleep_get_wakeup_cause();

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

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

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

  26.   //Print the wakeup reason for ESP32
  27.   print_wakeup_reason();

  28.   /*
  29.   First we configure the wake up source
  30.   We set our ESP32 to wake up for an external trigger.
  31.   There are two types for ESP32, ext0 and ext1 .
  32.   ext0 uses RTC_IO to wakeup thus requires RTC peripherals
  33.   to be on while ext1 uses RTC Controller so doesnt need
  34.   peripherals to be powered on.
  35.   Note that using internal pullups/pulldowns also requires
  36.   RTC peripherals to be turned on.
  37.   */
  38.   esp_sleep_enable_ext0_wakeup(GPIO_NUM_33,1); //1 = High, 0 = Low

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

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

  46. void loop(){
  47.   //This is not going to be called
  48. }
复制代码

上传草图后,打开串口显示器,将波特率设置为115200bps。


现在,当您按下按钮时,ESP32将显示启动计数并在串口显示器上唤醒原因。尝试几次,观看每次按钮时的启动计数增加。另请注意,ext0使用RTC IO唤醒ESP32。

ESP32-Deep-Sleep-Ext0-Wakeup-Output.jpg


代码说明

第一行代码设置位掩码。 ext0外部唤醒不需要它,因此您可以暂时忽略它。我们将在ext1外部唤醒代码解释中了解这一点。

  1. #define BUTTON_PIN_BITMASK 0x200000000 // 2^33 in hex
复制代码

如前所述,您可以将数据保存在ESP32的RTC内存(8KB SRAM)中,该内存在深度睡眠期间未删除。但是,当ESP32复位时,它将被删除。


要将数据保存在RTC内存上,您只需要在定义变量之前添加RTC_DATA_ATTR属性即可。在此示例中,bootCount变量保存在RTC内存中。它将计算ESP32从深度睡眠中唤醒的次数。

  1. RTC_DATA_ATTR int bootCount = 0;
复制代码

接下来,定义了print_wakeup_reason()函数,该函数打印出ESP32从深度睡眠中唤醒的原因。

  1. void print_wakeup_reason(){
  2.   esp_sleep_wakeup_cause_t wakeup_reason;

  3.   wakeup_reason = esp_sleep_get_wakeup_cause();

  4.   switch(wakeup_reason)
  5.   {
  6.     case ESP_SLEEP_WAKEUP_EXT0 : Serial.println("Wakeup caused by external signal using RTC_IO"); break;
  7.     case ESP_SLEEP_WAKEUP_EXT1 : Serial.println("Wakeup caused by external signal using RTC_CNTL"); break;
  8.     case ESP_SLEEP_WAKEUP_TIMER : Serial.println("Wakeup caused by timer"); break;
  9.     case ESP_SLEEP_WAKEUP_TOUCHPAD : Serial.println("Wakeup caused by touchpad"); break;
  10.     case ESP_SLEEP_WAKEUP_ULP : Serial.println("Wakeup caused by ULP program"); break;
  11.     default : Serial.printf("Wakeup was not caused by deep sleep: %d\n",wakeup_reason); break;
  12.   }
  13. }
复制代码

在setup()函数中,我们首先初始化串口通信。

  1. Serial.begin(115200);
复制代码

然后将bootCount变量自增1,并打印到串口显示器上,以显示ESP32从深度睡眠中醒来的次数。

  1. ++bootCount;
  2. Serial.println("Boot number: " + String(bootCount));
复制代码

然后调用print_wakeup_reason()函数,但是您可以调用要执行所需任务的任何函数,例如,读取传感器的值。

  1. print_wakeup_reason();
复制代码

现在,使用esp_sleep_enable_ext0_wakeup(GPIO_PIN, LOGIC_LEVEL) 函数来配置ext0外部唤醒源。此函数需要两个参数。第一个是GPIO引脚编号,第二个是我们要触发唤醒的逻辑电平(低或高)。在此示例中,当GPIO#33的逻辑电平变高时,ESP32被唤醒。

  1. esp_sleep_enable_ext0_wakeup(GPIO_NUM_33,1);
复制代码

最后,调用esp_deep_sleep_start()函数来使ESP32进入睡眠。

  1. esp_deep_sleep_start();
复制代码

在此草图中,ESP32在setup()函数中进入深度睡眠,因此它永远不会达到loop()函数。因此,loop()函数为空。

  1. void loop(){
  2.   //This is not going to be called
  3. }
复制代码

回复

使用道具 举报

风筝
发表于: 2022-11-6 22:02:26 | 显示全部楼层

ext1外部唤醒源

ESP32可以配置为使用多个引脚从深度睡眠中唤醒。请记住,这些引脚必须是RTC GPIO引脚。


由于ext1唤醒源使用RTC控制器,因此不需要RTC外围设备和RTC内存。这时内部上拉和下拉电阻将不可用。


为了使用内部上拉和下拉电阻,我们需要在睡眠期间请求RTC外围设备持续供电,并在输入睡眠之前使用rtc_gpio_pullup_en()和rtc_gpio_pulldown_en()配置上拉/下拉电阻。


esp_sleep_enable_ext1_wakeup(BUTTON_PIN_MASK, LOGIC_LEVEL)函数用于启用此唤醒源。该函数需要两个参数。第一个是一个掩码,它告诉我们要使用哪些引脚,第二个参数可以是下面提到的两个逻辑电平之一,以触发唤醒:

●    如果选定的引脚其中之一为高电平(ESP_EXT1_WAKEUP_ANY_HIGH),这时会唤醒。

●    如果所有选定的引脚都低电平(ESP_EXT1_WAKEUP_ALL_LOW),这时会唤醒。


位掩码(bitmask)

理解位掩码的最简单方法是以二进制格式编写它。您可以看到位编号基于普通的GPIO编号。最低显着的位(LSB)代表GPIO#0,最显着的位(MSB)代表GPIO#39。

ext1-Pin-Bit-Mask-Representation-in-Binary.jpg

●    0代表掩码的引脚

●    1表示将启用作为唤醒源的引脚

因此,如果您想启用GPIO唤醒,则必须将1写入其相应位置,剩余引脚写0。最后,您必须将其转换为十六进制。


例如,如果您想将GPIO#32和GPIO#33用作外部唤醒源,则位掩码将是这样:

ext1-External-Wakeup-Source-Pin-Bit-Mask-Representation-in-Binary.jpg


硬件连接

让我们使用10K下拉电阻将两个按钮连接到GPIO#33和GPIO#32。

Connecting-Multiple-Buttons-to-ESP32-for-ext1-External-Wakeup-Source.jpg


示例代码

让我们使用库中相同的外部效果示例来看看它的工作原理。再次打开您的Arduino IDE,然后导航到File > Examples > ESP32 > Deep Sleep,然后打开ExternalWakeup草图。


让我们对草图进行三个更改,以使其对我们有效:

1.  更改BUTTON_PIN_BITMASK常数

2.  注释掉ext0的代码

3.  取消注释ext1的代码

  1. #define BUTTON_PIN_BITMASK 0x300000000

  2. RTC_DATA_ATTR int bootCount = 0;

  3. /*
  4. Method to print the reason by which ESP32
  5. has been awaken from sleep
  6. */
  7. void print_wakeup_reason(){
  8.   esp_sleep_wakeup_cause_t wakeup_reason;

  9.   wakeup_reason = esp_sleep_get_wakeup_cause();

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

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

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

  26.   //Print the wakeup reason for ESP32
  27.   print_wakeup_reason();

  28.   /*
  29.   First we configure the wake up source
  30.   We set our ESP32 to wake up for an external trigger.
  31.   There are two types for ESP32, ext0 and ext1 .
  32.   ext0 uses RTC_IO to wakeup thus requires RTC peripherals
  33.   to be on while ext1 uses RTC Controller so doesnt need
  34.   peripherals to be powered on.
  35.   Note that using internal pullups/pulldowns also requires
  36.   RTC peripherals to be turned on.
  37.   */
  38.   //esp_sleep_enable_ext0_wakeup(GPIO_NUM_33,1); //1 = High, 0 = Low

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

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

  46. void loop(){
  47.   //This is not going to be called
  48. }
复制代码

上传草图后,打开串口显示器,将波特率设置为115200 bps。


现在,当您按下按钮时,您将在串口显示器上看到如下结果。 另请注意,ext1使用RTC控制器唤醒ESP32。

ESP32-Deep-Sleep-Ext1-Wakeup-Output.jpg


代码说明

此代码与Ext0代码相同,除了以下两个更改。


在代码开始时,定义了位掩码。 由于我们在示例中使用了PIN gpio#32和GPIO#33,因此相应的掩码位置为1,右侧32个0,左侧为6个0。

  1. #define BUTTON_PIN_BITMASK 0x300000000
复制代码

最后,启用ext1作为唤醒源。

  1. esp_sleep_enable_ext1_wakeup(BUTTON_PIN_BITMASK,ESP_EXT1_WAKEUP_ANY_HIGH);
复制代码

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

主题 54 | 回复: 107



手机版|

GMT+8, 2024-3-29 01:33 , Processed in 0.100343 second(s), 6 queries , Gzip On, MemCache On. Powered by Discuz! X3.5

YiBoard一板网 © 2015-2022 地址:河北省石家庄市长安区高营大街 ( 冀ICP备18020117号 )

快速回复 返回顶部 返回列表