<button id="ssm6u"><optgroup id="ssm6u"></optgroup></button>
  • 跳轉至

    功耗控制

    概要

    本節內容為大家講解ESP32的功耗控制方法。

    ESP32工作頻率

    使用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 喚醒模式

    接下來,我們分別對前三種模式進行詳細的闡述。

    RTC Timer 喚醒模式

    這是最簡單的喚醒模式,這種方式其實我們上文的代碼中就已經涉及:

    import machine
    machine.deepsleep() # 休眠,直到被人為喚醒
    machine.deepsleep(5000) # 休眠5S
    

    這里的deepsleep()函數本身可以接收一個休眠時間的參數,單位是毫秒,當該時間被計時器計時完成,便會觸發喚醒。

    RTC GPIO

    在進行接下來的三種喚醒模式之前,你需要先了解什么是RTC GPIO

    你可能并不清楚什么是RTC GPIO, 簡而言之,RTC GPIO也屬于GPIO,只不過他們特殊的地方在于,RTC GPIORTC時鐘模塊相連,因此在低功耗睡眠模式下,這些RTC GPIO才能夠保證輸入和輸出信號能夠被檢測到,因此,只有RTC GPIO才能夠喚醒ESP32 。

    NodeMCU-32S上,GPIO 總共有32個。

    ESP32上,RTC GPIO有18個,擁有自己的一套獨立的RTC GPIO編號,0-17

    NodeMCU-32S上,引出的RTC GPIO共有16個:

    ?

    EXT0喚醒模式

    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就蘇醒(重啟)了。

    EXT1 喚醒模式

    在這種模式下,允許用戶配置一個或者多個RTC GPIO 作為喚醒源, 在一個或者多個 RTC GPIO 存在任意一個高電平或者同時為低電平時喚醒。

    我們可以使用GPIO26 , GPIO27同時按下時將其喚醒。

    按照上面的GPIO中斷進行配置的話,正如在ESP32-MicroPython的Github倉庫ISSUE里開發者們所討論的那樣

    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

    當開發板從休眠模式喚醒后,重啟原因是4machine.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
        # ......
    

    韩国精品无码一区二区三区,精品无码一区二区三区AV,欧洲丰满美熟女乱又伦AV,亚洲午夜久久久影院伊人