2022年2月3日 星期四

ESP8266 的睡眠模式

(一)ESP8266 的睡眠模式

如果您使用電池供電的 ESP8266 開發板製作了一個專案,或者只是將 ESP8266 NodeMCU 板連接到了移動電源。運行一段時間後,您會發現電池使用不了很長時間,特別是在使用 Wi-Fi 的情況下。如果將 ESP8266 設定為深度睡眠模式,則可以降低功耗,讓電池續航時間更長。讓 ESP8266 處於深度睡眠模式意味著可以減少一些在運行時會消耗更多功率的活動(例如 Wi-Fi)。

ESP8266 共有三種不同的睡眠模式:數據機睡眠 (modem sleep),輕度睡眠 (light sleep) 和深度睡眠 (deep sleep)。下表顯示了每種模式之間的差異(ESP8266數據表中的信息)。

它們各有不同的應用,在不同的應用程序中使用。

項目modem sleeplight sleepdeep sleep
WiFi
System clock
RTC
CPU待定
基板電流15mA0.4mA20uA
平均電流(DTIM=1)16.2mA1.8mA-
平均電流(DTIM=3)15.4mA0.9mA-
平均電流(DTIM=5)15.2mA0.55mA-

註:什麼是 DITM?

DTIM 是英文 Delivery Traffic Indication Message 縮寫,DTIM 用於傳統節電模式中,多點的套用,即由 AP 通過設定 DTIM 的間隔(預設是一個 beacon 時間,100ms),根據這個間隔傳送組播流量。

這個值不會影響單播的流量傳遞,如果沒有開啟 PS 的用戶使用組播也不會受到影響,但是會影響開啟了 PS 的用戶接收多播數據的傳遞,如果設定的太小,起不到節電作用,太大又可能會影響組播通訊的質量,這個過程是一個 trial-error 的調整過程,只能一個一個測試調整,以達到最佳,既可以達到最佳節電效果又不影回響用。

這裡,我們將介紹深度睡眠模式。除了即時時鐘(RTC),ESP8266 會一直跟踪時間,其他設定全部都是關閉狀態。

這是最省電的選擇,ESP 晶片僅消耗約 20uA 的電流。但是,如果您使用帶有內置編程器,LED 等的全功能開發板,則將無法實現低功耗狀態。

(二)深度睡眠作業流程

借助深度睡眠,應用程序範例如下所示:

  1. ESP8266 連接到 Wi-Fi
  2. ESP8266 執行任務(讀取感測器,發布 MQTT 消息等)
  3. 睡眠一段預定的時間
  4. ESP8266 喚醒
  5. 一遍又一遍地重複該過程

(三)喚醒方式

將ESP8266置於深度睡眠模式後,有多種喚醒方法:

  1. 定時器喚醒: ESP8266 在預定義的時間段後自行喚醒
    要將 ESP8266 置於深度睡眠模式,請使用 ESP.deepSleep(uS) 並以微秒為參數傳遞睡眠時間。GPIO 16 必須連接到復位(RST)引腳,ESP8266 才能喚醒。
  2. 外部喚醒:按 RST 按鈕時 ESP8266 喚醒(ESP8266 重新啟動)
    要將 ESP8266 置於深度睡眠模式並無限期睡眠,請使用 ESP.deepSleep(0)。當 RST 引腳接收到 LOW 信號時,ESP8266 將被喚醒。

要使用 ESP8266 的定時器喚醒功能,您需要在 NodeMCU 板中將 RST 引腳連接到標有 D0 的 GPIO 16 。參考下面的連接圖:

在上傳程式碼 ESP.deepSleep(uS) 後,再如上圖將 RST 引腳連接到 GPIO 16,即可實現在 ESP8266 進入深度睡眠後定時喚醒。

如果您看一下 NodeMCU 的引腳排列,您會發現 GPIO 16 是一個特殊的引腳,它具有喚醒功能。

