ESP32 系列芯片提供三种可配置的睡眠模式,针对这些睡眠模式,我们提供了了多种低功耗解决方案,用户可以结合具体需求选择睡眠模式并进行配置。三种睡眠模式如下:
三种模式的区别如下:
1.Modem-sleep 模式
目前 ESP32 的 Modem-sleep 仅工作在 Station 模式下,连接路由器后生效。Station 会周期性在工作状态和睡眠状态两者之间切换。
Modem-sleep 一般用于 CPU 持续处于工作状态并需要保持 Wi-Fi 连接的应用场景,例如,使用 ESP32 本地语音唤醒功能,CPU 需要持续采集和处理音频数据。
2.Light-sleep 模式
Light-sleep 的工作模式与 Modem-sleep 相似,不同的是,除了关闭 Wi-Fi 模块电路以外,在 Light-sleep 模式下,还会关闭时钟并暂停内部 CPU,比 Modem-sleep 功耗更低。
3.Deep-sleep 模式
相对于其他两种模式,系统无法自动进入 Deep-sleep,需要由用户调用接口函数 esp_deep_sleep_start() 进入 Deep-sleep 模式。在该模式下,芯片会断开所有 Wi-Fi 连接与数据连接,进入 Deep-sleep 模式,只有 RTC 存储器和 RTC 外设以及 ULP 协处理器可以工作。从 Deep-sleep 唤醒后,CPU 将软件复位重启。
Deep-sleep 可以用于低功耗的传感器应用,或者大部分时间都不需要进行数据传输的情况。设备可以每隔一段时间从 Deep-sleep 状态醒来测量数据并上传,之后继续进入 Deep-sleep。也可以将多个数据存储于 RTC memory(RTC memory 在 Deep-sleep 模式下仍然可以保存数据),然后一次发送出去。
使用machine模块,你可以轻而易举的设置CPU的运行频率:
import machine
machine.freq() # 查看当前的CPU运行频率
machine.freq(160000000) # 设置CPU运行频率至 160 MHz
ESP32默认工作在240MHz的主频下,它拥有三个可调的频率挡位:
80MHz
160MHz
240MHz
越低的运行主频意味着性能的下降,但同时也意味着更低的功耗,适用于计算力需求低,长续航的任务。
反之,越高的主频,提升了性能的同时意味着更高的功耗。实际应用中,大家按照需求,自行取舍。
有时候我们需要使用休眠模式来为设备节省功耗,保证续航。
ESP32进入休眠模式后,除了RTC的时钟电路不掉电继续工作外,其余各电路模块都将掉电.
注意
进入休眠模式也意味着你将失去网络连接,无法连接到WebREPL和EMP-IDE甚至是通过串口连接的REPL,直到休眠模式被唤醒或者重启复位
import machine
machine.deepsleep() # 休眠,直到被人为唤醒
machine.deepsleep(5000) # 休眠5S
因此,当ESP32从休眠模式醒来时,相当于重启,不同之处在于:
普通的重启RTC会恢复至初始点
休眠时RTC不会被关闭,因此芯片醒来之后,RTC是正确的时间。
当ESP32进入休眠模式后,很多时候我们希望能够人为的唤醒它。
我们有四种方式来唤醒ESP32:
RTC Timer 唤醒模式
EXT0 唤醒模式
EXT1 唤醒模式
TouchPad 唤醒模式
接下来,我们分别对前三种模式进行详细的阐述。
这是最简单的唤醒模式,这种方式其实我们上文的代码中就已经涉及:
import machine
machine.deepsleep() # 休眠,直到被人为唤醒
machine.deepsleep(5000) # 休眠5S
这里的deepsleep()函数本身可以接收一个休眠时间的参数,单位是毫秒,当该时间被计时器计时完成,便会触发唤醒。
在进行接下来的三种唤醒模式之前,你需要先了解什么是RTC GPIO
你可能并不清楚什么是RTC GPIO, 简而言之,RTC GPIO也属于GPIO,只不过他们特殊的地方在于,RTC GPIO和RTC时钟模块相连,因此在低功耗睡眠模式下,这些RTC GPIO才能够保证输入和输出信号能够被检测到,因此,只有RTC GPIO才能够唤醒ESP32 。
NodeMCU-32S上,GPIO 总共有32个。
ESP32上,RTC GPIO有18个,拥有自己的一套独立的RTC GPIO编号,0-17
NodeMCU-32S上,引出的RTC GPIO共有16个:
EXT0唤醒模式,允许用户配置 一个 RTC GPIO, 来唤醒ESP32。
只有具备RTC GPIO功能的GPIO才能够被配置用以唤醒。
我们可以在GPIO上使用中断的方式来触发唤醒, 其中:
trigger有两种触发方式:
Pin.WAKE_HIGH高电平触发
Pin.WAKE_LOW低电平触发
我们以高电平触发唤醒为例(大部分引脚默认都是低电平,所以WAKE_LOW触发会立即执行),在GPIO27上接入一个按钮。
>>> from machine import Pin
>>> import machine
>>> wake_pin = Pin(27,Pin.IN) # GPIO27 支持 RTC GPIO
>>> wake_pin.irq(trigger=Pin.WAKE_LOW, wake=machine.DEEPSLEEP) # 配置唤醒中断
>>> machine.deepsleep() # 开始睡眠
当按下按钮的时候,ESP32就苏醒(重启)了。
在这种模式下,允许用户配置一个或者多个RTC GPIO 作为唤醒源, 在一个或者多个 RTC GPIO 存在任意一个高电平或者同时为低电平时唤醒。
我们可以使用GPIO26 , GPIO27同时按下时将其唤醒。
按照上面的GPIO中断进行配置的话,
pin1.irq(trigger=Pin.IRQ_LOW_LEVEL, wake=machine.DEEPSLEEP) # configures ext0
pin2.irq(trigger=Pin.IRQ_HIGH_LEVEL, wake=machine.DEEPSLEEP) # configures ext1 with "any high"
pin3.irq(trigger=Pin.IRQ_HIGH_LEVEL, wake=machine.DEEPSLEEP) # reconfigures ext1 with "any high" with pin2 and pin3
pin4.irq(trigger=Pin.IRQ_LOW_LEVEL, wake=machine.DEEPSLEEP) # raises an exception, no resources left
所以还好我们有另外一种方式进行配置——esp32模块:
import esp32
esp32.wake_on_ext1(pins=(...), level=...) # 这样就简单很多了
pins是一个元组,传入配置的多个RTC GPIO引脚
level有以下两个选项:
WAKEUP_ANY_HIGH任意一个RTC GPIO高电平即可唤醒
WAKEUP_ALL_LOW所有RTC GPIO低电平时触发唤醒
笔者测试时使用 GPIO26(RTC GPIO7) GPIO27(RTC GPIO17)
使用WAKEUP_ANY_HIGN的选项进行测试(WAKEUP_ALL_LOW模式需要外部电路的支持,不然大部分引脚默认都是低电平,所以会立即触发唤醒),在这种模式下,我按下下图中的黑色或原谅色按钮,都可以唤醒
>>> import esp32
>>> import machine
>>> esp32.wake_on_ext1(pins=(Pin(26),Pin(27)),level=esp32.WAKEUP_ALL_LOW)
>>> machine.deepsleep()
既然存在休眠被唤醒的情况,那么很多时候用户就需要知道当前重启是由于何种原因,以便决策启动之后的工作。
在machine模块中,包含了以下两个函数,可以让我们对重启和唤醒的原因进行侦查:
reset_cause查看重启原因
wake_reason查看唤醒原因
这些数值,与machine模块中的宏定义有着一一对应的关系:
重启原因的宏定义 | 数值 | 含义 |
---|---|---|
PWRON_RESET | 1 | 上电重启 |
HARD_RESET | 2 | 硬重启 |
WDT_RESET | 3 | 看门狗计时器重启 |
DEEPSLEEP_RESET | 4 | 从休眠重启 |
SOFT_RESET | 5 | 软重启 |
唤醒原因的宏定义 | 数值 | 含义 |
---|---|---|
PIN_WAKE EXT0_WAKE | 1 | 单个RTC_GPIO唤醒 |
EXT1_WAKE | 2 | 多RTC_GPIO唤醒 |
TIMER_WAKE | 3 | 定时器唤醒 |
TOUCHPAD_WAKE | 4 | 触摸唤醒 |
ULP_WAKE | 5 | 协处理器唤醒 |
目前为止,笔者在测试的过程中,发现我们无论是使用machine.reset()函数进行软重启,还是按开发板上的reset按键进行重启,machine.reset_cause()的数值都是5即对应machine.SOFT_RESET
当开发板从休眠模式唤醒后,重启原因是4即machine.DEEPSLEEP_RESET
ESP32最常见的重启原因,无非也就以上两种了。
所以要想判断ESP32是从休眠中醒来还是正常的按键重启或是machine.reset()函数的重启,我们只需在开机后通过machine.reset_cause()函数来进行判断,如果是从睡眠中唤醒,那么进而可以继续判断唤醒的原因:
if machine.reset_cause() == machine.SOFT_RESET:
print('normal reboot')
# do something
elif machine.reset_cause() == machine.DEEPSLEEP_RESET:
print('reboot from deepsleep')
# 进而可以继续判断 是由于什么原因导致的唤醒
if machine.wake_reason() == machine.PIN_WAKE:
# do something
pass
elif machine.wake_reason() == machine.EXT1_WAKE:
# do something else...
pass
# ......
PID控制算法是结合比例、积分和微分三种环节于一体的控制算法,它是连续系统中技术最为成熟、应用最为广泛的一种控制算法。
本文介绍ESP32中的中断机制,以及如何通过GPIO中断实现按钮控制。重点讲解了如何设置中断服务例程、处理中断抖动问题,并提供了消除中断抖动的示例代码。
本文主要介绍在未联网(AP热点)情况下实现WEB交互界面的CSS和javascript库。
本文介绍如何使用Arduino-ESP32库中的API函数获取ESP32的芯片、RAM信息等,并提供了一个示例程序代码。
ESP32系列(包括ESP32-S3)搭载Xtensa双核处理器,默认情况下Arduino框架仅使用单核运行用户代码,通过多核编程,可以充分利用硬件资源来提升系统响应和性能。
ESP32 芯片有34个物理GPIO管脚。每个GPIO管脚都可用作一个通用IO,或连接一个内部的外设信号。IO_MUX ¹、RTC IO MUX 和GPIO交换矩阵用于将信号从外设传输至GPIO管脚。
ESP32Encoder库是一个利用ESP32脉冲计数器硬件外设实现高效旋转编码器读取的软件库。
本文对比了几款适合物联网开发的盒子硬件参数,供大家参考。
乐动掌控采用掌控板作为主控,塑胶一体式外壳,侧面和底面开具多个乐高扩展孔位,兼容乐高积木,可完成多种创意应用。
在MicroPython的ESP32库中,NVS类用于管理非易失性存储,支持 32 位有符号整数和 二进制blob。
umqtt 是 MicroPython 的一个轻量级 MQTT 客户端库,使得在微控制器上使用 MQTT 协议变得简单易行。本文将介绍 umqtt 的实用方法,帮助您更好地在项目中应用这一技术。