XIAO ESP32S3 Sense スリープモード

ここでは、これらの低消費電力スリープモードの使い方を示すために、いくつかの簡単な例を紹介します。すべての ESP32 ボードは汎用性がありますが、ここで使用している開発ボードは XIAO ESP32S3 Sense です。
ハードウェア概要
| Seeed Studio XIAO ESP32S3 Sense |
|---|
![]() |
Deep-Sleep
概要
Deep-Sleep モードでは、ESP32 は CPU、RAM の大部分、および APB_CLK からクロック供給されるすべてのデジタルペリフェラルの電源をオフにします。電源が維持されるコンポーネントは次のとおりです:
- RTC コントローラ
- ULP コプロセッサ
- RTC FAST メモリ
- RTC SLOW メモリ
Deep Sleep 中の USB ペリフェラル無効化: 内蔵 USB ペリフェラル(USB-Serial-JTAG)を含むすべてのデジタルペリフェラルは Deep Sleep 中に電源がオフになります。デバイスが Deep Sleep 中は USB 経由のシリアル出力は利用できません。 デバッグが必要な場合は、ハードウェア UART ピンに接続した外部 USB-UART チップを使用してください。
ウェイクアップ方法
-
タイマーウェイクアップ: ESP32 は、タイマーを設定することで、指定した時間が経過すると自動的にウェイクアップできます。
-
タッチパッド割り込みウェイクアップ: デバイスはタッチパッド上の動作によって起動でき、ユーザー操作が必要なアプリケーションに適しています。
-
外部ウェイクアップ: ESP32 は外部信号(例:ボタン押下)によってウェイクアップでき、低消費電力アプリケーションに最適です。
-
ULP コプロセッサ動作によるウェイクアップ: ULP コプロセッサは独立して動作し、特定の条件を監視してメイン CPU をウェイクアップできるため、電力を節約できます。
-
GPIO ウェイクアップ: デバイスは GPIO ピン状態(High または Low)の変化によってウェイクアップでき、さまざまなセンサやペリフェラルに柔軟に対応できます。
以下に、DeepSleep モードを使用する XIAO ESP32 S3 Sense の簡単な例を 3 つ示します。
コード実装
- TimerWakeUP
- ExternalWakeUp
- タッチウェイクアップ
- SmoothBink_ULP
#define uS_TO_S_FACTOR 1000000ULL
#define TIME_TO_SLEEP 5
RTC_DATA_ATTR int bootCount = 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);
++bootCount;
Serial.println("Boot number: " + String(bootCount));
print_wakeup_reason();
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");
Serial.println("Going to sleep now");
Serial.flush();
esp_deep_sleep_start();
Serial.println("This will never be printed");
}
void loop() {
}
詳細な説明
#define uS_TO_S_FACTOR 1000000ULL
- マクロを定義してマイクロ秒を秒に変換します。1000000ULL はマイクロ秒を秒に変換するために使用される係数です。
#define TIME_TO_SLEEP 5
- ESP32 がスリープする時間を設定するマクロを定義します。この例では 5 秒です。
RTC_DATA_ATTR int bootCount = 0;
RTC_DATA_ATTR属性を持つ整数変数bootCountを宣言します。これにより、Deep Sleep 中も値が保持されます。
void print_wakeup_reason() {
- ESP32 がウェイクアップした理由を出力する
print_wakeup_reason()という名前の関数を定義します。
esp_sleep_wakeup_cause_t wakeup_reason;
- ウェイクアップイベントの原因を保存するために、
esp_sleep_wakeup_cause_t型の変数wakeup_reasonを宣言します。
wakeup_reason = esp_sleep_get_wakeup_cause();
- 関数
esp_sleep_get_wakeup_cause()を呼び出してウェイクアップ理由を取得し、その結果を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", wakeup_reason); break;
}
ESP_SLEEP_WAKEUP_EXT0: このウェイクアップ理由は、RTC(リアルタイムクロック)I/O 用に設定された GPIO ピンで検出された外部信号によって ESP32 がウェイクアップしたことを示します。これは通常、ボタンやセンサがトリガされたときにスリープから復帰する用途に使用されます。ESP_SLEEP_WAKEUP_EXT1: これは、RTC コントローラによって管理される GPIO ピン上の外部信号によってウェイクアップが発生したことを示します。EXT0 と異なり、EXT1 は複数のピンを扱うことができ、指定されたピンのいずれかの状態が変化したとき(例:Low または High になる)にウェイクアップできます。ESP_SLEEP_WAKEUP_TIMER: このウェイクアップ理由は、あらかじめ設定されたタイマー時間が経過した後に ESP32 がウェイクアップしたことを示します。ユーザー操作を必要とせずに定期的なタスクを実行する必要があるアプリケーションに有用です。ESP_SLEEP_WAKEUP_TOUCHPAD: これは、タッチパッドイベントによって ESP32 がウェイクアップしたことを示します。ウェイクアップ用に設定されたタッチパッドがタッチを検出すると、デバイスをスリープモードから復帰させることができます。ESP_SLEEP_WAKEUP_ULP: このウェイクアップ理由は、ULP(Ultra-Low Power)プログラムによってウェイクアップがトリガされたことを意味します。ULP はメイン CPU が Deep Sleep 中でも動作でき、特定の条件が満たされたときに ESP32 をウェイクアップできるため、バッテリー消費を最小限に抑えた低消費電力動作が可能になります。
++bootCount;
- ブート回数をインクリメントし、デバイスが再起動するたびにその値を出力します。
print_wakeup_reason();
- ESP32 のウェイクアップ理由を出力します。
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");
Serial.println("Going to sleep now");
Serial.flush();
esp_deep_sleep_start();
Serial.println("This will never be printed");
esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);ESP32 が指定時間後にタイマーでウェイクアップするように有効化します。Serial.flush();スリープに入る前に、すべてのシリアルデータが送信されるようにします。esp_deep_sleep_start();ESP32 を Deep Sleep モードに移行させます。
#include "driver/rtc_io.h"
#define BUTTON_PIN_BITMASK(GPIO) (1ULL << GPIO)
#define USE_EXT0_WAKEUP 1
#define WAKEUP_GPIO GPIO_NUM_33
RTC_DATA_ATTR int bootCount = 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);
++bootCount;
Serial.println("Boot number: " + String(bootCount));
print_wakeup_reason();
#if USE_EXT0_WAKEUP
esp_sleep_enable_ext0_wakeup(WAKEUP_GPIO, 1);
rtc_gpio_pullup_dis(WAKEUP_GPIO);
rtc_gpio_pulldown_en(WAKEUP_GPIO);
#else
esp_sleep_enable_ext1_wakeup_io(BUTTON_PIN_BITMASK(WAKEUP_GPIO), ESP_EXT1_WAKEUP_ANY_HIGH);
rtc_gpio_pulldown_en(WAKEUP_GPIO);
rtc_gpio_pullup_dis(WAKEUP_GPIO);
#endif
Serial.println("Going to sleep now");
esp_deep_sleep_start();
Serial.println("This will never be printed");
}
void loop() {
}
詳細な説明
#include "driver/rtc_io.h"
- RTC GPIO にアクセスするために RTC I/O ドライバをインクルードします。
#define BUTTON_PIN_BITMASK(GPIO) (1ULL << GPIO)
#define USE_EXT0_WAKEUP 1
#define WAKEUP_GPIO GPIO_NUM_33
RTC_DATA_ATTR int bootCount = 0;
- 16 進数での 2 ^ GPIO_NUMBER
- 1 = EXT0 ウェイクアップ、0 = EXT1 ウェイクアップ
- 使用できるのは RTC IO のみ - ESP32 ピンの例
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;
}
ESP_SLEEP_WAKEUP_EXT0: このウェイクアップ理由は、RTC(リアルタイムクロック)I/O 用に設定された GPIO ピンで検出された外部信号により ESP32 が起床したことを示します。これは通常、ボタンやセンサーがトリガーされたときにスリープから復帰するために使用されます。ESP_SLEEP_WAKEUP_EXT1: このウェイクアップ理由は、RTC コントローラによって管理される GPIO ピン上の外部信号によって起床したことを示します。EXT0と異なり、EXT1は複数のピンを扱うことができ、指定したいずれかのピンの状態が変化したとき(例:Low または High になる)に起床させることができます。ESP_SLEEP_WAKEUP_TIMER: このウェイクアップ理由は、あらかじめ設定されたタイマー時間の経過後に ESP32 が起床したことを示します。これは、ユーザー操作を必要とせずに定期的なタスクを実行する必要があるアプリケーションに有用です。ESP_SLEEP_WAKEUP_TOUCHPAD: このウェイクアップ理由は、タッチパッドイベントによって ESP32 が起床したことを示します。ウェイクアップ用に設定されたタッチパッドがタッチを検出すると、デバイスをスリープモードから復帰させることができます。ESP_SLEEP_WAKEUP_ULP: このウェイクアップ理由は、ULP(Ultra-Low Power)プログラムによってウェイクアップがトリガーされたことを意味します。ULP はメイン CPU がディープスリープ中でも動作でき、特定の条件が満たされたときに ESP32 を起床させることができるため、バッテリー消費を最小限に抑えた低消費電力動作が可能になります。
Serial.begin(115200);
delay(1000);
++bootCount;
Serial.println("Boot number: " + String(bootCount));
print_wakeup_reason();
++bootCount;起動回数をインクリメントし、再起動のたびに表示しますprint_wakeup_reason();ESP32 のウェイクアップ理由を表示します
#if USE_EXT0_WAKEUP
esp_sleep_enable_ext0_wakeup(WAKEUP_GPIO, 1);
rtc_gpio_pullup_dis(WAKEUP_GPIO);
rtc_gpio_pulldown_en(WAKEUP_GPIO);
esp_sleep_enable_ext0_wakeup(WAKEUP_GPIO, 1);指定した GPIO ピンが High になったときに EXT0 ウェイクアップを有効にします。rtc_gpio_pullup_dis(WAKEUP_GPIO);ウェイクアップ用 GPIO ピンのプルアップ抵抗を無効にします。rtc_gpio_pulldown_en(WAKEUP_GPIO);ウェイクアップ用 GPIO ピンのプルダウン抵抗を有効にします。
#else
esp_sleep_enable_ext1_wakeup_io(BUTTON_PIN_BITMASK(WAKEUP_GPIO), ESP_EXT1_WAKEUP_ANY_HIGH);
rtc_gpio_pulldown_en(WAKEUP_GPIO);
rtc_gpio_pullup_dis(WAKEUP_GPIO);
-
esp_sleep_enable_ext1_wakeup_io(BUTTON_PIN_BITMASK(WAKEUP_GPIO), ESP_EXT1_WAKEUP_ANY_HIGH);EXT1 ウェイクアップ -
rtc_gpio_pulldown_en(WAKEUP_GPIO);GPIO33 を GND に接続し、High になったときにウェイクアップできるようにします -
rtc_gpio_pullup_dis(WAKEUP_GPIO);High でウェイクアップできるようにするために PULL_UP を無効にします -
esp_sleep_enable_ext1_wakeup_io(BUTTON_PIN_BITMASK(WAKEUP_GPIO), ESP_EXT1_WAKEUP_ANY_HIGH);ext1を使用する場合は、このように使用します -
rtc_gpio_pulldown_en(WAKEUP_GPIO);GPIO33 を GND に接続し、High になったときにウェイクアップできるようにします -
rtc_gpio_pullup_dis(WAKEUP_GPIO);High でウェイクアップできるようにするために PULL_UP を無効にします
Serial.println("Going to sleep now");
esp_deep_sleep_start();
Serial.println("This will never be printed");
esp_deep_sleep_start();ESP32 をディープスリープモードに移行させます。
#if CONFIG_IDF_TARGET_ESP32
#define THRESHOLD 40
#elif (CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3)
#define THRESHOLD 5000
#else
#define THRESHOLD 500
#endif
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();
#if CONFIG_IDF_TARGET_ESP32
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;
}
#else
if (touchPin < TOUCH_PAD_MAX) {
Serial.printf("Touch detected on GPIO %d\n", touchPin);
} else {
Serial.println("Wakeup not by touchpad");
}
#endif
}
void setup() {
Serial.begin(115200);
delay(1000);
++bootCount;
Serial.println("Boot number: " + String(bootCount));
print_wakeup_reason();
print_wakeup_touchpad();
#if CONFIG_IDF_TARGET_ESP32
touchSleepWakeUpEnable(T3, THRESHOLD);
touchSleepWakeUpEnable(T7, THRESHOLD);
#else
touchSleepWakeUpEnable(T3, THRESHOLD);
#endif
Serial.println("Going to sleep now");
esp_deep_sleep_start();
Serial.println("This will never be printed");
}
void loop() {
}
詳細なメモ
#if CONFIG_IDF_TARGET_ESP32
#define THRESHOLD 40
#elif (CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3)
#define THRESHOLD 5000
#else
#define THRESHOLD 500
#endif
- 対象が ESP32 かどうかを確認します
- ESP32 用のタッチ感度のしきい値を定義します
- 対象が ESP32S2 または ESP32S3 かどうかを確認します
- ESP32S2/S3 用に、より高いタッチ感度のしきい値を定義します
- 対象が上記のいずれでもない場合
- その他のターゲット向けのデフォルトのしきい値を定義します
RTC_DATA_ATTR int bootCount = 0; // Declare a variable to count boots, stored in RTC memory.
touch_pad_t touchPin; // Declare a variable to hold the touchpad pin status.
void print_wakeup_reason() { // Function to print the reason for waking up.
esp_sleep_wakeup_cause_t wakeup_reason; // Variable to hold the wakeup reason.
wakeup_reason = esp_sleep_get_wakeup_cause(); // Get the cause of the wakeup.
RTC_DATA_ATTR int bootCount = 0;RTC メモリに保存される、起動回数をカウントする変数を宣言します。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;
}
ESP_SLEEP_WAKEUP_EXT0: このウェイクアップ理由は、RTC(リアルタイムクロック)I/O 用に設定された GPIO ピンで検出された外部信号により ESP32 が起床したことを示します。これは通常、ボタンやセンサーがトリガーされたときにスリープから復帰するために使用されます。ESP_SLEEP_WAKEUP_EXT1: このウェイクアップ理由は、RTC コントローラによって管理される GPIO ピン上の外部信号によって起床したことを示します。EXT0と異なり、EXT1は複数のピンを扱うことができ、指定したいずれかのピンの状態が変化したとき(例:Low または High になる)に起床させることができます。ESP_SLEEP_WAKEUP_TIMER: このウェイクアップ理由は、あらかじめ設定されたタイマー時間の経過後に ESP32 が起床したことを示します。これは、ユーザー操作を必要とせずに定期的なタスクを実行する必要があるアプリケーションに有用です。ESP_SLEEP_WAKEUP_TOUCHPAD: このウェイクアップ理由は、タッチパッドイベントによって ESP32 が起床したことを示します。ウェイクアップ用に設定されたタッチパッドがタッチを検出すると、デバイスをスリープモードから復帰させることができます。ESP_SLEEP_WAKEUP_ULP: このウェイクアップ理由は、ULP(Ultra-Low Power)プログラムによってウェイクアップがトリガーされたことを意味します。ULP はメイン CPU がディープスリープ中でも動作でき、特定の条件が満たされたときに ESP32 を起床させることができるため、バッテリー消費を最小限に抑えた低消費電力動作が可能になります。
void print_wakeup_touchpad() {
touchPin = esp_sleep_get_touchpad_wakeup_status();
#if CONFIG_IDF_TARGET_ESP32
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;
}
#else
if (touchPin < TOUCH_PAD_MAX) {
Serial.printf("Touch detected on GPIO %d\n", touchPin);
} else {
Serial.println("Wakeup not by touchpad");
}
#endif
}
case 0:GPIO 4 でタッチが検出されました。case 1:GPIO 0 でタッチが検出されました。case 2:GPIO 2 でタッチが検出されました。case 3:GPIO 15 でタッチが検出されました。case 4:GPIO 13 でタッチが検出されました。case 5:GPIO 12 でタッチが検出されました。case 6:GPIO 14 でタッチを検出しました。case 7:GPIO 27 でタッチを検出しました。case 8:GPIO 33 でタッチを検出しました。case 9:GPIO 32 でタッチを検出しました。default:タッチが検出されなかった場合のデフォルトケース。
void setup() {
Serial.begin(115200);
delay(1000);
++bootCount;
Serial.println("Boot number: " + String(bootCount));
print_wakeup_reason();
print_wakeup_touchpad();
#if CONFIG_IDF_TARGET_ESP32
touchSleepWakeUpEnable(T3, THRESHOLD);
touchSleepWakeUpEnable(T7, THRESHOLD);
#else
touchSleepWakeUpEnable(T3, THRESHOLD);
#endif
Serial.println("Going to sleep now");
esp_deep_sleep_start();
Serial.println("This will never be printed");
}
-
++bootCount;起動回数をインクリメントします。 -
print_wakeup_reason();ウェイクアップ理由を出力します。 -
print_wakeup_touchpad();タッチパッドのウェイクアップ状態を出力します。 -
#if CONFIG_IDF_TARGET_ESP32ターゲットが ESP32 かどうかを確認します -
touchSleepWakeUpEnable(T3, THRESHOLD);定義されたしきい値で T3 のタッチウェイクアップを有効にします。 -
touchSleepWakeUpEnable(T7, THRESHOLD);定義されたしきい値で T7 のタッチウェイクアップを有効にします。 -
touchSleepWakeUpEnable(T3, THRESHOLD);定義されたしきい値で T3 のタッチウェイクアップを有効にします。 -
esp_deep_sleep_start();ESP32 をディープスリープモードにします。
#include <Arduino.h> // Include the Arduino core library
#include "esp32/ulp.h" // Include ESP32 ULP-related library
#include "driver/rtc_io.h" // Include RTC GPIO driver library
#include "soc/rtc_io_reg.h" // Include RTC IO register definitions
#define RTC_dutyMeter 0 // Define the storage location for dutyMeter
#define RTC_dir 4 // Define the storage location for direction
#define RTC_fadeDelay 12 // Define the storage location for fadeDelay
uint32_t *fadeCycleDelay = &RTC_SLOW_MEM[RTC_fadeDelay]; // Point to the fadeDelay location in RTC_SLOW_MEM
#define ULP_START_OFFSET 32 // Define the starting offset for the ULP program
RTC_DATA_ATTR uint32_t ULP_Started = 0; // Variable to indicate if the ULP program has started
// Time-to-Sleep
#define uS_TO_S_FACTOR 1000000ULL // Conversion factor from microseconds to seconds
#define TIME_TO_SLEEP 5 // Time to enter deep sleep (in seconds)
void ulp_setup() { // ULP setup function
if (ULP_Started) { // If ULP has already started, return
return;
}
*fadeCycleDelay = 5; // Initialize fadeCycleDelay to 5
ULP_Started = 1; // Mark ULP as started
const gpio_num_t MeterPWMPin = GPIO_NUM_2; // Define the PWM pin
rtc_gpio_init(MeterPWMPin); // Initialize GPIO
rtc_gpio_set_direction(MeterPWMPin, RTC_GPIO_MODE_OUTPUT_ONLY); // Set the pin as output
rtc_gpio_set_level(MeterPWMPin, 0); // Set the initial pin level to low
const uint32_t MeterPWMBit = rtc_io_number_get(MeterPWMPin) + RTC_GPIO_OUT_DATA_S; // Get the bit for the PWM pin
enum labels { // Define labels for the ULP program
INIFINITE_LOOP,
RUN_PWM,
NEXT_PWM_CYCLE,
PWM_ON,
PWM_OFF,
END_PWM_CYCLE,
POSITIVE_DIR,
DEC_DUTY,
INC_DUTY,
};
// Define the ULP program
const ulp_insn_t ulp_prog[] = {
// Initial value setup
I_MOVI(R0, 0), // Move 0 to register R0
I_ST(R0, R0, RTC_dutyMeter), // Store the value of R0 in dutyMeter
I_MOVI(R1, 1), // Move 1 to register R1
I_ST(R1, R0, RTC_dir), // Store the value of R1 in dir
M_LABEL(INIFINITE_LOOP), // Define the infinite loop label
I_MOVI(R3, 0), // Move 0 to R3
I_LD(R3, R3, RTC_fadeDelay), // Load the value from fadeDelay into R3
M_LABEL(RUN_PWM), // Define the run PWM label
I_MOVI(R0, 0), // Move 0 to R0
I_LD(R0, R0, RTC_dutyMeter), // Load the value from dutyMeter into R0
M_BL(NEXT_PWM_CYCLE, 1), // Branch to the next PWM cycle
I_WR_REG(RTC_GPIO_OUT_W1TS_REG, MeterPWMBit, MeterPWMBit, 1), // Set the PWM pin high
M_LABEL(PWM_ON), // Define the PWM ON label
M_BL(NEXT_PWM_CYCLE, 1), // Branch to the next PWM cycle
// I_DELAY(8), // Commented out delay instruction
I_SUBI(R0, R0, 1), // Decrement R0 by 1
M_BX(PWM_ON), // Go back to the PWM ON label
M_LABEL(NEXT_PWM_CYCLE), // Define the next PWM cycle label
I_MOVI(R0, 0), // Move 0 to R0
I_LD(R0, R0, RTC_dutyMeter), // Load the value from dutyMeter into R0
I_MOVI(R1, 100), // Move 100 to R1
I_SUBR(R0, R1, R0), // R0 = R1 - R0
M_BL(END_PWM_CYCLE, 1), // Branch to the end PWM cycle label
I_WR_REG(RTC_GPIO_OUT_W1TC_REG, MeterPWMBit, MeterPWMBit, 1), // Set the PWM pin low
M_LABEL(PWM_OFF), // Define the PWM OFF label
M_BL(END_PWM_CYCLE, 1), // Branch to the end PWM cycle label
// I_DELAY(8), // Commented out delay instruction
I_SUBI(R0, R0, 1), // Decrement R0 by 1
M_BX(PWM_OFF), // Go back to the PWM OFF label
M_LABEL(END_PWM_CYCLE), // Define the end PWM cycle label
I_SUBI(R3, R3, 1), // Decrement R3 by 1
I_MOVR(R0, R3), // Move R3 to R0
M_BGE(RUN_PWM, 1), // If R3 >= 0, branch to RUN_PWM
I_MOVI(R1, 0), // Move 0 to R1
I_LD(R1, R1, RTC_dutyMeter), // Load the value from dutyMeter into R1
I_MOVI(R0, 0), // Move 0 to R0
I_LD(R0, R0, RTC_dir), // Load the value from dir into R0
M_BGE(POSITIVE_DIR, 1), // If R0 >= 0, branch to POSITIVE_DIR
I_MOVR(R0, R1), // Move R1 to R0
M_BGE(DEC_DUTY, 1), // If R1 >= 0, branch to DEC_DUTY
I_MOVI(R3, 0), // Move 0 to R3
I_MOVI(R2, 1), // Move 1 to R2
I_ST(R2, R3, RTC_dir), // Store the value of R2 in dir
M_BX(INC_DUTY), // Branch to INC_DUTY label
M_LABEL(DEC_DUTY), // Define DEC_DUTY label
I_SUBI(R0, R0, 2), // Decrement R0 by 2
I_MOVI(R2, 0), // Move 0 to R2
I_ST(R0, R2, RTC_dutyMeter), // Store the value of R0 in dutyMeter
M_BX(INIFINITE_LOOP), // Go back to the infinite loop label
M_LABEL(POSITIVE_DIR), // Define POSITIVE_DIR label
I_MOVR(R0, R1), // Move R1 to R0
M_BL(INC_DUTY, 100), // Branch to INC_DUTY label with parameter 100
I_MOVI(R2, 0), // Move 0 to R2
I_ST(R2, R2, RTC_dir), // Store the value of R2 in dir
M_BX(DEC_DUTY), // Branch to DEC_DUTY label
M_LABEL(INC_DUTY), // Define INC_DUTY label
I_ADDI(R0, R0, 2), // Increment R0 by 2
I_MOVI(R2, 0), // Move 0 to R2
I_ST(R0, R2, RTC_dutyMeter), // Store the value of R0 in dutyMeter
M_BX(INIFINITE_LOOP), // Go back to the infinite loop label
};
// Run the ULP program
size_t size = sizeof(ulp_prog) / sizeof(ulp_insn_t); // Calculate the size of the ULP program
ulp_process_macros_and_load(ULP_START_OFFSET, ulp_prog, &size); // Load the ULP program
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON); // Configure power management for RTC peripherals
ulp_run(ULP_START_OFFSET); // Start the ULP program
}
void setup() { // Arduino setup function
Serial.begin(115200); // Initialize serial communication at 115200 baud rate
ulp_setup(); // Call the ULP setup function
Serial.printf("\nStarted smooth blink with delay %ld\n", *fadeCycleDelay); // Print startup information
if (*fadeCycleDelay < 195) { // If fadeCycleDelay is less than 195
*fadeCycleDelay += 10; // Increase fadeCycleDelay
} else {
*fadeCycleDelay = 5; // Otherwise, reset fadeCycleDelay to 5
}
Serial.println("Entering in Deep Sleep"); // Print entering deep sleep information
esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR /*/ 4*/); // Set timer wakeup
esp_deep_sleep_start(); // Enter deep sleep
}
void loop() { // Arduino loop function
// Empty loop
}
ディープスリープモードに入った後にプログラムを書き込み直すには、boot ボタンを押し続けたまま reset ボタンを押して ESP32 を再起動してください。
結果表示

