2021年5月25日 星期二

省電指南-ESP8266如何降低功耗


原廠參考文件
https://www.espressif.com/sites/default/files/documentation/9b-esp8266-low_power_solutions_cn.pdf


基於ESP8266的wemos D1開發板,需要定時讀取傳感器數據並上報記錄,由於該設備使用電池供電,所以希望最小化整個系統的功耗。

相信大家大部分的項目都不需要考慮系統功耗問題,插上插頭或者電腦USB口,代碼能順利跑起來就行了。但有些時候項目需要放置在室外或者其他沒有恆定供電源的條件下,系統一般採用乾電池、鋰電池或者太陽能等供電方式。這時候一節電池能撐一天還是一年,除了選擇更大容量的電池,系統的功耗就顯得至關重要了。那如果降低系統功耗呢?小編就以ESP8266開發板為例子來總結降低功耗的具體思路,希望對遇到類似問題的人有所幫助。

一個系統的功耗,即單位時間的耗電量。降低功耗跟整個系統的硬件設計和軟件設計都有關係,就像肉體和靈魂一樣,二者密不可分。有些人光注重精簡代碼,但硬件上有耗能大戶,再好的代碼也是徒勞;同樣,再完美的硬件也經不起爛代碼的折騰。所以,降低系統功耗要同時從硬件和軟件兩方面入手。

    硬件端:精簡元件,盡量選擇低功耗模組和最小化系統    

理論上,只要電路板一通電,板上所有的元件都在耗電,每個元件耗電量不同且能量的有效使用率也不一樣,比如有的元件耗能的80%是用於乾正事的,而其餘的20%都以熱量的形式散發掉了。最理想的情況下,我們當然希望能逐一挑選各部分的元件和封裝,每個元件盡可能低功耗高效率,且能使用最少數量的元件。但由於時間、工具和能力的限制,並不是每個人都能像專業電子工程師自己定制硬件。大部分時候,愛好者們的項目都是使用市面上的公版開發板。

儘管如此,我們在選擇開發板時還是有一定的選擇餘地的。就ESP8266而言,市面上的開發板/模組就超過了十多款。常見的如ESP-01、NodeMCU、wemos D1、D1 mini等等...即使讓每一款運行相同的點燈程序,它們的功耗也不盡相同。

那具體如何挑選呢?首先我們要大致了解學習了解每款開發板的佈局結構和功能特點。以wemos D1和D1 mini而言,除了大小區別,wemos D1比D1 mini多了外接電源管理部分。如果這一部分如果在你的項目中沒有用到,那它就是冗餘的耗能部分,應該去掉。

又比如NodeMCU,雖然跟D1 mini相似,都有串口驅動和5V轉3.3V的LDO線性穩壓器部分,但NodeMCU採用的LDO芯片是AMS1117,而D1 mini的LDO一般是RT9013。查看芯片的datasheet可以知道,AMS1117工作時的靜態電流明顯高於RT9013,這代表它的功耗也就更大。

另外,有些功能模塊比如串口驅動在系統工作時並不是必須的,只有在燒錄代碼或者debug時才用到,那麼是否可以去掉採用外接的USB轉串口模塊代替呢?

總之,我們可以根據自己的具體系統需求定制硬件部分,盡量做到“最少化”硬件,不多不少,讓每個元件都物盡其用。但大部分時候這個過程很難做到極致,是一個不斷權衡利弊的結果。

    代碼端:精簡功能,善用睡眠模式    

選定了硬件開發板,我們接下去就可以在軟件端來考慮如何進一步降低功耗了。其實,總體思路也很明確:裝死!能不干的活就不干,一定要幹的活少干,沒活干的時候就睡覺。

首先多看芯片手冊,具體了解系統芯片有沒有提供實現低功耗的功能。以ESP8266芯片為例,官方就提供了三種非常實用的低功耗運行的睡眠模式來滿足不同的需求:

Modem-sleep

Modem-sleep自動模式是ESP8266在WiFi STA(Station)模式下會自動開啟的模式,不要我們做任何設置。在STA模式下,ESP8266連接到無線路由器或者熱點,一般路由器會以一個特定時間間隔(DTIM beacon間隔)向網絡廣播信號,然後客戶端ESP8266接受完信號就可以休眠,直到下個間隔開啟再接受。因此,DTIM beacon間隔越久,ESP8266的Modem-sleep的休眠時間越久,也就越省電。但DTIM間隔時間一般是在路由器後台設置,ESP8266端並不能修改。⼀般路由器的DTIM Beacon間隔為100 ms ~ 1000 ms。

