Seeed Studio XIAO ESP32C3のMQTT送信(省電力)

Seeed K.K.の松岡です。
Seeed Studio XIAO ESP32C3のMQTT送信では、MQTTサーバーへパブリッシュ(送信)できました。今回は、これをESP32C3のディープスリープ機能を使って省電力にしたいと思います。

ESP32-C3のスリープ

Seeed Studio XIAO ESP32C3のCPU、ESP32-C3は、消費電力を抑えるモデムスリープライトスリープディープスリープというモードを持っています。モデムスリープはWi-FiとBLEを停止して、CPUを低速にして消費電流を減らします。ライトスリープとディープスリープは、CPUなどを停止(スリープ)して、グッと消費電流を減らします。GPIOやタイマー、UARTといったウェイクアップを検知するとスリープから復帰してプログラムが稼働します。ライトスリープはスリープした箇所から復帰しますが、ディープスリープはプログラムの最初から開始します。そのため、ディープスリープは扱いにくいのですが、ライトスリープよりも消費電流は少ないです。

ESP32-C3 Series Datasheetから引用:

もっと詳しく知りたい方は、こちらをご参照ください。
* ESP32-C3 Series Datasheet
* ESP-IDF Programming Guide - Sleep Modes

作ったもの

作ったものがこちらです。

github.com

MqttsPubClient.inoを、ディープスリープ機能を使うように変更しました。

実装のポイント

SNTPサーバーとの時刻同期と一定時間間隔の実装を変更しました。

省電力前と後のフロー比較:

一定時間間隔を実現しているdelay()を、RTCタイマーのウェイクアップ時間指定esp_sleep_enable_timer_wakeup()とディープスリープ遷移esp_deep_sleep_start()に変更します。

const int sleepSec = StartTime == 0 ? 0 : INTERVAL - (time(nullptr) - StartTime) % INTERVAL;
esp_sleep_enable_timer_wakeup(sleepSec * 1000 * 1000);
esp_deep_sleep_start();

これだけでは、ディープスリープからウェイクアップ後、sleepSecを正しく計算することができなくなりました。RAMで保持していたStartTimeが消えてしまうからです。StartTimeRTC_DATA_ATTRを付けて、StartTimeをディープスリープしても保持するRTC RAMに変更します。

static RTC_DATA_ATTR time_t StartTime = 0;

以上でMQTT送信は機能しますが、毎回、SNTPサーバーと時刻同期するのがちょっと過剰で気になりますね。無駄に通信していて気分悪いです。

SNTP_UPDATE_DELAYに応じて時刻同期するよう、NextSyncTimeをRTC RAMに保持して、時刻同期の指示を実装しておきましょう。

bool synced = NextSyncTime != 0 && time(nullptr) < NextSyncTime;
if (!synced)
{
    ...
    configTzTime(getenv("TZ"), SNTP_SERVER);

    elapsedMillis syncElapsed;
    while (syncElapsed < TIME_SYNC_TIMEOUT)
    {
        if (!TimeSyncCompleted)
        {
            delay(SPIN_WAIT);
        }
        else
        {
            synced = true;
            break;
        }
    }
    if (!synced)
    {
        ...
    }
    else
    {
        ...
        NextSyncTime = time(nullptr) + SNTP_UPDATE_DELAY;
    }
}

実行結果

5V電源供給の消費電流を確認しました。
平均30mAだったのが、ディープスリープを使うことで平均4.3mAに下がりました。

ディープスリープでCPU停止しているときは、約130uAでした。

消費電流波形の拡大図はREADME.mdに掲載しました。

Wi-FiのRSSIは-30程度でした。(先回よりも高いのは、実験に使ったWi-Fiアクセスポイントを変更したからです。)

データ欠損は1440件のうち11件でした。Wi-Fiアクセスポイントに都度接続が影響しているのか?それとも環境の影響なのか?QoS2にするとどうなるのか気になりますね。

まとめ

  • ディープスリープを使うとMQTT+TLS パブリッシュが平均30mAから平均4.3mA。(5V電源供給、送信間隔1分)
  • ディープスリープ中は約130uA。(5V電源供給)
  • データ欠損が増えた。(1440件のうち1件→11件。)

変更履歴

日付 変更者 変更内容
2022/9/18 松岡 作成