由於 ESP32 內建了 Wifi 無線通訊,在正常無線通訊運作下,耗電流也是不小的數值,以電池供電的環境下,就需要低功耗模式的支援,讓 MCU 在閒置或處理輕量工作時,可以更省電,同時提升電池續航力。ESP32 晶片本身設計了多種的省電模式選擇,今天這篇就來看一下在 micropython ESP32 平台上,要怎麼進入所謂的休眠 DeepSleep 模式。
1. ESP32 低功耗模式介紹
查詢 ESP32 的設計參考手冊,可以發現 ESP32 的電源模式有5種:Active、Modem Sleep、Light Sleep、Deep Sleep、Hibernation, 相關的設定流程如下:(參考資料:ESP32 Datasheet)
這5種功耗模式都有不一應用的場景,具體來說:
- Active Mode: 就是一般操作模式,內部運作的時脈或模組都可以正常操作。
- Modem Sleep Mode: 如字面上的定義,就是把 wifi 或 bluetooth 模組關掉或受限,CPU 保持正常運作。
- Light Sleep Mode: CPU 開始暫停,記憶體與其他周邊進入受限制的狀態(clock-gate),但 RTC 和 ULP(協同處理器)保持 active,此模式可以將耗電流下降到 1mA 以下。
- Deep Sleep Mode: CPU、Memory、其他周邊全部進入 PowerOff,僅剩 RTC、RTC 記憶體、RTC 周邊(ULP)保持 Active,RTC 的內部電壓降到0.7V。
- Hibernate Mode:此狀態 RTC Timer 保持 Active,僅剩 RTC 或 限制的 IO 可以喚醒 CPU 運作。
回到我們今天想實作的 micropython ESP32平台,目前已經實踐的低功耗模式就是 Deep Sleep 模式,當我們在程式內執行後,搭配周邊電路的設計,是可以達到uA等級的低功耗。
2. ESP32 DeepSleep Mode 操作
>> 進入 Deep-Sleep Mode
怎麼讓 ESP32 進入 Deep-Sleep 模式? 相關的方法放在 machine 模組內, 所以只要 import machine,就可以進行下面的模式操作:
import machine machine.deepsleep(5000)
machine.deepsleep(5000) 參數的單位是 ms,也就是 5000ms 等於 5 秒,這段程序的意思就是讓 ESP32 進入低功耗模式 5 秒,在之後就重新起動(Restart),這邊需注意一下,進入 Deep-Sleep 後的 Restart,會讓程序從第一行開始執行,如果需要有區別時,可以利用下面的程序來判斷:
f machine.reset_cause() == machine.DEEPSLEEP_RESET: print("This is a deepsleep wake-up condition")
machine.reset_cause() 是一個回饋 reset 原因的方法,會有 5 種的回饋值,表示 PWRON_RESET、WDT_RESET 等相關因素,machine.DEEPSLEEP_RESET 就是表示此次開機為 DeepMode 喚醒重新起動 。
>> 喚醒 ESP32 的多種方式
剛剛我們的範例,是進入低功耗模式一定時間(5秒)後就回自行喚醒,這種方法就是 RTC(RealTimeClock) 喚醒, 因為在深度睡眠模式下,RTC Timer 仍保持運作,當 Timer 指定時間到達,即觸發 CPU Restart。
ESP32 喚醒除支援 RTC wakeup 外,還可以透過外部的 IO 腳位進行喚醒,這邊的腳位並不是任意 IO,而是標記為 RTC GPIO的腳位,怎麼確定那幾隻腳位是 RTC 的 GPIO 呢?最直覺的方法就是查閱 ESP32 的參考手冊:(下表擷取於 ESP32技術參考手冊 Page.56 表4.4)
表內就有 RTC GPIO 的編號,對應到一般我們在使用的 GPIO 編號,如果確認 OK 後就可以開始使用。
在來講一下外部IO喚醒方法,可以分為 ext0 跟 ext1,兩種喚醒最大的差別就在於 ext0 可以設定1支IO作為喚醒源,ext1 可以同時設定多支 IO 作為喚醒機制,下面為使用 ext0 外部觸發喚醒的範例:
import machine,esp32 from machine import Pin ext_p32= Pin(32, Pin.IN,Pin.PULL_UP) esp32.wake_on_ext0(pin = ext_p32, level = esp32.WAKEUP_ALL_LOW)
因為使用到 GPIO 控制的關係,所以除 esp32 外,再多匯入 Pin 類別,ext_p32 物件就是建立 GPIO32 的 Pin 物件,並指定為輸入腳位與預設內部會有 pull-high 電阻。
接下來設定 ext0 作為喚醒 CPU的來源,esp32.wake_on_ext0 內的 pin 參數指向 GPIO32 Pin 物件,level 是指觸發喚醒的準位,字面上定義來說,IO腳位 Low 或 High 都可以觸發,但因為我們剛剛已經設定 GPIO32 為 pull-high,預設腳位讀取值就是 High,所以這邊選用 esp32.WAKEUP_ALL_LOW ,一旦指定腳位是 LOW 立即喚醒CPU。
3. 休眠與喚醒測試
這次我們就使用 ESP32S 與 2 個外部按鈕來進行一個簡單的休眠與喚醒實驗。實驗很簡單,其中一顆用來進入休眠模式,另一顆則是用來喚醒 CPU。休眠按鈕一側接 GND,另一側接 GPIO13;喚醒用按鈕一側連接到 GND,一側連接 ESP32 的 GPIO32;同時利用 GPIO2 LED的亮暗來表示是否進入休眠模式。
>> 電路連接
備註:因 aithinker ESP32S 內建一個 LED 連接到 GPIO2,所以這邊就不額外接 LED。
>> 完整程式碼
import machine,esp32,time from machine import Pin led_p2=Pin(2,Pin.OUT) btn_p13=Pin(13,Pin.IN,Pin.PULL_UP) ext_p32=Pin(32, Pin.IN,Pin.PULL_UP) esp32.wake_on_ext0(pin = ext_p32, level = esp32.WAKEUP_ALL_LOW) led_p2.value(1) print('This is in the active mode now.') while 1: if btn_p13.value() == 0: print('The cpu is going to enter the deep-sleep mode after 5s , look at LED !') time.sleep(5) led_p2.value(0) machine.deepsleep() else : pass
>> 程式解說
import machine,esp32,time from machine import Pin led_p2=Pin(2,Pin.OUT) btn_p13=Pin(13,Pin.IN,Pin.PULL_UP) ext_p32=Pin(32, Pin.IN,Pin.PULL_UP) esp32.wake_on_ext0(pin = ext_p32, level = esp32.WAKEUP_ALL_LOW) led_p2.value(1) print('This is in the active mode now.')
首先匯入需要的 module,包含 esp32、machine 和 time, 接著設定連接 LED 的 GPIO2 為 OUTPUT,連接外部按鈕的GPIO32 與 GPIO13 為 INPUT。esp32.wake_on_ext0(pin = ext_p32, level = esp32.WAKEUP_ALL_LOW)
此程序設定 GPIO32 為外部喚醒腳位,當該腳位 LOW時,觸發喚醒機制。 led_p2.value(1) 將 LED點亮,並顯示現在狀態為 active mode 正常模式。
while 1: if btn_p13.value() == 0: print('The cpu is going to enter the deep-sleep mode after 5s , look at LED !') time.sleep(5) led_p2.value(0) machine.deepsleep() else : pass
再來這邊就利用 while 迴圈來進行一個等待進入休眠模式,一旦 GPIO13 連接的按鈕被按下(Low),等待5秒後,LED熄滅,開始進入 ESP32 的 Deep Sleep Mode,machine.deepsleep() 內如果沒有填入數字的話,就是直接進入無限期的休眠,直到有任何的喚醒觸發引起系統 Restart。
>> 執行結果
一切就緒後,當程式開始執行時,LED點亮,按下休眠按鈕(GPIO13),直到 LED變暗,整個 ESP32S 模組便會進入所謂的深度休眠模式,這個範例如果各位有電表時,可以將電源線的部分再”串接”電流表,就可以明顯看到正常模式跟休眠模式的電流消耗的差異。
按下喚醒按鈕後,所以 CPU 重新 Restart,開始新的一次循環。
Tips:
- 當系統從 deep-sleep 模式離開重新起動時,系統的執行動作會從 main.py 重新開始執行,所以如果要測試這個程式得將檔名存成 main.py 放入 ESP32 內。
- 由於 CPU 在 deep-sleep 模式周邊都會關閉,包括 UART等,所以這個狀態下無法中斷程式(Ctrl+C)或上傳程式碼,需切換到 active-mode 才可,各位朋友在留意一下。
4. 小結
休眠模式在嵌入式平台的設計中很常見也很實用,因為很多使用環境都是採用電池供電的,最大宗就是手持式的裝置或遠端感測應用,系統如剛好遇到閒置時,透過這些休眠模式的操作,大幅的減少更換電池的機會,在實際產品上,更多會搭配周邊電路的設計以達到省電最佳化。
以我們創客常使用的應用來說,最常用的就是遠端感測服務,因為某些遠端感測的資訊更新並不需要非常頻繁(如我們常用的 DHT11 溫濕度),30秒或是更長時間的更新即可,此時適當的加入休眠模式操作(指定休眠時間)便是更好的機制,各位朋友可以再參考自己手邊的專案斟酌變化即可囉!
今天的內容就到這邊,如果有遇到什麼問題或想看那些教學內容,也歡迎在下面留言或寫信與我討論囉~
↓↓↓↓↓↓賣場連結↓↓↓↓↓↓
歡迎大家有需要的話,可以多多支持一下我們的蝦皮賣場喔! 😀
吉米家官方店-創客機器人材料專賣 https://shopee.tw/jimirobot.tw
Follow JIMI哥 Twitter : https://twitter.com/jimirobot <–得到最新文章通知