我們也可以強制開啟Modem-sleep模式,關閉WiFi射頻信號,這個功能在我們不需要WiFi功能的時候非常實用。

Light-sleep

Light-sleep模式與Modem-sleep相似,不同的是,除了關閉Wi-Fi模塊電路以外,在Light-sleep模式下,還會關閉內部時鐘並暫停CPU,⽐Modem-sleep 功耗更低。

Light-sleep模式也分自動和強制兩種模式。自動Light-sleep可⽤於需要保持與路由器的連接,可以實時響應路由器發來的數據的場合。在未接收到命令時,CPU處於空閒狀態。⽐如Wi-Fi開關的應⽤,⼤部分時間CPU都是空閒的,直到收到控制命令,CPU才需要進⾏GPIO的操作。

在強制Light-sleep模式下,CPU在暫停狀態下不會響應來⾃外圍硬件接⼝的信號與中斷,因此需要通過外部GPIO信號將ESP8266喚醒,硬件喚醒過程⼤約為3ms。由於Wi-Fi初始化過程還需要⼤約1ms,一般建議5ms之後再對芯⽚進⾏操作。一般代碼構造如下:

  1. //Force Light-sleep
  2. extern "C" {
  3.     #include "gpio.h"
  4. }
  5. extern "C" {
  6.     #include "user_interface.h"
  7. }
  8. void setup() {
  9.    Serial.begin(115200);
  10.    Serial.println();
  11.    gpio_init(); // Initilise GPIO pins
  12. }
  13. void loop() {
  14.   ...
  15.   delay(200);
  16.   Serial.println("Going to sleep now");
  17.   wifi_fpm_set_sleep_type(LIGHT_SLEEP_T); // set sleep type
  18.   wifi_fpm_open(); // Enables force sleep
  19.   wifi_enable_gpio_wakeup(GPIO_ID_PIN(12), GPIO_PIN_INTR_LOLEVEL); //set wakeup pin
  20.   wifi_fpm_do_sleep(0xFFFFFFF); // Sleep for longest possible time
  21.   delay(200);
  22.   Serial.println("Wake up");
  23.   ...
  24. }

Deep-sleep

Deep-sleep是比Modem-sleep和Light-sleep更節能的模式,它會關閉除了GPIO狀態和RTC之外的所有電路來最小化電流,最低僅為20uA。如果我們用1000mA的鋰電供電,那麼這個系統理論上可以工作:

T = 1000mAh / 20µA = 50,000小时 = 2083 天 = 5.7

Deep-sleep可以通過短接GPIO16針腳和RST針腳,代碼裡設定特定的時間自動喚醒,以NodeMCU開發板為例,我們可以這樣連接:

代碼構造如下:

  1. //Deep sleep
  2. void setup() {
  3.   Serial.begin(115200);
  4.   Serial.setTimeout(2000);
  5.   // 等待串口初始化
  6.   while(!Serial) { }
  7.   
  8.   Serial.println("I'm awake.");
  9.   Serial.println("Going into deep sleep for 20 seconds");
  10.   // 一但遇到以下方法ESP就会进入deepSleep状态
  11.   //ESP.deepSleep(time_in_us)
  12.   ESP.deepSleep(20e6); // 20e6 = 20 microseconds
  13. }
  14. void loop() {
  15. }

另外,Deep-sleep模式還支持外部喚醒,可以通過外部IO在RST針腳產生一個低電平脈衝喚醒。

Deep-sleep模式非常適合傳感器應⽤,或者⼤部分時間都不需要進⾏數據傳輸的情況。設備可以每隔⼀段時間從Deep-sleep狀態醒來測量數據並上傳,之後繼續進⼊Deep-sleep。也可以將多個數據存儲於RTC memory(RTC memory在Deep-sleep 模式下仍然可以保存數據),然後⼀次發送出去。

除了靈活運動以上三種睡眠模式,還有一些降低功耗的細節可以摳:

  • 比如可以在setup()裡把所有沒有用到的處於OUTPUT狀態的針腳腳改為INPUT狀態,消除針腳上的漏電,蚊子肉再小也是肉。

  • 另外如果項目中沒有用到ESP8266的WiFi功能,那可以在setup()里通過以下代碼關閉WiFi射頻。

  1. void setup() {
  2.   WiFi.mode( WIFI_OFF );
  3.   WiFi.forceSleepBegin();
  4.   delay( 1 );
  5.   ...
  6. }

 

資料來源: https://blog.csdn.net/tiandiren111/article/details/115410582

1 則留言:

匿名 提到...

ESP8266的WiFi功能你好我要買500個能與我聯繫嗎0935818740