Skip to main content

XIAO ESP32S3 Sense スリープモード

note

この文書は AI によって翻訳されています。内容に不正確な点や改善すべき点がございましたら、文書下部のコメント欄または以下の Issue ページにてご報告ください。
https://github.com/Seeed-Studio/wiki-documents/issues

ここでは、これらの低消費電力スリープモードの使用例をいくつか簡単に示します。すべてのESP32ボードは汎用性が高く、ここで使用している開発ボードはXIAO ESP32S3 Senseです。

ハードウェア概要

Seeed Studio XIAO ESP32S3 Sense

ディープスリープ

概要

ディープスリープモードでは、ESP32はCPU、RAMの大部分、およびAPB_CLKからクロック供給されるすべてのデジタル周辺機器の電源をオフにします。電源が供給され続けるコンポーネントは以下の通りです:

  • RTCコントローラー
  • ULPコプロセッサ
  • RTC FASTメモリ
  • RTC SLOWメモリ

ウェイクアップ方法

  • タイマーウェイクアップ: ESP32は指定された時間後にタイマーを設定することで自動的にウェイクアップできます。

  • タッチパッド割り込みウェイクアップ: タッチパッドの活動によってデバイスをウェイクアップでき、ユーザー操作が必要なアプリケーションに適しています。

  • 外部ウェイクアップ: ESP32は外部信号(例:ボタン押下)によってウェイクアップでき、低消費電力アプリケーションに最適です。

  • ULPコプロセッサ活動ウェイクアップ: ULPコプロセッサは独立して動作し、特定の条件を監視してメインCPUをウェイクアップすることで電力を節約します。

  • GPIOウェイクアップ: GPIOピンの状態(高または低)の変化によってデバイスをウェイクアップでき、さまざまなセンサーや周辺機器に柔軟性を提供します。

以下に、XIAO ESP32 S3 Senseを使用したディープスリープモードの3つの簡単な例を示します。

コード実現


#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("RTC_IOを使用した外部信号によるウェイクアップ"); break;
case ESP_SLEEP_WAKEUP_EXT1: Serial.println("RTC_CNTLを使用した外部信号によるウェイクアップ"); break;
case ESP_SLEEP_WAKEUP_TIMER: Serial.println("タイマーによるウェイクアップ"); break;
case ESP_SLEEP_WAKEUP_TOUCHPAD: Serial.println("タッチパッドによるウェイクアップ"); break;
case ESP_SLEEP_WAKEUP_ULP: Serial.println("ULPプログラムによるウェイクアップ"); break;
default: Serial.printf("ディープスリープによるウェイクアップではありません: %d\n", wakeup_reason); break;
}
}

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


++bootCount;
Serial.println("起動回数: " + String(bootCount));


print_wakeup_reason();


esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
Serial.println("ESP32を毎 " + String(TIME_TO_SLEEP) + " 秒間スリープするよう設定");

Serial.println("今からスリープします");
Serial.flush();
esp_deep_sleep_start();
Serial.println("これは決して表示されません");
}

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を宣言します。この属性により、ディープスリープ中も値を保持できます。
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("RTC_IOを使用した外部信号によるウェイクアップ"); break;
case ESP_SLEEP_WAKEUP_EXT1: Serial.println("RTC_CNTLを使用した外部信号によるウェイクアップ"); break;
case ESP_SLEEP_WAKEUP_TIMER: Serial.println("タイマーによるウェイクアップ"); break;
case ESP_SLEEP_WAKEUP_TOUCHPAD: Serial.println("タッチパッドによるウェイクアップ"); break;
case ESP_SLEEP_WAKEUP_ULP: Serial.println("ULPプログラムによるウェイクアップ"); break;
default: Serial.printf("ディープスリープによるウェイクアップではありません: %d\n", wakeup_reason); break;
}
  • ESP_SLEEP_WAKEUP_EXT0 : ESP32がRTC(リアルタイムクロック)I/Oに設定されたGPIOピンで検出された外部信号によってウェイクアップしたことを示します。通常、ボタンやセンサーがトリガーされた場合に使用されます。
  • ESP_SLEEP_WAKEUP_EXT1 : RTCコントローラーで管理されるGPIOピンの外部信号によるウェイクアップを示します。EXT0とは異なり、複数のピンを処理でき、指定されたピンのいずれかが状態を変化させた場合(例:低または高になる)にウェイクアップします。
  • ESP_SLEEP_WAKEUP_TIMER : ESP32が事前に定義されたタイマー期間後にウェイクアップしたことを示します。ユーザー操作を必要としない定期的なタスクに役立ちます。
  • ESP_SLEEP_WAKEUP_TOUCHPAD : タッチパッドイベントによるESP32のウェイクアップを示します。ウェイクアップ用に設定されたタッチパッドがタッチを検出すると、デバイスをスリープモードから復帰させることができます。
  • ESP_SLEEP_WAKEUP_ULP : ULP(超低消費電力)プログラムによるウェイクアップを意味します。ULPはメインCPUがディープスリープ中に動作し、特定の条件が満たされた場合に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をディープスリープモードにします。