ESP8266 運行時,ESP8266 的 RST 引腳始終為高電平。但是,當 RST 引腳接收到 LOW 信號時,它將重新啟動微控制器。

如果您使用 ESP8266 設置了深度睡眠計時器,則計時器結束後,GPIO 16 將發送 LOW 信號。這意味著,GPIO 16 連接到 RST 引腳後,可以在設定的時間後喚醒 ESP8266。

(四)ESP8266 NodeMCU 定時器喚醒範例

安裝了適""用於 Arduino IDE 的 ESP8266 插件(如何在 Arduino IDE 中安裝 ESP8266 板),轉到 “工具”,然後選擇 “NodeMCU(ESP-12E Module)” 。以下是範例程式:

void setup()
{
    Serial.begin(115200);
    Serial.setTimeout(2000);
    
    // 等待序列初始化。
    while(!Serial) { }
    
    // 深度睡眠模式設定 60 秒,ESP8266 自身喚醒,當 GPIO 16(在 NodeMCU 板 D0)連接到復位(RST)引腳時
    Serial.println("我醒了, 但我將進入深度睡眠模式60秒");
    ESP.deepSleep(60e6); 
    
    // 深睡眠模式直到復位引腳連接到 LOW 信號(例如按鈕或磁性簧片開關)
    //Serial.println("我醒了, 但我將進入深度睡眠模式直到 RESET 引腳收到 LOW 信號");
    //ESP.deepSleep(0);
}
      
void loop()
{
}

首先,我們在序列監視器中印出一條訊息:

Serial.println("我醒了, 但我將進入深度睡眠模式60秒");

之後,ESP8266 進入睡眠狀態達 60 秒鐘。

ESP.deepSleep(60e6); 

要使 ESP8266 處於深度睡眠狀態,請使用 ESP.deepsleep(uS) 並以毫秒為單位計算睡眠時間。

在這種情況下,60e6 對應於 60000000 微秒,等於 60 秒。

上傳程式碼後,按 RST 按鈕開始運行代碼,然後將 RST 連接到 GPIO16。ESP8266 應該每 60 秒喚醒一次,並在序列監視器中顯示一條訊息,如下所示。

該範例僅在序列監視器中印出一條消息,但是在實際應用程序中,您將執行一項有用的任務,例如發出請求,發布感測器讀數等。

(五)ESP8266 NodeMCU 外部喚醒範例

我們也可以通過外部喚醒功能來喚醒 ESP8266,例如按下按鈕或簧片開關。您只需要將 ESP8266 置於深度睡眠模式不確定的時間,然後將 RST 引腳設置為 LOW 即可將其喚醒。

要測試此設置,請按以下原理圖所示,將按鈕連接到 ESP8266 開發板上。當您按下按鈕時,RST 引腳變為低電平。

然後,將以下程式碼上傳到 ESP8266 開發板。

void setup()
{
    Serial.begin(115200);
    Serial.setTimeout(2000);
            
    // 等待序列初始化。
    while(!Serial) { }
            
    // 深度睡眠模式設定 60 秒,ESP8266 自身喚醒,當 GPIO 16(在 NodeMCU 板 D0)連接到復位(RST)引腳時
    // Serial.println("我醒了, 但我將進入深度睡眠模式60秒");
    // ESP.deepSleep(60e6); 
            
    // 深睡眠模式直到復位引腳連接到 LOW 信號(例如按鈕或磁性簧片開關)
    Serial.println("我醒了, 但我將進入深度睡眠模式直到 RESET 引腳收到 LOW 信號");
    ESP.deepSleep(0);
}
              
void loop()
{
}

將 ESP8266 置於不確定時間的深度睡眠模式。只需將 0 作為參數傳遞給沉睡功能:

ESP.deepSleep(0);

在這種情況下,僅有按下按鈕會將 RST 引腳拉至 GND,ESP8266 才會喚醒,執行已編程的任務,然後返回睡眠狀態,直到觸發新的重置事件為止。