【ESP32最全学习笔记(基础篇)——9.ESP32 深度睡眠模式】

关于本教程:

ESP32 基础篇                                

1.ESP32简介                                                                

2.ESP32 Arduino 集成开发环境

3.VS 代码和 PlatformIO

4.ESP32 引脚

5.ESP32 输入输出

6.ESP32 脉宽调制

7.ESP32 模拟输入

8.ESP32 中断定时器

9.ESP32 深度睡眠 ☑

ESP32 协议篇

ESP32 网络服务器

ESP32 LoRa

ESP32 BLE

ESP32 BLE 客户端-服务器

ESP32 蓝牙

ESP32 MQTT

ESP32 ESP-NOW

ESP32 Wi-Fi

ESP32 WebSocket

ESP32 ESP-MESH

ESP32 邮箱

ESP32 短信

ESP32 HTTP 获取 POST

HTTP GET Web APIs

HTTP POST Web APIs

 ESP32 服务器篇

持续更新,关注博主不迷路!!!

 ESP32 传感器模块篇

持续更新,关注博主不迷路!!!

ESP32 终极实战篇

百余项ESP32实战项目,敬请关注!!!

ESP32 深度睡眠模式 

本文是使用 Arduino IDE 实现 ESP32 深度睡眠模式的完整指南。我们将向您展示如何让 ESP32 进入深度睡眠,并了解唤醒它的不同模式:定时器唤醒触摸唤醒外部唤醒。本指南提供了带有代码、代码解释和原理图的实际示例。

相关内容:ESP8266 深度睡眠模式

本文分为 4 个不同的部分:

引入深度睡眠模式
定时器唤醒
触摸唤醒
外部唤醒

引入深度睡眠模式

ESP32 可以在不同的电源模式之间切换:

  • 活动模式
  • 调制解调器睡眠模式
  • 浅睡眠模式
  • 深度睡眠模式
  • 休眠模式

您可以在 ESP32 Espressif 数据表中的下表中比较五种不同的模式。

ESP32 Espressif 数据表还提供了一张比较不同电源模式的功耗的表格。

这里还有表 10来比较活动模式下的功耗:

为什么选择深度睡眠模式?

让你的 ESP32 使用电池在活动模式下运行并不理想,因为电池的电量会很快耗尽。

如果将 ESP32 置于深度睡眠模式,它会降低功耗并延长电池寿命。

让 ESP32 处于深度睡眠模式意味着减少运行时消耗更多电量的活动,但只留下足够的活动以在发生有趣的事情时唤醒处理器。

在深度睡眠模式下,CPU 或 Wi-Fi 活动都不会发生,但超低功耗 (ULP) 协处理器仍可开启。

当 ESP32 处于深度睡眠模式时,RTC 内存也保持开启状态,因此我们可以为 ULP 协处理器编写程序并将其存储在 RTC 内存中,以访问外围设备、内部定时器和内部传感器。

如果您需要通过外部事件、计时器或两者唤醒主 CPU,同时保持最低功耗,则此操作模式很有用。

RTC_GPIO 引脚

在深度睡眠期间,ULP 协处理器可以使用 ESP32 的一些引脚,即 RTC_GPIO 引脚和触摸引脚。ESP32 数据表提供了一个表格来标识 RTC_GPIO 引脚。您可以在第 7 页找到该表。

您可以将该表用作参考,或查看以下引脚分配以找到不同的 RTC_GPIO 引脚。RTC_GPIO 引脚用橙色矩形框突出显示。

唤醒源

将 ESP32 置于深度睡眠模式后,有以下几种唤醒方式:

  1. 您可以使用定时器,使用预定义的时间段唤醒您的 ESP32;
  2. 您可以使用触摸针
  3. 您可以使用两种可能的外部唤醒:您可以使用一种外部唤醒,也可以使用多种不同的外部唤醒;
  4. 您可以使用ULP 协处理器唤醒——本指南不涉及此内容。

写深度睡眠代码

要写一个让你的 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)

代码

