【雕爷学编程】MicroPython手册之 ESP32 深度睡眠模式

在这里插入图片描述
MicroPython是为了在嵌入式系统中运行Python 3编程语言而设计的轻量级版本解释器。与常规Python相比,MicroPython解释器体积小(仅100KB左右),通过编译成二进制Executable文件运行,执行效率较高。它使用了轻量级的垃圾回收机制并移除了大部分Python标准库,以适应资源限制的微控制器。

MicroPython主要特点包括:
1、语法和功能与标准Python兼容,易学易用。支持Python大多数核心语法。
2、对硬件直接访问和控制,像Arduino一样控制GPIO、I2C、SPI等。
3、强大的模块系统,提供文件系统、网络、图形界面等功能。
4、支持交叉编译生成高效的原生代码,速度比解释器快10-100倍。
5、代码量少,内存占用小,适合运行在MCU和内存小的开发板上。
6、开源许可,免费使用。Shell交互环境为开发测试提供便利。
7、内置I/O驱动支持大量微控制器平台,如ESP8266、ESP32、STM32、micro:bit、掌控板和PyBoard等。有活跃的社区。

MicroPython的应用场景包括:
1、为嵌入式产品快速构建原型和用户交互。
2、制作一些小型的可 programmable 硬件项目。
3、作为教育工具,帮助初学者学习Python和物联网编程。
4、构建智能设备固件,实现高级控制和云连接。
5、各种微控制器应用如物联网、嵌入式智能、机器人等。

使用MicroPython需要注意:
1、内存和Flash空间有限。
2、解释执行效率不如C语言。
3、部分库函数与标准版有差异。
4、针对平台优化语法,订正与标准Python的差异。
5、合理使用内存资源,避免频繁分配大内存块。
6、利用原生代码提升速度关键部位的性能。
7、适当使用抽象来封装底层硬件操作。

总体来说,MicroPython让Python进入了微控制器领域,是一项重要的创新,既降低了编程门槛,又提供了良好的硬件控制能力。非常适合各类物联网和智能硬件的开发。
在这里插入图片描述
ESP32 是一款功能丰富的微控制器,集成了 Wi-Fi 和蓝牙连接功能,适合物联网开发的强大而实惠的平台。ESP32 的主要特点有:

1、处理器:CPU:Xtensa 双核(或单核)32 位 LX6 微处理器,工作频率为 160 或 240 MHz,性能可达 600 DMIPS。超低功耗(ULP)协处理器。
2、内存:520 KiB RAM,448 KiB ROM。
3、无线连接:Wi-Fi:802.11 b/g/n。蓝牙:v4.2 BR/EDR 和 BLE。
4、外设:12 位 SAR ADC 最多支持 18 个通道,2 个 8 位 DAC,10 个触摸传感器,4 个 SPI,2 个 I2S,2 个 I2C,3 个 UART,SD/SDIO/MMC 主机控制器,SDIO/SPI 从设备控制器,以太网 MAC 接口,CAN 总线 2.0,红外远程控制器,电机 PWM,LED PWM 最多支持 16 通道。
4、安全性:硬件加速 AES、SHA-2、RSA、ECC、随机数生成器(RNG)等。
5、可靠性:工作温度范围为 –40°C 到 +125°C。具有动态电压调整和时钟门控等功能,可适应外部条件的变化和降低功耗。
6、灵活性:可作为独立系统运行应用程序或作为主机 MCU 的从设备,通过 SPI / SDIO 或 I2C / UART 接口提供 Wi-Fi 和蓝牙功能。具有高度集成的天线开关、RF balun、功率放大器、低噪声放大器、滤波器和电源管理模块等。

在这里插入图片描述
深度睡眠模式是ESP32的一种低功耗模式,可以将CPU、内存和大部分外围设备关闭,只保留RTC控制器、RTC外设和RTC内存。在这种模式下,ESP32的电流消耗可以降低到几微安以下,适合需要长时间使用电池供电的应用场景。

深度睡眠模式的主要特点有:

1、可以使用machine模块中的deepsleep函数来进入深度睡眠模式。
2、可以在进入深度睡眠模式前指定一个超时时间,单位为毫秒。超时时间到达后,ESP32会自动重启。
3、可以使用esp32模块中的wake_on_ext0或wake_on_ext1函数来设置外部GPIO引脚作为唤醒源。这些引脚必须是RTC GPIO引脚,并且可以指定唤醒的电平条件。
4、可以使用machine模块中的reset_cause函数来获取重启的原因,判断是否是由深度睡眠模式唤醒。
5、可以使用machine模块中的wake_reason函数来获取唤醒的原因,判断是由哪个引脚或定时器触发的唤醒。

