ESP32 Deep Sleep のテスト (Hibernation mode)

 ESP32 の Deep Sleep が 27μA までしか落とせない・・・って 嘆いていた ところ、keynee さんから貴重なコメント を賜りました。
 結果として無事に 4μA@3.3V な Hibernation mode に突入させることに成功しましたので、他の方への参考になるよう記事に残します。

#include "esp_deep_sleep.h"
#include "soc/rtc_cntl_reg.h"
#include "soc/dport_reg.h"
#include "soc/i2s_reg.h"
#include "soc/sens_reg.h"
#include "soc/syscon_reg.h"

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200, SERIAL_8N1);
  Serial.println("Start");  

  esp_deep_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_OFF);
  esp_deep_sleep_pd_config(ESP_PD_DOMAIN_RTC_SLOW_MEM, ESP_PD_OPTION_OFF);
  esp_deep_sleep_pd_config(ESP_PD_DOMAIN_RTC_FAST_MEM, ESP_PD_OPTION_OFF);
  esp_deep_sleep_pd_config(ESP_PD_DOMAIN_MAX, ESP_PD_OPTION_OFF); 
}

void loop() {
  // put your main code here, to run repeatedly:
  delay(1000);
  Serial.println("good night!");

  SET_PERI_REG_BITS(RTC_CNTL_TEST_MUX_REG, RTC_CNTL_DTEST_RTC, 0, RTC_CNTL_DTEST_RTC_S);
  CLEAR_PERI_REG_MASK(RTC_CNTL_TEST_MUX_REG, RTC_CNTL_ENT_RTC);
  CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_FORCE_PU);

  esp_deep_sleep_enable_timer_wakeup(10 * 1000 * 1000);  // wakeup(restart) after 10secs
  esp_deep_sleep_start();

  Serial.println("zzz");  // ここは実行されない
}

 keynee さん直伝の秘技

  SET_PERI_REG_BITS(RTC_CNTL_TEST_MUX_REG, RTC_CNTL_DTEST_RTC, 0, RTC_CNTL_DTEST_RTC_S);
  CLEAR_PERI_REG_MASK(RTC_CNTL_TEST_MUX_REG, RTC_CNTL_ENT_RTC);
  CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_FORCE_PU);

の3連投をしたのちに esp_deep_sleep_start() させてやることで、見事に Hibernation mode に移行♪

4.0μA@3.3V 3.8μA@3.0V
http://dl.ftrans.etr.jp/?07f969c2ac6043bdb700ca4d4e71a6a1e81781cd.jpg http://dl.ftrans.etr.jp/?1bc2d1d65645481281eadd00608bb96d815487e3.jpg


 ほぼ全停止状態ではありますが RTC は生きてるので「指定時間後に再起動」だけは出来ます。
(上のサンプルだと10秒後に再起動)
 ESP8266 のときには、Deep Sleep から抜けて再起動させるときには、IO16 を RST ピンに繋いでおく必要がありましたが、ESP32 ではそーいう作法は必要なく、普通に再起動かかるようです。


 ESP8266 の Deep Sleep 10μA でも凄いのに、その半分以下の 4μA とは驚きですねー


(追記)2017/02/23
 Arduino-esp32 が更新され、特別な操作なく普通に deep sleep が活用できるようになった模様です。

#include "esp_deep_sleep.h"

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200, SERIAL_8N1);
  Serial.println("Start");  

  esp_deep_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_OFF);
  esp_deep_sleep_pd_config(ESP_PD_DOMAIN_RTC_SLOW_MEM, ESP_PD_OPTION_OFF);
  esp_deep_sleep_pd_config(ESP_PD_DOMAIN_RTC_FAST_MEM, ESP_PD_OPTION_OFF);
  esp_deep_sleep_pd_config(ESP_PD_DOMAIN_MAX, ESP_PD_OPTION_OFF); 
}

void loop() {
  // put your main code here, to run repeatedly:
  delay(1000);
  Serial.println("good night!");

  esp_deep_sleep_enable_timer_wakeup(10 * 1000 * 1000);  // wakeup(restart) after 10secs
  esp_deep_sleep_start();

  Serial.println("zzz");  // ここは実行されない
}

 TrueRMS テスターを使って、4.0μA@3.3V、3.8μA@3.0V を確認しました。



(追記)2017/02/26
 内蔵 ADC で電源電圧を測定し、低電圧をトリガーにして自発的に Hibernation mode(過放電防止モード)に移行する方法について記事にしました。
 詳しくは こちら をどうぞ