tip

ディープスリープモードに入った後にプログラムを書き込み直すには、ブートボタンを押し続けながらリセットボタンを押してESP32を再起動してください。

結果表示

ライトスリープ

概要

ライトスリープモードは、ESP32のもう一つの低消費電力モードであり、迅速な応答時間を維持しながらエネルギーを節約することができます。このモードでは、CPUコアは停止しますが、RAMや一部の周辺機器は電源が入ったままなので、特定のイベントに応じて迅速にウェイクアップすることが可能です。

ライトスリープは、低消費電力を必要としながらもWiFiやBluetoothへの接続を維持する必要があるアプリケーションに最適です。このモードでは、無線通信モジュールをアクティブな状態に保つことができます。

ウェイクアップ方法

  • タイマーウェイクアップ: 指定された時間経過後にデバイスをウェイクアップさせ、定期的なタスクを実行できます。
  • 外部割り込みウェイクアップ: ボタンの押下や他のハードウェア割り込みなどの外部信号によって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制御タスクを作成します。

結果表示

モデムスリープ

はじめに

モデムスリープモードは、ESP32のもう一つの重要な低消費電力モードであり、ディープスリープモードとは異なります。モデムスリープモードは、主にESP32の無線通信モジュールを最適化するために設計されています。

このモードでは、ESP32のWiFi/Bluetoothモジュールがスリープ状態に入り、CPUコアはアクティブなままです。これにより、ESP32は一定の無線接続を維持しながら、消費電力を大幅に削減することができます。

ウェイクアップ方法

  • タイマーウェイクアップ

  • 外部割り込みウェイクアップ

  • タスクウェイクアップ

  • ネットワークアクティビティウェイクアップ

コード実現

#include "WiFi.h"

void setup() {
Serial.begin(115200);
Serial.println("WiFiに接続中...");

WiFi.begin("****", "****");

while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("接続中...");
}
Serial.println("WiFiに接続しました!");

WiFi.setSleep(true);
Serial.println("モデムスリープが有効になりました。");
}

void loop() {

Serial.println("実行中...");

delay(5000);

WiFi.setSleep(false);
Serial.println("モデムスリープが無効になりました。WiFiがアクティブです。");

if (WiFi.status() == WL_CONNECTED) {
Serial.println("WiFiにまだ接続されています。");
} else {
Serial.println("WiFiが切断されました。");
}

delay(5000);
WiFi.setSleep(true);
Serial.println("モデムスリープが有効になりました。");
}

詳細な説明

#include "WiFi.h"
  • WiFi機能を有効にするためにWiFiライブラリをインクルードします。
Serial.println("WiFiに接続中...");
  • WiFi接続の開始を示すメッセージを出力します。
WiFi.begin("****", "****");
  • 指定されたWiFiネットワークへの接続を開始します。
    while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("接続中...");
}
Serial.println("WiFiに接続しました!");
  • WiFiに正常に接続されるまでループします。
WiFi.setSleep(true);
  • モデムスリープモードを有効にして電力を節約します。
WiFi.setSleep(false);
  • モデムスリープモードを無効にしてWiFiをアクティブにします。