让我们使用库中的示例看看这是如何工作的。打开您的 Arduino IDE,然后转到文件>示例ESP32 >深度睡眠,然后打开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
}

让我们看一下这段代码。第一条评论描述了在深度睡眠期间通过定时器唤醒关闭电源的内容。

在这种模式下,CPU、大部分 RAM
和所有由 APB_CLK 提供时钟的数字外设都
被关闭。芯片唯一
仍可通电的部分是:
RTC 控制器、RTC 外设和 RTC 存储器

当你使用timer wake up时,将要上电的部分是RTC controller、RTC peripherals和RTC memory。

定义休眠时间

前两行代码定义了 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 快速存储器。此处保存的数据在深度睡眠期间不会被删除。但是,当您按下重置按钮(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()是您应该放置代码的地方。在沉睡中,代码永远达不到loop()陈述。所以,你需要把所有的代码都写在setup().

此示例首先以 115200 的波特率初始化串行通信。

Serial.begin(115200);

然后,开机次数变量bootCount在每次重新启动时增加 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()section 是空的,因为 ESP32 会在到达这部分代码之前进入休眠状态。所以,你需要把所有的代码都写在setup().

将示例代码上传到您的 ESP32。确保选择了正确的板和 COM 端口。

测试定时器唤醒

以 115200 的波特率打开串行监视器。

每 5 秒,ESP 唤醒一次,在串行监视器上打印一条消息,然后再次进入深度睡眠。

每次 ESP 唤醒开机次数变量增加。它还会打印唤醒原因,如下图所示。

但是请注意,如果您按下 ESP32 板上的 EN 按钮,它会将启动计数再次重置为 1。

您可以修改提供的示例,而不是打印消息,您可以让 ESP 执行任何其他任务。定时器唤醒对于使用 ESP32 执行周期性任务非常有用,例如日常任务,而不会消耗太多电量。

触摸唤醒

您可以使用触摸引脚将 ESP32 从深度睡眠中唤醒。本节介绍如何使用 Arduino IDE 执行此操作。

启用触摸唤醒

使用触摸针唤醒 ESP32 很简单。在 Arduino IDE 中,您需要使用以下函数:

esp_sleep_enable_touchpad_wakeup()

代码

让我们使用库中的示例看看这是如何工作的。打开您的 Arduino IDE,然后转到文件 示例 >  ESP32  > 深度睡眠,然后打开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

This code is under Public Domain License.

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

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

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

void callback(){
  //placeholder callback function
}

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

  //Setup interrupt on Touch Pad 3 (GPIO15)
  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
}

设置阈值

您需要做的第一件事是为触摸引脚设置一个阈值。在这种情况下,我们设置临界点到 40。您可能需要根据您的项目更改阈值。

#define Threshold 40

当您触摸触敏 GPIO 时,传感器读取的值会减少。因此,您可以设置一个阈值,使检测到触摸时发生某些事情。

这里设置的阈值是指当触摸感应 GPIO 读取的值低于 40 时,ESP32 应该被唤醒。您可以根据所需的灵敏度相应地调整该值。

附加中断

您需要将中断附加到触敏引脚。当在指定的 GPIO 上检测到触摸时,将执行回调函数。例如,看看下面一行:

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

当 T3 上读取的值(GPIO 15)低于上设置的值Threshold变量,ESP32 唤醒并且callback函数被执行。

callback()函数只会在 ESP32 唤醒时执行。

  • 如果 ESP32 处于休眠状态,你触摸 T3,ESP 将被唤醒——callback()如果您只是按下并释放触摸针,功能将不会被执行;
  • 如果 ESP32 处于唤醒状态并且您触摸 T3,将执行回调函数。所以,如果你想执行callback()当你唤醒 ESP32 时,你需要在该引脚上保持触摸一段时间,直到该功能被执行。

在这种情况下callback()函数为空。

void callback(){
   //placeholder callback function
}

如果您想使用不同的触摸引脚唤醒 ESP32,只需将中断附加到这些引脚即可。