ライトスリープ
概要
ライトスリープモードは、ESP32 におけるもう一つの低消費電力モードであり、素早い応答時間を維持しながらデバイスの電力を節約することができます。このモードでは CPU コアは停止しますが、RAM と一部のペリフェラルは電源が入ったままのため、特定のイベントに応じてデバイスをすばやくウェイクアップさせることができます。
ライトスリープは、低消費電力が求められる一方で WiFi や Bluetooth への接続を維持する必要があるアプリケーションに最適であり、無線通信モジュールをアクティブな状態に保つことができます。
ライトスリープ中の USB ペリフェラル無効化: 省電力のため、内部 USB ペリフェラル(USB-Serial-JTAG)はライトスリープ中に無効化されます。これは、デバイスがライトスリープ中は USB 経由のシリアル出力が利用できない ことを意味します。USB ポートを使用してシリアルログを表示している場合、スリープ期間中は何も出力されません。デバッグするには、ハードウェア UART ピンに接続した外部 USB-UART チップを使用するか、GPIO ウェイクアップを利用して、デバイスのウェイクアップ後に出力を監視することを検討してください。
ウェイクアップ方法
- タイマーウェイクアップ: デバイスは指定した時間経過後にウェイクアップでき、定期的なタスクを実行できます。
- 外部割り込みウェイクアップ: ESP32 は、ボタン押下やその他のハードウェア割り込みなどの外部信号によってウェイクアップさせることができます。
- ネットワークアクティビティによるウェイクアップ: デバイスは、受信したネットワークパケットに応答してウェイクアップでき、常にアクティブ状態にしておくことなく効率的な通信を実現します。
- GPIO ウェイクアップ: 特定の GPIO ピンを設定して、状態変化や信号などのイベントが発生したときにライトスリープからデバイスをウェイクアップさせることができます。
コード実装
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
const int sleepTime = 10000;
const int ledPin = LED_BUILTIN;
void ledTask(void *pvParameters) {
digitalWrite(ledPin, HIGH);
Serial.println("LED is ON");
vTaskDelay(pdMS_TO_TICKS(1000));
digitalWrite(ledPin, LOW);
Serial.println("LED is OFF");
vTaskDelete(NULL);
}
void setup() {
Serial.begin(115200);
pinMode(ledPin, OUTPUT);
Serial.println("Setup complete. Going to sleep...");
}
void loop() {
esp_sleep_enable_timer_wakeup(sleepTime * 1000);
Serial.println("Going to sleep now...");
esp_light_sleep_start();
xTaskCreate(ledTask, "LED Task", 2048, NULL, 1, NULL);
delay(1000);
}
詳細な説明
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
- FreeRTOS ライブラリをインクルードします
const int sleepTime = 10000;
const int ledPin = LED_BUILTIN;
- スリープ時間を 10 秒に設定します
- 内蔵 LED ピンを使用します
void ledTask(void *pvParameters):
- LED の状態を制御する FreeRTOS タスクを定義します。
digitalWrite(ledPin, HIGH);
Serial.println("LED is ON");
vTaskDelay(pdMS_TO_TICKS(1000));
digitalWrite(ledPin, LOW);
Serial.println("LED is OFF");
vTaskDelete(NULL);
vTaskDelay(pdMS_TO_TICKS(1000));LED を 1 秒間点灯させますvTaskDelete(NULL);現在のタスクを削除します
esp_sleep_enable_timer_wakeup(sleepTime * 1000);
Serial.println("Going to sleep now...");
esp_light_sleep_start();
xTaskCreate(ledTask, "LED Task", 2048, NULL, 1, NULL);
delay(1000);
esp_sleep_enable_timer_wakeup(sleepTime * 1000);ウェイクアップ用のタイマーを設定しますesp_light_sleep_start();ライトスリープモードに入りますxTaskCreate(ledTask, "LED Task", 2048, NULL, 1, NULL);LED 制御タスクを作成します
実行結果