深度睡眠模式的应用场景有:

1、在需要节省电池寿命的情况下,使用深度睡眠模式来减少不必要的功耗,例如无线传感器网络、智能家居设备等。
2、在需要定期执行某些任务或操作的情况下,使用深度睡眠模式来作为一个简单的定时器,通过设置合适的超时时间和唤醒条件,实现周期性的触发和执行。
3、在需要在重启前执行某些清理或保存工作的情况下,使用esp32模块中的irq函数来创建一个由WDT触发的中断对象,并指定一个回调函数,在中断发生时执行。

深度睡眠模式需要注意的事项有:

1、在使用深度睡眠模式之前,需要先导入machine和esp32模块,并创建相应的对象和函数。
2、在使用深度睡眠模式时,需要注意合理地设置超时时间和唤醒条件,避免过于频繁或过于稀少地重启系统,影响系统性能和用户体验。
3、在使用深度睡眠模式时,需要注意在合适的位置保存数据和状态,因为进入深度睡眠模式后,内存和外围设备都会丢失数据和状态。

以下是MicroPython的ESP32 深度睡眠模式几个实际运用程序参考代码案例:

案例1:使用深度睡眠模式来监测一个可能会出现死循环的函数,并在出现异常时重启系统:

from machine import WDT, reset_cause, DEEPSLEEP_RESET
import time

# 创建一个可能会出现死循环的函数
def risky_function():
    # 生成一个随机数
    n = urandom.randint(0, 9)
    # 如果随机数是0
    if n == 0:
        # 进入死循环
        while True:
            pass
    # 如果随机数不是0
    else:
        # 打印随机数
        print(n)

# 创建一个WDT对象,并设置超时时间为5秒
wdt = WDT(timeout=5000)

# 判断是否是由深度睡眠模式唤醒
if reset_cause() == DEEPSLEEP_RESET:
    # 打印一条消息
    print('This is a deepsleep wake-up condition')

# 循环调用可能会出现死循环的函数
while True:
    # 调用函数
    risky_function()
    # 喂狗
    wdt.feed()
    # 等待1秒
    time.sleep(1)

案例2:使用深度睡眠模式来作为一个定时器,在每隔10秒钟打印一条消息:

from machine import deepsleep, reset_cause, DEEPSLEEP_RESET

# 判断是否是由深度睡眠模式唤醒
if reset_cause() == DEEPSLEEP_RESET:
    # 打印一条消息
    print('Hello, world!')

# 进入深度睡眠模式,设置超时时间为10秒
deepsleep(10000)

案例3:使用深度睡眠模式的中断功能,在重启前保存一些数据到文件中:

from machine import deepsleep, WDT, irq, reset_cause, DEEPSLEEP_RESET
import uos

# 创建一个WDT对象,并设置超时时间为10秒
wdt = WDT(timeout=10000)

# 定义一个回调函数,在中断发生时执行
def irq_handler(irq):
    # 打印一条消息
    print('WDT triggered!')
    # 打开一个文件
    f = uos.open('data.txt', 'w')
    # 写入一些数据
    f.write('Some important data')
    # 关闭文件
    f.close()

# 创建一个IRQ对象,由WDT触发
wdt.irq(trigger=WDT.ALARM0, handler=irq_handler)

# 判断是否是由深度睡眠模式唤醒
if reset_cause() == DEEPSLEEP_RESET:
    # 打印一条消息
    print('This is a deepsleep wake-up condition')

# 进入深度睡眠模式,不设置超时时间,等待WDT触发重启
deepsleep()

案例4:使用定时唤醒的深度睡眠模式:

import machine

# 配置定时唤醒的深度睡眠模式
wake_interval = 10  # 每隔10秒唤醒一次
rtc = machine.RTC()
rtc.irq(trigger=rtc.ALARM0, wake=machine.DEEPSLEEP)
rtc.alarm(rtc.ALARM0, wake_interval * 1000)

# 进入深度睡眠模式
machine.deepsleep()

