Deep Sleep & Wake-up Sources

データロガー等バッテリー駆動の機器を製作する場合一番気になるのが消費電力です。通常はPowerSaveモードを使用して消費電力を抑えます。

PowerSaveモードからの復帰方法についてこのサイトを見つけました。ー>ESP32 Deep Sleep & Its Wake-up Sources。 このHPによると復帰方法(Wake-up)として下記の3つが代表的な方法の様です。

  • Timer
  • Touch pad
  • External wakeup(ext0 & ext1)

Timer

ESP32内のRTCタイマーを使う方法です。関数は、

  • esp_err_t esp_sleep_enable_timer_wakeup(uint64_t time_in_us)
    • 引数:time_in_usは、負号無し64ビットの数字
    • タイマーの単位はミクロ秒。
    • 2^64 マイクロ秒 → 約1.84x10^13秒 → 約5.1x10^9時間。かなり長い時間の指定が可能です。

サンプルスケッチも載っていました。


#define uS_TO_S_FACTOR 1000000  //Conversion factor for micro seconds to seconds
#define TIME_TO_SLEEP  5        //Time ESP32 will go to sleep (in seconds)

RTC_DATA_ATTR int bootCount = 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();

	//Set timer to 5 seconds
	esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
	Serial.println("Setup ESP32 to sleep for every " + String(TIME_TO_SLEEP) +
	" Seconds");

	//Go to sleep now
	esp_deep_sleep_start();
}

void loop(){}

//Function that prints 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 1  : Serial.println("Wakeup caused by external signal using RTC_IO"); break;
		case 2  : Serial.println("Wakeup caused by external signal using RTC_CNTL"); break;
		case 3  : Serial.println("Wakeup caused by timer"); break;
		case 4  : Serial.println("Wakeup caused by touchpad"); break;
		case 5  : Serial.println("Wakeup caused by ULP program"); break;
		default : Serial.println("Wakeup was not caused by deep sleep"); break;
	}
}
  • 4行:RTC_DATA_ATTR int bootCount = 0;
    • RTCのメモリーを使用する時の宣言です。
    • 通常のメモリーはDeepSleepに入ると消えてしまいますが、このRTCのメモリーは消えません
    • Bootの回数をカウントする変数として使用しています。
  • 11行:++bootCount;;
    • ここでBootの回数をカウント
  • 15行:print_wakeup_reason();
    • この関数は再起動したトリガーを表示する関数です。
  • 18行:esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
    • ここでタイマー復帰の設定を行っています。
    • 引数はSleep時間: 1000000 * 5 = 5000000マイクロ秒→5秒
  • 23行:esp_deep_sleep_start();
    • これがDeep Sleepを開始する関数
  • 31行:wakeup_reason = esp_sleep_get_wakeup_cause();
    • esp_sleep_get_wakeup_cause();が復帰のトリガーを返す関数
    • 戻り値は下のCaseで挙げられている5個の様ですが、全てに1足した値が正しい様です。

  switch(wakeup_reason)
  {
    case 2  : Serial.println("Wakeup caused by external signal using RTC_IO"); break;
    case 3  : Serial.println("Wakeup caused by external signal using RTC_CNTL"); break;
    case 4  : Serial.println("Wakeup caused by timer"); break;
    case 5  : Serial.println("Wakeup caused by touchpad"); break;
    case 6  : Serial.println("Wakeup caused by ULP program"); break;
    default : Serial.println("Wakeup was not caused by deep sleep"); break;
  }

正しいスケッチに書き換えてコンパイルして下さい。ー>この部分最新コードではwakeup_reasonが予約語に変更されていました。


  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"); break;
  }

数字より予約語を使う方が直感的に理解出来ます。各予約語と数字は対応しているので予約を使わないで数字を用いてもコードは同じ動作をします。

このコードを実行すると以下の様になります。

  1. 最初の1回目: Wakeup was not caused by deep sleep
    • 1回目はパワーオンですから、switch()のdefault:が有効になります。
    • esp_sleep_get_wakeup_cause();関数はパワーオン時は0を返す様です。
  2. 2回目以降:Wakeup caused by timer
    • ちゃんとタイマーにより復帰したと表示しています。

Touch Pad

Touch Padは使った事が無いので飛ばします。

ext0 External Wake-up Source

  • GPIOのピン 0,2,4,12-15,25-27,32-39が使用可能
  • 予めトリガー条件を設定し、GPIOピンがその値になったら復帰。
  • 関数は esp_err_t  esp_sleep_enable_ext0_wakeup(GPIO_PIN,LOGIC_LEVEL)
    • 1番目の引数は、GPIOのピン 0,2,4,12-15,25-27,32-39の番号
    • 2番目の引数は、1(high) , 0(low)

リンク先では下記の回路で試しています。

GPIO3ピンが1になったら復帰する様です。スケッチは


RTC_DATA_ATTR int bootCount = 0;

void setup(){
  Serial.begin(115200);
  delay(1000); 

  //Increment boot number and print it every reboot
  ++bootCount;
  Serial.println("Boot number: " + String(bootCount));

  //Print the wakeup reason for ESP32
  print_wakeup_reason();

  //Configure GPIO33 as ext0 wake up source for HIGH logic level
  esp_sleep_enable_ext0_wakeup(GPIO_NUM_33,1);

  //Go to sleep now
  esp_deep_sleep_start();
}

void loop(){}

//Function that prints 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 2  : Serial.println("Wakeup caused by external signal using RTC_IO"); break;
    case 3  : Serial.println("Wakeup caused by external signal using RTC_CNTL"); break;
    case 4  : Serial.println("Wakeup caused by timer"); break;
    case 5  : Serial.println("Wakeup caused by touchpad"); break;
    case 6  : Serial.println("Wakeup caused by ULP program"); break;
    default : Serial.println("Wakeup was not caused by deep sleep"); break;
  }
}

  • 15行:esp_sleep_enable_ext0_wakeup(GPIO_NUM_33,1);
    • ここで指定しています。

実行し、ボタンを押すと確かに、”Wakeup caused by external signal using RTC_IO”とモニタに表示されます。

ext1 External Wake-up Source

GPIOピン 32-39の8ポートを使用して幾つかのポートの組み合わせで復帰させるモードです。例題では、32,33ポートを使って復帰させています。

<<Before

Next>>