Modem-Sleep
概要
Modem Sleep モードは ESP32 におけるもう 1 つの重要な低消費電力モードであり、Deep Sleep モードとは異なります。Modem Sleep モードは主に ESP32 の無線通信モジュール向けに最適化されています。
このモードでは、ESP32 の WiFi/Bluetooth モジュールがスリープ状態に入り、CPU コアは動作したままになります。これにより、消費電力を大幅に削減しつつ、ESP32 は一定レベルの無線接続性を維持できます。
ウェイクアップ方法
-
タイマーによるウェイクアップ
-
外部割り込みによるウェイクアップ
-
タスクによるウェイクアップ
-
ネットワークアクティビティによるウェイクアップ
コード実装
#include "WiFi.h"
void setup() {
Serial.begin(115200);
Serial.println("Connecting to WiFi...");
WiFi.begin("****", "****");
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting...");
}
Serial.println("Connected to WiFi!");
WiFi.setSleep(true);
Serial.println("Modem-Sleep enabled.");
}
void loop() {
Serial.println("Running...");
delay(5000);
WiFi.setSleep(false);
Serial.println("Modem-Sleep disabled. WiFi is active.");
if (WiFi.status() == WL_CONNECTED) {
Serial.println("Still connected to WiFi.");
} else {
Serial.println("WiFi disconnected.");
}
delay(5000);
WiFi.setSleep(true);
Serial.println("Modem-Sleep enabled.");
}
詳細な説明
#include "WiFi.h"
- WiFi 機能を有効にするために WiFi ライブラリをインクルードします。
Serial.println("Connecting to WiFi...");
- WiFi への接続を開始することを示すメッセージを出力します。
WiFi.begin("****", "****");
- 指定した WiFi ネットワークへの接続を開始します。
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting...");
}
Serial.println("Connected to WiFi!");
- WiFi に正常に接続されるまでループします。
WiFi.setSleep(true);
- 省電力のために Modem Sleep モードを有効にします。
WiFi.setSleep(false);
- WiFi を有効化するために Modem Sleep モードを無効にします。
if (WiFi.status() == WL_CONNECTED) {
- WiFi の状態を確認します。
WiFi.setSleep(true);
- 再度 Modem Sleep モードを有効にします。
実行結果

スリープ機能の応用
上記の簡単な例を踏まえて、次は一歩進めて、これらのスリープ機能を ESP32 S3 Sense センサー上で活用してみましょう。
ソフトウェアの準備
この記事を始める前に、まだ XIAO ESP32S3 Sense 上のすべてのハードウェア機能を使用したことがない場合は、いくつかのソフトウェアインストールの準備が完了していることを確認してください。
ここでは 3 つの機能について紹介します。詳細は次のリンクから確認できます。
-
Micrphone Use: XIAO ESP32S3 Sense 上のマイクを使用して周囲の音量を取得し、音声を録音する方法を学びます。
-
MicroSD: プロジェクトでファイルを保存および取得できるように、データ保存用に MicroSD カードを使用する方法を理解します。
-
Camera Use: XIAO ESP32S3 Sense 上のカメラモジュールを使用して写真を撮影し、動画を録画する方法を習得します。
コード実装
- Deep-Sleep
- Light-Sleep
- Modem-Sleep
#include "esp_camera.h"
#include "FS.h"
#include "SD.h"
#include "SPI.h"
#define CAMERA_MODEL_XIAO_ESP32S3
#include "camera_pins.h"
unsigned long lastCaptureTime = 0;
int imageCount = 1;
bool camera_sign = false;
bool sd_sign = false;
void photo_save(const char * fileName) {
camera_fb_t *fb = esp_camera_fb_get();
if (!fb) {
Serial.println("Failed to get camera frame buffer");
return;
}
writeFile(SD, fileName, fb->buf, fb->len);
esp_camera_fb_return(fb);
Serial.println("Photo saved to file");
}
void writeFile(fs::FS &fs, const char * path, uint8_t * data, size_t len){
Serial.printf("Writing file: %s\r\n", path);
File file = fs.open(path, FILE_WRITE);
if (!file) {
Serial.println("Failed to open file for writing");
return;
}
if (file.write(data, len) == len) {
Serial.println("File written");
} else {
Serial.println("Write failed");
}
file.close();
}
void setup() {
Serial.begin(115200);
while (!Serial);
camera_config_t config;
config.ledc_channel = LEDC_CHANNEL_0;
config.ledc_timer = LEDC_TIMER_0;
config.pin_d0 = Y2_GPIO_NUM;
config.pin_d1 = Y3_GPIO_NUM;
config.pin_d2 = Y4_GPIO_NUM;
config.pin_d3 = Y5_GPIO_NUM;
config.pin_d4 = Y6_GPIO_NUM;
config.pin_d5 = Y7_GPIO_NUM;
config.pin_d6 = Y8_GPIO_NUM;
config.pin_d7 = Y9_GPIO_NUM;
config.pin_xclk = XCLK_GPIO_NUM;
config.pin_pclk = PCLK_GPIO_NUM;
config.pin_vsync = VSYNC_GPIO_NUM;
config.pin_href = HREF_GPIO_NUM;
config.pin_sscb_sda = SIOD_GPIO_NUM;
config.pin_sscb_scl = SIOC_GPIO_NUM;
config.pin_pwdn = PWDN_GPIO_NUM;
config.pin_reset = RESET_GPIO_NUM;
config.xclk_freq_hz = 20000000;
config.frame_size = FRAMESIZE_UXGA;
config.pixel_format = PIXFORMAT_JPEG;
config.grab_mode = CAMERA_GRAB_WHEN_EMPTY;
config.fb_location = CAMERA_FB_IN_PSRAM;
config.jpeg_quality = 12;
config.fb_count = 1;
esp_err_t err = esp_camera_init(&config);
if (err != ESP_OK) {
Serial.printf("Camera init failed with error 0x%x", err);
return;
}
camera_sign = true;
if (!SD.begin(21)) {
Serial.println("Card Mount Failed");
return;
}
uint8_t cardType = SD.cardType();
if (cardType == CARD_NONE) {
Serial.println("No SD card attached");
return;
}
Serial.print("SD Card Type: ");
if (cardType == CARD_MMC) {
Serial.println("MMC");
} else if (cardType == CARD_SD) {
Serial.println("SDSC");
} else if (cardType == CARD_SDHC) {
Serial.println("SDHC");
} else {
Serial.println("UNKNOWN");
}
sd_sign = true;
Serial.println("Photos will begin shortly, please be ready.");
}
void loop() {
if (camera_sign && sd_sign) {
unsigned long now = millis();
if ((now - lastCaptureTime) >= 60000) {
char filename[32];
sprintf(filename, "/image%d.jpg", imageCount);
photo_save(filename);
Serial.printf("Saved picture: %s\r\n", filename);
Serial.println("Entering deep sleep for 10 seconds...");
esp_sleep_enable_timer_wakeup(10000000);
esp_deep_sleep_start();
}
}
}
詳細な説明
このコードは ESP32 カメラモジュールをベースにした画像キャプチャシステムを実装しており、60 秒ごとに自動で写真を撮影し、SD カードに保存します。void setup() 関数ではカメラと SD カードを初期化し、デバイスの状態を確認します。void loop() 関数ではカメラが撮影可能かどうかを確認し、条件を満たす場合は photo_save() 関数を呼び出して画像を保存し、保存後に 10 秒間のディープスリープ状態に入って省電力化を行います。
#include <ESP_I2S.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
I2SClass I2S;
const int sleepTime = 10000;
void i2sTask(void *pvParameters) {
Serial.println("start collecting");
for (int i = 0; i < 10; i++) {
int sample = I2S.read();
if (sample && sample != -1 && sample != 1) {
Serial.println(sample);
}
vTaskDelay(pdMS_TO_TICKS(1000));
}
vTaskDelay(pdMS_TO_TICKS(3000));
vTaskDelete(NULL);
}
void setup() {
Serial.begin(115200);
while (!Serial) {
;
}
I2S.setPinsPdmRx(42, 41);
if (!I2S.begin(I2S_MODE_PDM_RX, 16000, I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_MONO)) {
Serial.println("Failed to initialize I2S!");
while (1);
}
}
void loop() {
esp_sleep_enable_timer_wakeup(sleepTime * 1000);
xTaskCreate(i2sTask, "I2S Task", 2048, NULL, 1, NULL);
Serial.println("Going to sleep now...");
esp_light_sleep_start();
delay(1000);
}
詳細な説明
このコードは I2S インターフェースを使用して音声データを取得する機能を実装しています。void setup() 関数ではシリアルポートと I2S インターフェースを初期化し、void loop() 関数ではウェイクアップタイマーを有効にしてタスク void i2sTask(void *pvParameters) を作成します。このタスクは音声サンプルを読み取り、毎秒有効なデータを出力する役割を担います。タスクが 10 回実行された後、3 秒間の遅延を行い、自身を削除します。
#include "esp_camera.h"
#include <WiFi.h>
#define CAMERA_MODEL_XIAO_ESP32S3
#include "camera_pins.h"
const char *ssid = "******";
const char *password = "******";
void startCameraServer();
void setupLedFlash(int pin);
unsigned long lastCameraOperationTime = 0;
const unsigned long sleepDelay = 10000;
void setup() {
Serial.begin(115200);
Serial.setDebugOutput(true);
Serial.println();
camera_config_t config;
config.ledc_channel = LEDC_CHANNEL_0;
config.ledc_timer = LEDC_TIMER_0;
config.pin_d0 = Y2_GPIO_NUM;
config.pin_d1 = Y3_GPIO_NUM;
config.pin_d2 = Y4_GPIO_NUM;
config.pin_d3 = Y5_GPIO_NUM;
config.pin_d4 = Y6_GPIO_NUM;
config.pin_d5 = Y7_GPIO_NUM;
config.pin_d6 = Y8_GPIO_NUM;
config.pin_d7 = Y9_GPIO_NUM;
config.pin_xclk = XCLK_GPIO_NUM;
config.pin_pclk = PCLK_GPIO_NUM;
config.pin_vsync = VSYNC_GPIO_NUM;
config.pin_href = HREF_GPIO_NUM;
config.pin_sccb_sda = SIOD_GPIO_NUM;
config.pin_sccb_scl = SIOC_GPIO_NUM;
config.pin_pwdn = PWDN_GPIO_NUM;
config.pin_reset = RESET_GPIO_NUM;
config.xclk_freq_hz = 20000000;
config.frame_size = FRAMESIZE_UXGA;
config.pixel_format = PIXFORMAT_JPEG;
config.grab_mode = CAMERA_GRAB_WHEN_EMPTY;
config.fb_location = CAMERA_FB_IN_PSRAM;
config.jpeg_quality = 12;
config.fb_count = 1;
if (config.pixel_format == PIXFORMAT_JPEG) {
if (psramFound()) {
config.jpeg_quality = 10;
config.fb_count = 2;
config.grab_mode = CAMERA_GRAB_LATEST;
} else {
config.frame_size = FRAMESIZE_SVGA;
config.fb_location = CAMERA_FB_IN_DRAM;
}
} else {
config.frame_size = FRAMESIZE_240X240;
#if CONFIG_IDF_TARGET_ESP32S3
config.fb_count = 2;
#endif
}
#if defined(CAMERA_MODEL_ESP_EYE)
pinMode(13, INPUT_PULLUP);
pinMode(14, INPUT_PULLUP);
#endif
esp_err_t err = esp_camera_init(&config);
if (err != ESP_OK) {
Serial.printf("Camera init failed with error 0x%x", err);
return;
}
sensor_t *s = esp_camera_sensor_get();
if (s->id.PID == OV3660_PID) {
s->set_vflip(s, 1);
s->set_brightness(s, 1);
s->set_saturation(s, -2);
}
if (config.pixel_format == PIXFORMAT_JPEG) {
s->set_framesize(s, FRAMESIZE_QVGA);
}
#if defined(CAMERA_MODEL_M5STACK_WIDE) || defined(CAMERA_MODEL_M5STACK_ESP32CAM)
s->set_vflip(s, 1);
s->set_hmirror(s, 1);
#endif
#if defined(CAMERA_MODEL_ESP32S3_EYE)
s->set_vflip(s, 1);
#endif
#if defined(LED_GPIO_NUM)
setupLedFlash(LED_GPIO_NUM);
#endif
WiFi.begin(ssid, password);
WiFi.setSleep(false);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
startCameraServer();
Serial.print("Camera Ready! Use 'http://");
Serial.print(WiFi.localIP());
Serial.println("' to connect");
}
void loop() {
delay(10000);
if (WiFi.getSleep()) {
Serial.println("WiFi is in sleep mode.");
} else {
Serial.println("WiFi is active.");
}
if (millis() - lastCameraOperationTime > sleepDelay) {
WiFi.setSleep(true);
Serial.println("No camera operation. WiFi is now in sleep mode.");
} else {
WiFi.setSleep(false);
}
cameraOperation();
}
void cameraOperation() {
lastCameraOperationTime = millis();
}
詳細な説明
このコードは、ESP32 カメラモジュールを使用した画像キャプチャと Wi-Fi 経由での接続を実装しています。void setup() 関数では、シリアルポート、カメラ、および Wi-Fi 接続が初期化されます。初期化が成功すると、ユーザーが接続できるように Wi-Fi アドレスが出力されます。void loop() 関数では、10 秒ごとに Wi-Fi の状態をチェックし、カメラの操作がない場合は省電力のために Wi-Fi をスリープモードに設定します。cameraOperation() 関数が呼び出されるたびに、最後の操作時刻が更新され、イベントの間は Wi-Fi 接続が維持されるようになっています。
これらのコードはそのままでは使用できません。カメラに関するヘッダーファイルを追加する必要があります。XIAO ESP32 S3 に関する上記のサンプルを確認してください。
まとめ
Deep Sleep モードを使用する理由
デバイスのバッテリー寿命を延ばすために、機能性を損なうことなく電力節約を最大化します。 適したシナリオ:リモートセンサーノード、ウェアラブルデバイス、その他の低消費電力 IoT デバイスなど、バッテリー寿命が重要となるアプリケーション。ウェイクアップ時間は比較的遅いものの、このトレードオフには十分な価値があります。
Modem Sleep モードを使用する理由
ネットワーク接続を維持しながら、無線通信モジュールの消費電力を最適化します。 適したシナリオ:ネットワーク接続を維持する必要がありつつ、低消費電力も求められるアプリケーション。例えば、間欠的に動作する IoT デバイスなどです。Modem Sleep は、無線モジュールの消費電力を大幅に削減しつつ、高速なウェイクアップ応答を提供できます。
総括
これら 3 つのスリープモードは、開発者に対して電力と性能の異なるトレードオフの選択肢を提供し、アプリケーションの具体的な要件に応じて柔軟に選択できます。バッテリー寿命が重視されるデバイスには Deep Sleep モードが適しており、ネットワーク接続を維持する必要がある IoT デバイスには Modem Sleep モードが最適な選択肢となります。
技術サポート & 製品ディスカッション
弊社製品をお選びいただきありがとうございます。製品をできるだけスムーズにご利用いただけるよう、さまざまなサポートをご用意しています。お好みやニーズに応じて選べる複数のコミュニケーションチャネルを提供しています。