这个示例演示了如何使用定时唤醒的深度睡眠模式。首先配置RTC实时时钟对象,通过设置wake_interval变量来指定唤醒的时间间隔(这里设置为10秒)。然后使用RTC的irq()方法配置唤醒触发事件为ALARM0,并使用alarm()方法设置定时唤醒的时间间隔。最后调用deepsleep()函数进入深度睡眠模式,ESP32会在每隔指定时间后自动唤醒。

案例5:使用外部中断唤醒的深度睡眠模式:

import machine

# 配置外部中断唤醒的深度睡眠模式
button_pin = machine.Pin(5, machine.Pin.IN, machine.Pin.PULL_UP)
rtc = machine.RTC()
rtc.irq(trigger=machine.Pin.IRQ_FALLING, wake=machine.DEEPSLEEP)

# 中断回调函数
def button_interrupt(pin):
    pass  # 在此处执行需要的操作

# 配置外部中断
button_pin.irq(trigger=machine.Pin.IRQ_FALLING, handler=button_interrupt)

# 进入深度睡眠模式
machine.deepsleep()

这个示例演示了如何使用外部中断唤醒的深度睡眠模式。首先配置一个外部中断引脚(这里使用引脚5作为示例),然后配置RTC实时时钟对象并设置唤醒触发事件为IRQ_FALLING,即引脚上的下降沿触发中断。定义一个中断回调函数button_interrupt(),在其中可以执行需要的操作。最后通过调用deepsleep()函数进入深度睡眠模式,当外部中断触发时,ESP32会被唤醒并执行中断回调函数。

案例6:使用内部定时器唤醒的深度睡眠模式:

import machine

# 配置内部定时器唤醒的深度睡眠模式
timer = machine.Timer(0)

# 定时回调函数
def timer_callback(timer):
    pass  # 在此处执行需要的操作

# 配置定时器
timer.init(period=10000, mode=machine.Timer.PERIODIC, callback=timer_callback)

# 进入深度睡眠模式
machine.deepsleep()

这个示例演示了如何使用内部定时器唤醒的深度睡眠模式。首先创建一个内部定时器对象(此处使用定时器0作为示例),然后定义一个定时回调函数timer_callback(),在其中可以执行需要的操作。通过调用定时器的init()方法来配置定时器的周期为10秒(这里使用10,000毫秒),模式为周期性触发(PERIODIC),并指定定时回调函数。最后通过调用deepsleep()函数进入深度睡眠模式,当定时器触发时,ESP32会被唤醒并执行定时回调函数。进入深度睡眠模式后,ESP32会暂时关闭大部分功能以节省能量,只有配置的唤醒事件发生时才会请注意,进入深度睡眠模式后,ESP32会暂时关闭大部分功能以节省能量,只有配置的唤醒事件发生时才会唤醒。具体的深度睡眠模式的配置和实际应用需根据具体的需求进行调整和扩展。

【雕爷学编程】MicroPython手册之 ESP32 深度睡眠模式_第1张图片

案例7:进入深度睡眠并设置唤醒引脚:

import machine

# 配置唤醒引脚
wake_pin = machine.Pin(14, machine.Pin.IN, machine.Pin.PULL_UP)

# 进入深度睡眠
machine.deepsleep(5000, wake=machine.Pin.WAKE_LOW, enable_pull=True)

在上述示例中,我们使用machine.Pin()初始化唤醒引脚,并将其配置为输入模式,并使用上拉电阻。然后,我们调用machine.deepsleep()进入深度睡眠模式。在这个例子中,ESP32将进入深度睡眠并保持睡眠状态5000毫秒,直到唤醒引脚(引脚14)的电平变为低电平,以唤醒ESP32。

案例8:进入深度睡眠并设置定时唤醒:

import machine
import utime

# 计算当前时间到下一个整点小时的时间差
current_time = utime.localtime()
next_hour = current_time[3] + 1
if next_hour > 23:
    next_hour = 0
next_hour_time = (current_time[0], current_time[1], current_time[2], next_hour, 0, 0, 0, 0)
time_diff = utime.mktime(next_hour_time) - utime.mktime(current_time)

# 进入深度睡眠并设置定时唤醒时间
machine.deepsleep(time_diff * 1000)