if (WiFi.status() == WL_CONNECTED) {
  • WiFiの状態を確認します。
WiFi.setSleep(true);
  • 再びモデムスリープモードを有効にします。

結果表示

スリープ機能の応用

上記の簡単な例を基に、次はこれらのスリープ機能をESP32 S3 Senseセンサーでさらに活用してみましょう。

ソフトウェア準備

この記事を始める前に、XIAO ESP32S3 Senseのすべてのハードウェア機能をまだ使用していない場合は、いくつかのソフトウェアインストール準備を完了していることを確認してください。

以下は3つの機能の紹介で、詳細は以下のリンクから確認できます:

  • マイクの使用: XIAO ESP32S3 Senseのマイクを使用して周囲の音量をキャプチャし、音声を記録する方法を学びます。

  • MicroSD: MicroSDカードをデータストレージに使用する方法を理解し、プロジェクトでファイルを保存および取得できるようにします。

  • カメラの使用: XIAO ESP32S3 Senseのカメラモジュールを使用して写真を撮影し、ビデオを記録する方法を習得します。

コード実現

#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("カメラフレームバッファの取得に失敗しました");
return;
}
writeFile(SD, fileName, fb->buf, fb->len);

esp_camera_fb_return(fb);

Serial.println("写真がファイルに保存されました");
}

void writeFile(fs::FS &fs, const char * path, uint8_t * data, size_t len){
Serial.printf("ファイルを書き込み中: %s\r\n", path);

File file = fs.open(path, FILE_WRITE);
if (!file) {
Serial.println("ファイルの書き込み用オープンに失敗しました");
return;
}
if (file.write(data, len) == len) {
Serial.println("ファイルが書き込まれました");
} else {
Serial.println("書き込みに失敗しました");
}
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("カメラの初期化に失敗しました。エラーコード: 0x%x", err);
return;
}

camera_sign = true;

if (!SD.begin(21)) {
Serial.println("カードのマウントに失敗しました");
return;
}

uint8_t cardType = SD.cardType();

if (cardType == CARD_NONE) {
Serial.println("SDカードが接続されていません");
return;
}

Serial.print("SDカードの種類: ");
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("不明");
}

sd_sign = true;

Serial.println("写真撮影が間もなく始まります。準備してください。");
}

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("写真を保存しました: %s\r\n", filename);
Serial.println("10秒間ディープスリープに入ります...");

esp_sleep_enable_timer_wakeup(10000000);
esp_deep_sleep_start();

}
}
}

詳細な説明

このコードは、ESP32カメラモジュールを使用した画像キャプチャシステムを実装しており、60秒ごとに自動的に写真を撮影し、SDカードに保存します。void setup()関数では、カメラとSDカードが初期化され、デバイスの状態が確認されます。void loop()関数では、カメラが写真を撮影できるかどうかを確認し、条件が満たされた場合はphoto_save()関数を呼び出して画像を保存します。その後、エネルギーを節約するために10秒間ディープスリープ状態に入ります。

tip

これらのコードは直接使用することはできません。カメラに関するヘッダーファイルを追加する必要があります。上記のXIAO ESP32 S3の例を参照してください。

結論として

Deep Sleep モードを使用する理由

機能性を損なうことなく電力消費を最大限に抑えることで、デバイスのバッテリー寿命を延ばすことができます。
適したシナリオ:バッテリー寿命が重要なリモートセンサーノード、ウェアラブルデバイス、その他の低消費電力IoTデバイスなどのアプリケーション。ウェイクアップ時間が比較的遅いものの、このトレードオフは価値があります。

Modem Sleep モードを使用する理由

ネットワーク接続を維持しながら、ワイヤレス通信モジュールの電力消費を最適化します。
適したシナリオ:ネットワーク接続を維持しつつ低消費電力が求められる、断続的に動作するIoTデバイスなどのアプリケーション。Modem Sleepは、ワイヤレスモジュールの電力消費を大幅に削減しつつ、高速なウェイクアップ応答を提供します。

まとめ

これら3つのスリープモードは、開発者に対して異なる電力/性能のトレードオフオプションを提供し、アプリケーションの具体的な要件に基づいて柔軟に選択できます。バッテリー寿命が求められるデバイスにはDeep Sleepモードが適しており、ネットワーク接続を維持する必要があるIoTデバイスにはModem Sleepモードが最適な選択です。

技術サポートと製品ディスカッション

弊社製品をお選びいただきありがとうございます!製品をご利用いただく際に、できるだけスムーズな体験を提供できるよう、さまざまなサポートをご用意しています。異なる好みやニーズに対応するため、いくつかのコミュニケーションチャネルを提供しています。

Loading Comments...