接下来,您需要使用esp_sleep_enable_touchpad_wakeup()函数将触摸引脚设置为唤醒源。

//Configure Touchpad as wakeup source
esp_sleep_enable_touchpad_wakeup()

原理图

要测试此示例,请将电缆连接到GPIO 15,如下图所示。

(此示意图使用带有 30 个 GPIO 的 ESP32 DEVKIT V1 模块版本——如果您使用的是其他型号,请检查您正在使用的电路板的引出线。)

测试示例

将代码上传到您的 ESP32,并以 115200 的波特率打开串口监视器。

ESP32 进入深度睡眠模式。

你可以通过触摸连接到 Touch Pin 3 的线来唤醒它。

当您触摸该引脚时,ESP32 会在串行监视器上显示:启动号、唤醒原因以及检测到 GPIO 触摸的位置。

外部唤醒

除了定时器和触摸引脚,我们还可以通过切换引脚上的信号值将 ESP32 从深度睡眠中唤醒,例如按下按钮。这称为外部唤醒。您有两种外部唤醒的可能性:ext0 和 ext1。

esp_sleep_enable_ext1_wakeup(bitmask, mode)

这个函数接受两个参数:

  • 将导致唤醒的 GPIO 编号的位掩码;
  • Mode:唤醒 ESP32 的逻辑。有可能:
    • ESP_EXT1_WAKEUP_ALL_LOW:当所有 GPIO 变低时唤醒;
    • ESP_EXT1_WAKEUP_ANY_HIGH:如果任何 GPIO 变为高电平,则唤醒。

注意:使用此唤醒源,您只能使用 RTC GPIO 引脚。

代码

让我们探索 ESP32 库附带的示例。转到文件>示例ESP32 >深度睡眠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
}

此示例在您触发时唤醒 ESP32GPIO 33到高。代码示例显示了如何使用这两种方法:ext0 和 ext1。如果您按原样上传代码,您将使用 ext0。使用 ext1 的函数已注释。我们将向您展示这两种方法的工作原理以及如何使用它们。

这段代码与本文前面的代码非常相似。在里面setup(),您首先要初始化串行通信:

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

然后,您将 1 递增到开机次数变量,并在串行监视器中打印该变量。

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

接下来,您使用print_wakeup_reason()前面定义的函数。

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

在此之后,您需要启用唤醒源。我们将分别测试每个唤醒源,ext0 和 ext1。

ext0

在此示例中,ESP32 在GPIO 33被触发到高:

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

代替GPIO 33,您可以使用任何其他 RTC GPIO 引脚。

原理图

要测试此示例,请按照下一个示意图将按钮连接到 ESP32。该按钮连接到GPIO 33使用下拉 10K 欧姆电阻。

(此示意图使用带有 30 个 GPIO 的 ESP32 DEVKIT V1 模块版本——如果您使用的是其他型号,请检查您正在使用的电路板的引出线。)

注意:只有 RTC GPIO 可以用作唤醒源。除了 GPIO 33,您还可以使用任何 RTC GPIO 引脚来连接您的按钮。

测试示例

让我们测试这个例子。将示例代码上传到您的 ESP32。确保选择了正确的板和 COM 端口。以 115200 的波特率打开串行监视器。

按下按钮唤醒 ESP32。

多试几次,看到每次按下按钮时启动计数都在增加。

使用此方法可用于使用按钮唤醒 ESP32,例如执行特定任务。但是,使用这种方法您只能使用一个 GPIO 作为唤醒源。

如果你想要不同的按钮,它们都可以唤醒 ESP,但执行不同的任务怎么办?为此,您需要使用 ext1 方法。

ext1

ext1 允许您使用不同的按钮唤醒 ESP,并根据您按下的按钮执行不同的任务。

而不是使用esp_sleep_enable_ext0_wakeup()功能,你使用esp_sleep_enable_ext1_wakeup()功能。在代码中,该函数被注释:

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

取消注释该功能,以便您拥有:

esp_sleep_enable_ext1_wakeup(BUTTON_PIN_BITMASK,ESP_EXT1_WAKEUP_ANY_HIGH);

该函数的第一个参数是您将用作唤醒源的 GPIO 的位掩码,第二个参数定义了唤醒 ESP32 的逻辑。

在这个例子中,我们使用变量BUTTON_PIN_BITMASK 按钮,这是在代码开头定义的:

这只是将一个引脚定义为唤醒源,GPIO 33. 您需要修改位掩码以将更多 GPIO 配置为唤醒源。

GPIO 位掩码

要获取 GPIO 位掩码,请执行以下步骤:

  1. 计算 2^(GPIO_NUMBER)。以小数形式保存结果;
  2. 将十进制数转换为十六进制数;
  3. 替换您在BUTTON_PIN_BITMASK 按钮多变的。

单个 GPIO 的掩码

为了让您了解如何获取 GPIO 位掩码,我们来看一个示例。在库中的代码中,按钮连接到GPIO 33. 获得面具GPIO 33:

1. 计算 2^33。你应该得到 8589934592 ;

2. 将该数字 (8589934592) 转换为十六进制。

3.将十六进制数复制到BUTTON_PIN_BITMASK 按钮变量,你应该得到:

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

多个 GPIO 的掩码

如果你想使用GPIO 2GPIO 15作为唤醒源,您应该执行以下操作:

  1. 计算 2^2 + 2^15。你应该得到 32772
  2. 将该数字转换为十六进制。你应该得到:8004
  3. 替换那个数字在BUTTON_PIN_BITMASK 按钮如下:
#define BUTTON_PIN_BITMASK 0x8004

识别用作唤醒源的 GPIO

当您使用多个引脚唤醒 ESP32 时,了解是哪个引脚引起了唤醒非常有用。为此,您可以使用以下功能:

esp_sleep_get_ext1_wakeup_status()

此函数返回一个以 2 为底的数字,以 GPIO 编号作为指数:2^(GPIO)。因此,要获得十进制的 GPIO,您需要进行以下计算:

GPIO = log(RETURNED_VALUE)/log(2)

外部唤醒——多个 GPIO

现在,您应该能够使用不同的按钮唤醒 ESP32,并确定是哪个按钮导致了唤醒。在这个例子中我们将使用GPIO 2GPIO 15作为唤醒源。

原理图

将两个按钮连接到 ESP32。在这个例子中我们使用GPIO 2GPIO 15, 但您可以将按钮连接到任何 RTC GPIO。

代码

您需要对我们之前使用的示例代码进行一些修改:

  • 创建要使用的位掩码GPIO 15GPIO 2. 我们之前已经向您展示了如何执行此操作;
  • 启用 ext1 作为唤醒源;
  • 使用esp_sleep_get_ext1_wakeup_status()函数获取触发唤醒的 GPIO。

下一个代码实现了所有这些更改。

/*
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
}

您在代码开头定义 GPIO 掩码:

#define BUTTON_PIN_BITMASK 0x8004 // GPIOs 2 and 15

您创建一个函数来打印导致唤醒的 GPIO:

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(2), 0);
}

最后,您启用 ext1 作为唤醒源:

esp_sleep_enable_ext1_wakeup(BUTTON_PIN_BITMASK,ESP_EXT1_WAKEUP_ANY_HIGH);

测试代码

有两个按钮连接到GPIO 2GPIO15,您可以上传提供给您的 ESP32 的代码。确保选择了正确的板和 COM 端口。

ESP32 现在处于深度睡眠模式。您可以通过按下按钮将其唤醒。

以 115200 的波特率打开串行监视器。按下按钮唤醒 ESP32。

你应该在串行监视器上得到类似的东西。

总结

        在本文中,我们向您展示了如何通过 ESP32 使用深度睡眠以及唤醒它的不同方法。您可以使用定时器、触摸引脚或更改 GPIO 状态来唤醒 ESP32。

猜你喜欢

转载自blog.csdn.net/m0_46509684/article/details/129117612
今日推荐