在上述示例中,我们使用utime.localtime()获取当前时间,并计算出距离下一个整点小时的时间差。然后,我们使用utime.mktime()将当前时间和下一个整点小时时间转换为时间戳,并计算时间差(以秒为单位)。最后,我们调用machine.deepsleep()进入深度睡眠模式,并将时间差乘以1000(转换为毫秒)作为参数,以设置定时唤醒。

案例9:进入深度睡眠并使用定时唤醒和RTC唤醒:

import machine

# 配置RTC唤醒时间
rtc = machine.RTC()
rtc.alarm(machine.RTC.ALARM0, 5000, repeat=False)  # 5000毫秒后唤醒一次

# 进入深度睡眠,设置定时唤醒和RTC唤醒
machine.deepsleep(0, wake=machine.DEEPSLEEP | machine.RTC_WAKE)

案例10:定期唤醒的传感器监测

import machine  
import time  
import ntptime  
  
# 设置GPIO为输入模式,用于连接传感器  
sensor_pin = machine.Pin(5, machine.Pin.IN)  
  
def internet_time():  
    ntptime.settime()  
    t = utime.localtime()  
    return t[3], t[4], t[5]  
  
def check_sensor():  
    if sensor_pin.value() == 1:  
        print('Sensor detected activity!')  
  
while True:  
    check_sensor()  
    hour, minute, second = internet_time()  
    # 在每天的特定时间进入深度睡眠模式  
    if hour == 2 and minute == 0 and second == 0:  
        print('Sleeping...')  
        machine.deep_sleep(60*60*24)  # 休眠24小时

案例11:远程唤醒的智能家居设备

import network  
import time  
import utime  
from machine import Pin  
import ntptime  
  
# 设置GPIO为输出模式,用于连接智能家居设备(例如LED灯)  
led = Pin(2, Pin.OUT)  
  
def internet_time():  
    ntptime.settime()  
    t = utime.localtime()  
    return t[3], t[4], t[5]  
  
def check_network():  
    wlan = network.WLAN(network.STA_IF)  
    if not wlan.isconnected():  
        print('Connecting to network...')  
        wlan.connect('YourSSID', 'YourPassword')  
        while not wlan.isconnected():  
            pass  
    print('Network connection successful')  
  
def wake_up():  
    led.on()  
    print('Woken up!')  
    led.off()  
    time.sleep(1)  # 等待1秒让LED灯亮起后熄灭  
    machine.deep_sleep(60*60)  # 休眠1小时  
  
while True:  
    check_network()  # 检查网络连接情况  
    hour, minute, second = internet_time()  # 获取当前时间  
    # 在每天的特定时间唤醒设备并检查网络连接情况,然后休眠一段时间以节省能源。  
    if hour == 8 and minute == 0 and second == 0:  # 例如在每天的8点唤醒设备。  
        wake_up()  # 唤醒设备并检查网络连接情况。

案例12:使用定时器唤醒ESP3212
这个例子展示了如何使用定时器在预设的时间间隔后唤醒ESP32。这个功能对于需要时间戳或定期任务的项目很有用,同时又能保持低功耗。
代码如下:

import machine

# 配置RTC.ALARM0能够唤醒设备
rtc = machine.RTC()
rtc.irq(trigger=rtc.ALARM0, wake=machine.DEEPSLEEP)

# 设置RTC.ALARM0在10秒后触发(唤醒设备)
rtc.alarm(rtc.ALARM0, 10000)

# 将设备置于深度睡眠模式
machine.deepsleep()

【雕爷学编程】MicroPython手册之 ESP32 深度睡眠模式_第2张图片

案例13:使用外部事件唤醒ESP3234
这个例子展示了如何使用外部事件(如按键)在引脚状态发生变化时唤醒ESP32。这个功能对于需要根据用户输入或传感器信号来执行任务的项目很有用。
代码如下:

import machine

# 定义一个按键引脚
button = machine.Pin(14, machine.Pin.IN)

# 配置外部中断能够唤醒设备
machine.wake_on_ext0(button, level=machine.WAKEUP_ANY_HIGH)

# 将设备置于深度睡眠模式
machine.deepsleep()

案例14:使用ULP协处理器唤醒ESP323
这个例子展示了如何使用ULP协处理器在设备处于深度睡眠模式时执行一些简单的任务,并根据条件唤醒ESP32。这个功能对于需要在低功耗状态下进行一些数据采集或处理的项目很有用。
代码如下:

import machine
import esp32

# 定义一个ADC引脚
adc = machine.ADC(machine.Pin(34))

