深度睡眠的實驗
深度睡眠的實驗
為什麼要讓ESP32進入深度睡眠模式?
其實我也是最近剛學到這一塊,所以就順手紀錄下來。
記得以前做過一些要電池的成品,發現放一天半左右就
沒電了,後來網路上搜尋相關知識才知道Arduino和esp32
它們都有使其進入深度睡眠的方法。
在深度睡眠中,可以使機板降低功耗,CPU和WIFI都會
停止運作,只有ULP還會以最低功耗運作,雖然 ESP32
處於深度睡眠模式,但 RTC 記憶體也仍然處於打開狀態,
因此我們可以為 ULP 共同處理器編寫一個程式,並將其
存儲在 RTC 記憶體中以訪問週邊設備、內部定時器和內
部感測器。
下圖黃色區塊的都可以使用RTC
#define us_to_s 1000000
#define time__to_sleep 5
RTC_DATA_ATTR int count = 0;
void print_wakeup_reason()
{
esp_sleep_wakeup_cause_t wakeup_reason;
wakeup_reason = esp_sleep_get_wakeup_cause();
switch (wakeup_reason)
{
case ESP_SLEEP_WAKEUP_EXT0:
Serial.println("Wakeup caused by external signal using RTC_IO");
break;
case ESP_SLEEP_WAKEUP_EXT1:
Serial.println("Wakeup caused by external signal using RTC_CNTL");
break;
case ESP_SLEEP_WAKEUP_TIMER:
Serial.println("Wakeup caused by timer");
break;
case ESP_SLEEP_WAKEUP_TOUCHPAD:
Serial.println("Wakeup caused by touchpad");
break;
case ESP_SLEEP_WAKEUP_ULP:
Serial.println("Wakeup caused by ULP program");
break;
default:
Serial.printf("Wakeup was not caused by deep sleep: %d\n", wakeup_reason);
break;
}
}
void setup()
{
Serial.begin(115200);
delay(1000);
++count;
Serial.println("boot num: " + String(count));
print_wakeup_reason();
esp_sleep_enable_timer_wakeup(us_to_s * time__to_sleep);
delay(1000);
esp_deep_sleep_start();
}
void loop()
{
}
一開始設定微秒轉成秒,也可以以直接寫成TIME_TO_SLEEP 5000000
#define us_TO_s 1000000
#define TIME_TO_SLEEP 5
這一段是說要在RTC上保存喚醒的次數,可以在最前面加上RTC_DATA_ATTR
*但是在按下EN鍵重啓這個數據會流失掉
RTC_DATA_ATTR int count = 0;
這個函式主要是設定"被換醒的原因"
void print_wakeup_reason(){
esp_sleep_wakeup_cause_t wakeup_reason;
wakeup_reason = esp_sleep_get_wakeup_cause();
switch(wakeup_reason){
case ESP_SLEEP_WAKEUP_EXT0 : Serial.println("Wakeup caused by external signal using RTC_IO"); break;
case ESP_SLEEP_WAKEUP_EXT1 : Serial.println("Wakeup caused by external signal using RTC_CNTL"); break;
case ESP_SLEEP_WAKEUP_TIMER : Serial.println("Wakeup caused by timer"); break;
case ESP_SLEEP_WAKEUP_TOUCHPAD : Serial.println("Wakeup caused by touchpad"); break;
case ESP_SLEEP_WAKEUP_ULP : Serial.println("Wakeup caused by ULP program"); break;
default : Serial.printf("Wakeup was not caused by deep sleep: %d\n",wakeup_reason); break;
}
}
進入到void setup(){}
設定序列埠的波特率
Serial.begin(115200);
每次被喚醒,count就會加1,並被印出來
++count;
Serial.println("Boot number: " + String(bootCount));
調用剛最前方那個被喚醒的原因函式
print_wakeup_reason()
啓用幾秒後,調用睡眠模式的函式
esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
esp_deep_sleep_start()
實驗結果
紅色字體是指進入深睡模式
土黃色字體是指被喚醒的次數
深藍色字體是被喚醒的原因
rst:0x5 (DEEPSLEEP_RESET),boot:0x17 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0018,len:4
load:0x3fff001c,len:1044
load:0x40078000,len:10124
load:0x40080400,len:5828
entry 0x400806a8
boot num: 2
Wakeup caused by timer
ets Jun 8 2016 00:22:57
rst:0x5 (DEEPSLEEP_RESET),boot:0x17 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0018,len:4
load:0x3fff001c,len:1044
load:0x40078000,len:10124
load:0x40080400,len:5828
entry 0x400806a8
boot num: 3
Wakeup caused by timer
ets Jun 8 2016 00:22:57
rst:0x5 (DEEPSLEEP_RESET),boot:0x17 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0018,len:4
load:0x3fff001c,len:1044
load:0x40078000,len:10124
load:0x40080400,len:5828
entry 0x400806a8
boot num: 4
Wakeup caused by timer
ets Jun 8 2016 00:22:57
2.觸摸喚醒實驗
後來我發現來在Arduino IDE裡切換到ESP32的模式下,範例裡就有DEEP SLEEP的範例可用
將範例載入後,上傳。
#define Threshold 40
RTC_DATA_ATTR int bootCount = 0;
touch_pad_t touchPin;
void print_wakeup_reason(){
esp_sleep_wakeup_cause_t wakeup_reason;
wakeup_reason = esp_sleep_get_wakeup_cause();
switch(wakeup_reason)
{
case ESP_SLEEP_WAKEUP_EXT0 : Serial.println("Wakeup caused by external signal using RTC_IO"); break;
case ESP_SLEEP_WAKEUP_EXT1 : Serial.println("Wakeup caused by external signal using RTC_CNTL"); break;
case ESP_SLEEP_WAKEUP_TIMER : Serial.println("Wakeup caused by timer"); break;
case ESP_SLEEP_WAKEUP_TOUCHPAD : Serial.println("Wakeup caused by touchpad"); break;
case ESP_SLEEP_WAKEUP_ULP : Serial.println("Wakeup caused by ULP program"); break;
default : Serial.printf("Wakeup was not caused by deep sleep: %d\n",wakeup_reason); break;
}
}
void print_wakeup_touchpad(){
touchPin = esp_sleep_get_touchpad_wakeup_status();
switch(touchPin)
{
case 0 : Serial.println("Touch detected on GPIO 4"); break;
case 1 : Serial.println("Touch detected on GPIO 0"); break;
case 2 : Serial.println("Touch detected on GPIO 2"); break;
case 3 : Serial.println("Touch detected on GPIO 15"); break;
case 4 : Serial.println("Touch detected on GPIO 13"); break;
case 5 : Serial.println("Touch detected on GPIO 12"); break;
case 6 : Serial.println("Touch detected on GPIO 14"); break;
case 7 : Serial.println("Touch detected on GPIO 27"); break;
case 8 : Serial.println("Touch detected on GPIO 33"); break;
case 9 : Serial.println("Touch detected on GPIO 32"); break;
default : Serial.println("Wakeup not by touchpad"); break;
}
}
void callback(){
}
void setup(){
Serial.begin(115200);
delay(1000);
++bootCount;
Serial.println("Boot number: " + String(bootCount));
print_wakeup_reason();
print_wakeup_touchpad();
touchAttachInterrupt(T4, callback, Threshold);
esp_sleep_enable_touchpad_wakeup();
Serial.println("Going to sleep now");
esp_deep_sleep_start();
Serial.println("This will never be printed");
}
void loop(){
}
程式碼裡面這個是給予觸摸觸發的值
#define Threshold 40
當在觸摸引腳上讀取的值低於 Threshold 變量上設置的值時,ESP32 喚醒並執行回調函數。
Callback() 函數只有在 ESP32 處於喚醒狀態時才會執行。
Callback() 函數只有在 ESP32 處於喚醒狀態時才會執行。
所以如果是在喚醒的狀態下壓著觸摸腳不放開,並不會執行callback()回調。
如果是在睡眠狀態下碰了一下引腳馬上放開,這樣也不會執行callback()回調。
touchAttachInterrupt(T3, callback, Threshold);
callback() 函數是空的
void callback(){
//placeholder callback function
}
接下來,使用 esp_sleep_enable_touchpad_wakeup() 函數將觸摸引腳設置為喚醒源。
esp_sleep_enable_touchpad_wakeup()
3.外部喚醒 (ext0)
要使用此喚醒,請使用以下函數:
Esp_sleep_enable_ext0_wakeup(GPIO_NUM_X,level)
此函數接受您要使用的引腳作為第一個參數,格式為 GPIO_NUM_X,其中 X 表示該引腳的 GPIO 編號。
第二個參數 level 可以是 1 或 0。這表示將觸發喚醒的 GPIO 狀態。
注意:使用此喚醒,只能使用 RTC GPIO 引腳。
可以在範例裡載入如下程式碼
/*Deep Sleep with External Wake Up=====================================This code displays how to use deep sleep withan external trigger as a wake up source and howto store data in RTC memory to use it over rebootsThis code is under Public Domain License.Hardware Connections======================Push Button to GPIO 33 pulled down with a 10K OhmresistorNOTE:======Only RTC IO can be used as a source for external wakesource. They are pins: 0,2,4,12-15,25-27,32-39.Author:Pranav Cherukupalli <cherukupallip@gmail.com>*/#define BUTTON_PIN_BITMASK 0x200000000 // 2^33 in hexRTC_DATA_ATTR int bootCount = 0;/*Method to print the reason by which ESP32has been awaken from sleep*/void print_wakeup_reason(){esp_sleep_wakeup_cause_t wakeup_reason;wakeup_reason = esp_sleep_get_wakeup_cause();switch(wakeup_reason){case ESP_SLEEP_WAKEUP_EXT0 : Serial.println("Wakeup caused by external signal using RTC_IO"); break;case ESP_SLEEP_WAKEUP_EXT1 : Serial.println("Wakeup caused by external signal using RTC_CNTL"); break;case ESP_SLEEP_WAKEUP_TIMER : Serial.println("Wakeup caused by timer"); break;case ESP_SLEEP_WAKEUP_TOUCHPAD : Serial.println("Wakeup caused by touchpad"); break;case ESP_SLEEP_WAKEUP_ULP : Serial.println("Wakeup caused by ULP program"); break;default : Serial.printf("Wakeup was not caused by deep sleep: %d\n",wakeup_reason); break;}}void setup(){Serial.begin(115200);delay(1000); //Take some time to open up the Serial Monitor//Increment boot number and print it every reboot++bootCount;Serial.println("Boot number: " + String(bootCount));//Print the wakeup reason for ESP32print_wakeup_reason();/*First we configure the wake up sourceWe set our ESP32 to wake up for an external trigger.There are two types for ESP32, ext0 and ext1 .ext0 uses RTC_IO to wakeup thus requires RTC peripheralsto be on while ext1 uses RTC Controller so doesnt needperipherals to be powered on.Note that using internal pullups/pulldowns also requiresRTC peripherals to be turned on.*/esp_sleep_enable_ext0_wakeup(GPIO_NUM_33,1); //1 = High, 0 = Low//If you were to use ext1, you would use it like//esp_sleep_enable_ext1_wakeup(BUTTON_PIN_BITMASK,ESP_EXT1_WAKEUP_ANY_HIGH);//Go to sleep nowSerial.println("Going to sleep now");esp_deep_sleep_start();Serial.println("This will never be printed");}void loop(){//This is not going to be called}
在這個例子中,我們使用了在代碼開頭定義的變量 BUTTON_PIN_BITMASK:
#define BUTTON_PIN_BITMASK 0x200000000 // 2^33 in hex
按鈕連接到 GPIO 33。要獲取 GPIO 33 的十六進位碼:
計算 2的33次方,應該得到 8589934592,將該數字 (8589934592) 轉換為十六進制。您可以轉到此轉換器來執行此操作。
計算 2的33次方,應該得到 8589934592,將該數字 (8589934592) 轉換為十六進制。您可以轉到此轉換器來執行此操作。
esp_sleep_enable_ext0_wakeup(GPIO_NUM_33,1); //1 = High, 0 = Low
#可以使用任何其他 RTC GPIO 引腳來代替 GPIO 33
4.外部喚醒 (ext1)
在這裡不使用esp_sleep_enable_ext0_wakeup(),而是使用
esp_sleep_enable_ext1_wakeup()
/*
Deep Sleep with External Wake Up
=====================================
This code displays how to use deep sleep with
an external trigger as a wake up source and how
to store data in RTC memory to use it over reboots
This code is under Public Domain License.
Hardware Connections
======================
Push Button to GPIO 33 pulled down with a 10K Ohm
resistor
NOTE:
======
Only RTC IO can be used as a source for external wake
source. They are pins: 0,2,4,12-15,25-27,32-39.
Author:
Pranav Cherukupalli <cherukupallip@gmail.com>
*/
#define BUTTON_PIN_BITMASK 0x8004 // GPIOs 2 and 15
RTC_DATA_ATTR int bootCount = 0;
/*
Method to print the reason by which ESP32
has been awaken from sleep
*/
void print_wakeup_reason(){
esp_sleep_wakeup_cause_t wakeup_reason;
wakeup_reason = esp_sleep_get_wakeup_cause();
switch(wakeup_reason)
{
case ESP_SLEEP_WAKEUP_EXT0 : Serial.println("Wakeup caused by external signal using RTC_IO"); break;
case ESP_SLEEP_WAKEUP_EXT1 : Serial.println("Wakeup caused by external signal using RTC_CNTL"); break;
case ESP_SLEEP_WAKEUP_TIMER : Serial.println("Wakeup caused by timer"); break;
case ESP_SLEEP_WAKEUP_TOUCHPAD : Serial.println("Wakeup caused by touchpad"); break;
case ESP_SLEEP_WAKEUP_ULP : Serial.println("Wakeup caused by ULP program"); break;
default : Serial.printf("Wakeup was not caused by deep sleep: %d\n",wakeup_reason); break;
}
}
/*
Method to print the GPIO that triggered the wakeup
*/
void print_GPIO_wake_up(){
uint64_t GPIO_reason = esp_sleep_get_ext1_wakeup_status();
Serial.print("GPIO that triggered the wake up: GPIO ");
Serial.println((log(GPIO_reason))/log(2), 0);
}
void setup(){
Serial.begin(115200);
delay(1000); //Take some time to open up the Serial Monitor
//Increment boot number and print it every reboot
++bootCount;
Serial.println("Boot number: " + String(bootCount));
//Print the wakeup reason for ESP32
print_wakeup_reason();
//Print the GPIO used to wake up
print_GPIO_wake_up();
/*
First we configure the wake up source
We set our ESP32 to wake up for an external trigger.
There are two types for ESP32, ext0 and ext1 .
ext0 uses RTC_IO to wakeup thus requires RTC peripherals
to be on while ext1 uses RTC Controller so doesnt need
peripherals to be powered on.
Note that using internal pullups/pulldowns also requires
RTC peripherals to be turned on.
*/
//esp_deep_sleep_enable_ext0_wakeup(GPIO_NUM_15,1); //1 = High, 0 = Low
//If you were to use ext1, you would use it like
esp_sleep_enable_ext1_wakeup(BUTTON_PIN_BITMASK,ESP_EXT1_WAKEUP_ANY_HIGH);
//Go to sleep now
Serial.println("Going to sleep now");
delay(1000);
esp_deep_sleep_start();
Serial.println("This will never be printed");
}
void loop(){
//This is not going to be called
}
0x8004怎麼來的?
計算 2^2 + 2^15。你應該得到 32772
將該數字轉換為十六進制。你應該得到:8004
在這個例子中,我們使用了在代碼開頭定義的變量 BUTTON_PIN_BITMASK
#define BUTTON_PIN_BITMASK 0x8004
當您使用多個引腳來喚醒 ESP32 時,知道是哪個引腳引起了喚醒是很有用的。為此,您可以使用以下功能:
esp_sleep_get_ext1_wakeup_status()
該函數返回一個基數2,與GPIO號碼作為指數:2 ^(GPIO_NUMBER)。因此,在小數得到GPIO,你需要做以下計算:
GPIO = log(GPIO_NUMBER)/log(2)
其它程式碼如同前面試驗
將程式碼上傳後可以看到按壓哪個GPIO會顯示在監測窗口
留言
張貼留言