# 配置ULP协处理器能够唤醒设备
esp32.wake_on_ulp(True)

# 加载ULP汇编代码
ulp_code = """
    move r3, 1500 # 设置一个阈值
    ld r2, r0, [0] # 读取ADC值
    cmp r2, r3 # 比较ADC值和阈值
    jumplt r2, r3, done # 如果ADC值小于阈值,跳转到done标签
    wake # 如果ADC值大于等于阈值,唤醒设备
    done:
    halt # 停止ULP协处理器
"""

# 编译ULP汇编代码并加载到内存中
esp32.ULP().set_wakeup_period(0, 100000) # 设置ULP协处理器的唤醒周期为100毫秒
esp32.ULP().load_assembly(ulp_code) # 加载ULP汇编代码

# 启动ULP协处理器并将设备置于深度睡眠模式
esp32.ULP().run()
machine.deepsleep()

案例15:使用machine模块的deepsleep()函数实现ESP32深度睡眠

import machine

# 初始化硬件
uart = machine.UART(1, baudrate=9600)
led = machine.Pin(2, machine.Pin.OUT)

# 主循环
while True:
    # 读取串口数据
    data = uart.read()
    print("Received data:", data)

    # 控制LED闪烁
    led.value(not led.value())
    machine.sleep(1)

    # 将ESP32设置为深度睡眠模式,单位为毫秒
    machine.deepsleep(60000)

案例16:使用esp32模块的esp32_sleep()函数实现ESP32深度睡眠

from esp32 import deep_sleep

# 初始化硬件
uart = machine.UART(1, baudrate=9600)
led = machine.Pin(2, machine.Pin.OUT)

# 主循环
while True:
    # 读取串口数据
    data = uart.read()
    print("Received data:", data)

    # 控制LED闪烁
    led.value(not led.value())
    machine.sleep(1)

    # 将ESP32设置为深度睡眠模式,单位为毫秒
    deep_sleep(60000)

案例17:使用time模块和esp32模块的esp32_sleep_mode()函数实现ESP32深度睡眠

import time
from esp32 import sleep_mode

# 初始化硬件
uart = machine.UART(1, baudrate=9600)
led = machine.Pin(2, machine.Pin.OUT)

# 主循环
while True:
    # 读取串口数据
    data = uart.read()
    print("Received data:", data)

    # 控制LED闪烁
    led.value(not led.value())
    time.sleep(1)

    # 将ESP32设置为深度睡眠模式,单位为毫秒
    sleep_mode(60000)

案例18::定时深度睡眠

import esp32

esp32.wake_on_ext0(pin=pin, level=esp32.WAKEUP_ALL_LOW)

while True:
  # do work
  print('Going into deep sleep')
  esp32.deepsleep(sleep_sec * 1000)

案例19:按键唤醒深度睡:

import esp32

wake = esp32.wake_on_ext0(pin=0, level=esp32.WAKEUP_ANY_HIGH) 

while True:
  # do work
  print('Sleeping...')
  wake.sleep(10000) 
  print('Woke up!')

案例20:深度睡眠降功耗

import esp32, time

while True:
  # send data
  time.sleep(10)
  
  # deep sleep to reduce power  
  print('Sleeping...')
  esp32.deepsleep(10 * 1000 * 1000)

在上述示例中,我们使用machine.RTC()初始化ESP32的RTC对象,并使用rtc.alarm()设置RTC唤醒时间,以5000毫秒后唤醒一次。然后,我们调用machine.deepsleep()进入深度睡眠模式,并将参数wake设置为machine.DEEPSLEEP | machine.RTC_WAKE,以启用定时唤醒和RTC唤醒。这将使ESP32在定时唤醒和RTC唤醒事件发生时被唤醒。

请注意,以上案例只是为了拓展思路,可能存在错误或不适用的情况。不同的硬件平台、使用场景和MicroPython版本可能会导致不同的使用方法。在实际编程中,您需要根据您的硬件配置和具体需求进行调整,并进行多次实际测试。确保正确连接硬件并了解所使用的传感器和设备的规范和特性非常重要。
【雕爷学编程】MicroPython手册之 ESP32 深度睡眠模式_第3张图片

你可能感兴趣的:(MicroPython手册,单片机,嵌入式硬件,物联网,python,MicroPython,ESP32,深度睡眠模式)