M5Stamp S3でできること 〜M5Stamp S3の消費電流値(他のM5デバイスと比較)

スポンサーリンク
M5Stamp S3

先日、「M5Stamp S3」の使い方を確認しました(記事は こちら)。
M5Stack社のドキュメントページ(こちら)に従って作業を進めることで、問題なく環境構築ができました。

M5Stamp S3(Yahoo!ショッピング)

私はこの「M5Stamp S3」を、乾電池で長期間にわたり連続稼働のできる、低電力で安価なIoTデバイスとして活用したいと考えています。
これまでこのような用途には「M5Stamp Pico」を使ってきましたが、「M5Stamp Pico」にプログラムを書き込むには別途ダウンローダーが必要で、屋外でプログラムを書き換えたりする際の作業が若干面倒でした。「M5Stamp S3」に置き換えることでその作業が楽になることを期待しています。
そのためには、まず「M5Stamp S3」が「M5Stamp Pico」並みに低電力であることを確認する必要があります。

そんな訳で今回、「M5Stamp S3」の消費電力を調べてみたいと思います。

なお、私はこれまでにも、さまざまな低電力マイコンデバイス(ESP32)について、同等の調査を行ってきました。
ただ、それらの調査は条件がまちまちで、デバイス間の比較がしにくい状況でした。
今回改めて、これまで調査してきたデバイスについても、同じ条件で調査をやり直すことにします。

調査するのは以下のESP32デバイスです。

ESPr Developer 32一般的なESP32マイコンボード(比較対象)
M5Stack Basic V2.6一般的なESP32マイコンボード(比較対象)
M5Stamp Pico低電力なIoTデバイスとして活用
Timer Camera F低電力なカメラデバイスとして活用
ATOMS3低電力なディスプレイ付きIoTデバイスとして活用
M5Stamp S3今回の調査対象(M5Stamp Picoの代替)

それらに加えて、ESP32ではありませんが、私が低電力IoTデバイスとして活用できそうと考えている以下のデバイスについても調査します。

Raspberry Pi Pico WESP32以外の選択肢としてピックアップ
micro:bit V2.21子どもでも開発可能なIoTデバイス用としてピックアップ

開発環境のバージョンは以下のとおりです。

【ESP32デバイス】
Arduino IDEのバージョン1.8.19
esp32ボードのバージョン2.0.9
M5Stackボードのバージョン2.0.7
【Raspberry Pi Pico W】
Thonnyのバージョン4.0.2
UF2ファイルのバージョン1.19.1(20230329)
【micro:bit V2.21】
MakeCodeエディタのバージョン6.0.15
Power拡張機能のバージョン0.2.3

調査内容

条件を揃えるため、いずれのデバイスとも以下のような処理を行うこととします。

  • 起動したら「チップID」と「ランダムな値(3桁の整数を10で割った値)」をWebサーバに送信する。送信完了すると低電力モードに移行し、30秒たってから再起動、以降は同じ処理を繰り返す。
  • Ni-MH電池4本で動かす(micro:bitのみNi-MH電池2本)。電池接続場所は、屋外設置を想定した時に一番接続しやすい場所、もしくは接続が必要な理由がある場所とする。
  • 電池とデバイスの間に「INA226PRC」を挿入して電流波形を測定する(測定方法は こちら)。

ESPr Developer 32

電池を「VIN」端子と「GND」端子につなぎます。
Arduino IDEのボード設定で、「ツール」>「ボード」>「ESP32 Arduino」>「ESP32 Dev Module」を選択します。

スケッチはこちらです。

#include <WiFi.h>

const char*  ssid      = "XXXXXXXX";
const char*  password  = "XXXXXXXX";

unsigned long interval = 30; // unit:sec

boolean sendRequest(float val0) {
  : 省略
}

void setup() {
  Serial.begin(115200);
  esp_sleep_enable_timer_wakeup(interval*1000*1000);

  // Get Data
  float val0 = random(0, 1000) / 10.0;
  // Connect WiFi
  Serial.printf("Connecting to %s\n", ssid);
  WiFi.begin(ssid, password);
  while(WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.printf("\nWiFi connected\n");
  // Send Data
  if(!sendRequest(val0)) esp_deep_sleep_start();;
  Serial.println("Send request is finished.");

  esp_deep_sleep_start();
}

void loop() {}

M5Stack Basic V2.6

電池をUSBポート(電源端子名は「VIN_USB」)につなぎます。
「M5Stack Basic」にはバッテリーが内蔵されており、このバッテリーへの充放電があると本体での電流消費が分からなくなるため、充放電をしないように「ボトム」を外しておきます。
Arduino IDEのボード設定で、「ツール」>「ボード」>「M5Stack Arduino」>「M5Stack-Core-ESP32」を選択します。

スケッチはこちらです。

#include <M5Stack.h>
#include <WiFi.h>

const char*  ssid      = "XXXXXXXX";
const char*  password  = "XXXXXXXX";

unsigned long interval = 30; // unit:sec

boolean sendRequest(float val0) {
  : 省略
}

void setup() {
  M5.begin();
  esp_sleep_enable_timer_wakeup(interval*1000*1000);

  // Get Data
  float val0 = random(0, 1000) / 10.0;
  M5.Lcd.clear();
  M5.Lcd.setTextDatum(4);
  M5.Lcd.drawFloat(val0, 1, M5.Lcd.width()/2,  M5.Lcd.height()/2, 7);
  // Connect WiFi
  Serial.printf("Connecting to %s\n", ssid);
  WiFi.begin(ssid, password);
  while(WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.printf("\nWiFi connected\n");
  // Send Data
  if(!sendRequest(val0)) esp_deep_sleep_start();;
  Serial.println("Send request is finished.");

  esp_deep_sleep_start();
}

void loop() {}

M5Stamp Pico

電池をGROVEポート(電源端子名は「SYS_P050」)につなぎます。
Arduino IDEのボード設定で、「ツール」>「ボード」>「M5Stack Arduino」>「STAMP-PICO」を選択します。

スケッチはこちらです。

#include <FastLED.h>
#include <WiFi.h>

#define NUM_LEDS 1
#define LED_PIN 27
CRGB leds[NUM_LEDS];

const char*  ssid      = "XXXXXXXX";
const char*  password  = "XXXXXXXX";

unsigned long interval = 30; // unit:sec

boolean sendRequest(float val0) {
  : 省略
}

void setup() {
  Serial.begin(115200);
  esp_sleep_enable_timer_wakeup(interval*1000*1000);

  FastLED.addLeds<SK6812, LED_PIN, GRB>(leds, NUM_LEDS);
  leds[0] = CRGB::Green;
  FastLED.show();

  // Get Data
  float val0 = random(0, 1000) / 10.0;
  // Connect WiFi
  Serial.printf("Connecting to %s\n", ssid);
  WiFi.begin(ssid, password);
  while(WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.printf("\nWiFi connected\n");
  // Send Data
  if(!sendRequest(val0)) esp_deep_sleep_start();;
  Serial.println("Send request is finished.");

  leds[0] = CRGB::Black;
  FastLED.show();
  esp_deep_sleep_start();
}

void loop() {}

Timer Camera F

「Timer Camera F」を低電力で動作させるため、「Timer Camera F」から内蔵バッテリーを取り外し、元々は内蔵バッテリーがつながっていたコネクタ(電源端子名は「VBAT_VIN」)に電池をつなぎます(処理内容の詳細については こちら)。
Arduino IDEのボード設定で、「ツール」>「ボード」>「M5Stack Arduino」>「M5Stack-Timer-CAM」を選択します。
なお、今回のArduino IDE環境で「Timer-CAM」ライブラリ(0.0.3)を利用すると、デバイス起動時にエラーが発生してしまいました。回避策として「Timer-CAM」ライブラリにて「src/bmm8563.c」内の「i2c_init()」に「conf.clk_flags = 0;」という記述を追加する必要があります(詳しくは こちら)。

スケッチはこちらです。

#include "battery.h"
#include "bmm8563.h"
#include <WiFi.h>

const char*  ssid      = "XXXXXXXX";
const char*  password  = "XXXXXXXX";

unsigned long interval = 30; // unit:sec

boolean sendRequest(float val0) {
  : 省略
}

void setup() {
  Serial.begin(115200);
  bat_init();
  bmm8563_init();
  bmm8563_setTimerIRQ(interval);
  esp_sleep_enable_timer_wakeup(interval*1000*1000);

  pinMode(2, OUTPUT);
  digitalWrite(2, HIGH);

  // Get Data
  float val0 = random(0, 1000) / 10.0;
  // Connect WiFi
  Serial.printf("Connecting to %s\n", ssid);
  WiFi.begin(ssid, password);
  while(WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.printf("\nWiFi connected\n");
  // Send Data
  if(!sendRequest(val0)) {
    bat_disable_output();
    esp_deep_sleep_start();;
  }
  Serial.println("Send request is finished.");

  digitalWrite(2, LOW);
  bat_disable_output();
  esp_deep_sleep_start();
}

void loop() {}

ATOMS3

電池をGROVEポートにつなぎます(「ATOMS3」の回路図が見つからなかったため、電源端子名は分かりません)。
Arduino IDEのボード設定で、「ツール」>「ボード」>「M5Stack Arduino」>「M5Stack-ATOMS3」を選択します。

スケッチはこちらです。

#include <M5AtomS3.h>
#include <WiFi.h>

const char*  ssid      = "XXXXXXXX";
const char*  password  = "XXXXXXXX";

unsigned long interval = 30; // unit:sec

boolean sendRequest(float val0) {
  : 省略
}

void setup() {
  M5.begin(true, true, false, false);
  esp_sleep_enable_timer_wakeup(interval*1000*1000);

  // Get Data
  float val0 = random(0, 1000) / 10.0;
  M5.Lcd.clear();
  M5.Lcd.setTextDatum(4);
  M5.Lcd.drawFloat(val0, 1, M5.Lcd.width()/2,  M5.Lcd.height()/2, 7);
  // Connect WiFi
  USBSerial.printf("Connecting to %s\n", ssid);
  WiFi.begin(ssid, password);
  while(WiFi.status() != WL_CONNECTED) {
    delay(500);
    USBSerial.print(".");
  }
  USBSerial.printf("\nWiFi connected\n");
  // Send Data
  if(!sendRequest(val0)) esp_deep_sleep_start();;
  USBSerial.println("Send request is finished.");

  esp_deep_sleep_start();
}

void loop() {}

M5Stamp S3

電池をUSBポート(電源端子名は「VIN_5V」)につなぎます。
なお、GROVEポートの電源端子も同じ「VIN_5V」なので、もしも「M5Stamp S3」にGROVEポートを取り付けているのであれば、そちらに電池をつないでも同じです。
Arduino IDEのボード設定で、「ツール」>「ボード」>「M5Stack Arduino」>「STAMP-S3」を選択します。

スケッチはこちらです。

#include <FastLED.h>
#include <WiFi.h>

#define NUM_LEDS 1
#define LED_PIN 21
CRGB leds[NUM_LEDS];

const char*  ssid      = "XXXXXXXX";
const char*  password  = "XXXXXXXX";

unsigned long interval = 30; // unit:sec

boolean sendRequest(float val0) {
  : 省略
}

void setup() {
  USBSerial.begin(115200);
  esp_sleep_enable_timer_wakeup(interval*1000*1000);

  FastLED.addLeds<WS2812, LED_PIN, GRB>(leds, NUM_LEDS);
  leds[0] = CRGB::Green;
  FastLED.show();

  // Get Data
  float val0 = random(0, 1000) / 10.0;
  // Connect WiFi
  USBSerial.printf("Connecting to %s\n", ssid);
  WiFi.begin(ssid, password);
  while(WiFi.status() != WL_CONNECTED) {
    delay(500);
    USBSerial.print(".");
  }
  USBSerial.printf("\nWiFi connected\n");
  // Send Data
  if(!sendRequest(val0)) esp_deep_sleep_start();;
  USBSerial.println("Send request is finished.");

  leds[0] = CRGB::Black;
  FastLED.show();
  esp_deep_sleep_start();
}

void loop() {}

Raspberry Pi Pico W

電池をUSBポート(電源端子名は「VBUS」)につなぎます。

プログラムはこちらです。

import machine
import time
import network
import urequests
import random

led = machine.Pin("LED", machine.Pin.OUT)
led.value(1)

ssid = 'XXXXXXXX'
password = 'XXXXXXXX'

machine.Pin(23, machine.Pin.OUT).high()
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
chipid = int.from_bytes(wlan.config('mac'), 'big') % 65536
wlan.connect(ssid, password)

max_wait = 10
while max_wait > 0:
    if wlan.status() < 0 or wlan.status() >= 3:
        break
    max_wait -= 1
    print('waiting for connection...')
    time.sleep(1)
    
if wlan.status() != 3:
    raise RuntimeError('network connection failed')
else:
    print('connected')
    status = wlan.ifconfig()
    print('ip = ' + status[0])

while True:
    led.value(1)
    value = random.randint(0, 999) / 10
    url = "http://XXXXXXXX?chipid=RPI" + str(chipid) + "&val0=" + str(value)
    r = urequests.get(url)
    print(r.content)
    r.close()
    led.value(0)
    wlan.disconnect()
    wlan.active(False)
    machine.Pin(23, machine.Pin.OUT).low()
    machine.deepsleep(30000)

micro:bit V2.2

電池を電池接続用のPHポートにつなぎます。
今回はNi-MH電池2本をつなぎますが、このポートであればNi-MH電池3本を供給することも可能なようです(詳しくは こちら)。
micro:bitにはWi-Fi通信機能などはありませんので、micro:bit独自の「無線」機能で別のmicro:bit(親機)にデータを送信することとします。
電源のある場所に設置したmicro:bit親機をESP32などと有線でつないでおき、ESP32経由でWebサーバにデータ送信することを想定しています(詳しくは こちら)。

プログラムはこちらです。

調査結果

それぞれのデバイスについて処理を4回ずつ行い、その時の消費電流の変化を重ねてグラフ表示しました。
Wi-Fi接続できるまでの時間によって処理時間も変わってきますが、各回の処理時間にばらつきがあると結果比較が難しくなるので、今回は速やかにWi-Fi接続できるよう、Wi-Fiルータの近くで調査を実施しました。

ESPr Developer 32

M5Stack Basic V2.6

M5Stamp Pico

Timer Camera F

ATOMS3

M5Stamp S3

Raspberry Pi Pico W

micro:bit V2.2

結果比較

先ほどの消費電流グラフやその他のデータから、1回の処理にかかる時間やその間の消費電流値などをまとめてみました。
なお「Timer Camera F」については、今回の調査方法では待機時の消費電流値がマイナスになってしまいましたので、表にはゼロと記載しています。

処理時間(ms)消費電流(mA)電源電圧(V)消費電力(mW)
動作時待機時動作時待機時動作時待機時
ESPr Developer 321081.582.840.125.465.70452.310.68
M5Stack Basic V2.61370.596.7216.045.325.60514.5589.82
M5Stamp Pico867.058.340.605.375.65313.293.39
Timer Camera F1248.082.190.005.365.70440.540.00
ATOMS31707.561.480.095.435.65333.840.51
M5Stamp S3822.559.050.285.395.55318.281.55
Raspberry Pi Pico W2751.054.241.405.435.59294.527.83
micro:bit V2.21378.015.342.122.712.8141.575.96

「M5Stamp Pico」や「M5Stamp S3」は、その他のデバイスに比べて、1回の処理にかかる時間、その間の平均消費電流値ともに、やや小さな結果となりました。
また「Raspberry Pi Pico W」や「micro:bit V2.21」の待機時の消費電流値は、M5Stack社の低電力デバイスに比べるとやや大きくなっています(「M5Stack Basic V2.6」に比べると格段に小さいですが)。

一定時間間隔で間欠動作させた時の平均消費電流値を机上計算しました。

間欠動作時の平均消費電流値(mA)
1分毎10分毎1時間毎
ESPr Developer 321.610.270.14
M5Stack Basic V2.617.8816.2216.07
M5Stamp Pico1.430.680.61
Timer Camera F1.710.170.03
ATOMS31.840.260.12
M5Stamp S31.090.360.29
Raspberry Pi Pico W3.821.641.44
micro:bit V2.212.202.132.12

また、この結果を元に、単三型Ni-MH電池(2000mAh)での稼働日数を机上計算しました。
2023年7月時点のスイッチサイエンスでの販売価格も併記しておきました。

価格(円)単三型Ni-MH電池での稼働日数
1分毎10分毎1時間毎
ESPr Developer 32220051.7309.7575.3
M5Stack Basic V2.656654.75.15.2
M5Stamp Pico96858.1121.9135.7
Timer Camera F299248.7487.52924.7
ATOMS3247545.4314.8699.6
M5Stamp S3123276.8231.1284.0
Raspberry Pi Pico W126521.850.757.9
micro:bit V2.21292637.839.239.3

「M5Stamp S3」は期待どおりの低電力で、1分間隔で動作させても、単三型Ni-MH電池4本で2ヶ月以上連続稼働できるという結果になりました。
その他も、「M5Stamp Pico」「Timer Camera F」「ATOMS3」「M5Stamp S3」「micro:bit V2.2」のいずれも1ヶ月以上、他に比べるとやや劣る「Raspberry Pi Pico W」でも3週間と、これまで低電力デバイスとして使ってきた製品や、今後低電力デバイスとして活用していこうと考えている製品はいずれも、充分長い期間にわたり連続稼働できる見込みです。

なお、今回気になった点として、「ATOMS3」の消費電流(特に待機時)が非常に小さい点が挙げられます。
「ATOMS3」の価格は「M5Stamp S3」の倍なので、「M5Stamp S3」をそのまま「ATOMS3」に代替するということにはならなそうですが、「ATOMS3」の類似製品である「ATOMS3 Lite」であれば価格も1408円と「M5Stamp S3」に近く、最初からGROVEポートも付いているので、GROVEセンサを使うような用途には「ATOMS3 Lite」が最適かもしれません。
「ATOMS3 Lite」はまだ持っていないので、近いうちに同様の調査をしてみたいと思います。

(追記)ATOMS3 Lite

前述のとおり、低電力用途のIoTデバイスとしては、ここまで調査してきたもの以外に「ATOMS3 Lite」も選択肢となりそうです。
先日「ATOMS3 Lite」を購入したので、同様の調査を行ってみました。

電池はGROVEポートにつなぎます(「ATOMS3 Lite」の回路図が見つからなかったため、電源端子名は分かりません)。
Arduino IDEのボード設定で、「ツール」>「ボード」>「M5Stack Arduino」>「M5Stack-ATOMS3」を選択します。

スケッチはこちらです。

#include <M5AtomS3.h>
#include <WiFi.h>

const char*  ssid      = "XXXXXXXX";
const char*  password  = "XXXXXXXX";

unsigned long interval = 30; // unit:sec

boolean sendRequest(float val0) {
  : 省略
}

void setup() {
  M5.begin(false, true, false, true); // LCD, Serial, I2C, LED
  esp_sleep_enable_timer_wakeup(interval*1000*1000);

  M5.dis.drawpix(0xff0000);
  M5.dis.show();

  // Get Data
  float val0 = random(0, 1000) / 10.0;
  // Connect WiFi
  USBSerial.printf("Connecting to %s\n", ssid);
  WiFi.begin(ssid, password);
  while(WiFi.status() != WL_CONNECTED) {
    delay(500);
    USBSerial.print(".");
  }
  USBSerial.printf("\nWiFi connected\n");
  // Send Data
  if(!sendRequest(val0)) esp_deep_sleep_start();;
  USBSerial.println("Send request is finished.");

  M5.dis.clear();
  M5.dis.show();
  esp_deep_sleep_start();
}

void loop() {}

調査結果(消費電流波形グラフ)はこちらです。

他のデバイスとの比較結果は以下のとおりです。

処理時間(ms)消費電流(mA)電源電圧(V)消費電力(mW)
動作時待機時動作時待機時動作時待機時
ESPr Developer 321081.582.840.125.465.70452.310.68
M5Stack Basic V2.61370.596.7216.045.325.60514.5589.82
M5Stamp Pico867.058.340.605.375.65313.293.39
Timer Camera F1248.082.190.005.365.70440.540.00
ATOMS31707.561.480.095.435.65333.840.51
ATOMS3 Lite1420.546.790.335.575.74260.621.89
M5Stamp S3822.559.050.285.395.55318.281.55
Raspberry Pi Pico W2751.054.241.405.435.59294.527.83
micro:bit V2.21378.015.342.122.712.8141.575.96
間欠動作時の平均消費電流値(mA)
1分毎10分毎1時間毎
ESPr Developer 321.610.270.14
M5Stack Basic V2.617.8816.2216.07
M5Stamp Pico1.430.680.61
Timer Camera F1.710.170.03
ATOMS31.840.260.12
ATOMS3 Lite1.430.440.35
M5Stamp S31.090.360.29
Raspberry Pi Pico W3.821.641.44
micro:bit V2.212.202.132.12
価格(円)単三型Ni-MH電池での稼働日数
1分毎10分毎1時間毎
ESPr Developer 32220051.7309.7575.3
M5Stack Basic V2.656654.75.15.2
M5Stamp Pico96858.1121.9135.7
Timer Camera F299248.7487.52924.7
ATOMS3247545.4314.8699.6
ATOMS3 Lite149658.3189.4239.2
M5Stamp S3123276.8231.1284.0
Raspberry Pi Pico W126521.850.757.9
micro:bit V2.21292637.839.239.3

期待していたとおり、「ATOMS3 Lite」も、「M5Stamp S3」やその他の低電力デバイスと比べても遜色のない結果になりました。
価格も「M5Stamp S3」と大差ないので、外付けデバイスを接続する際の都合(GROVEポートの有無、はんだつけの要不要)などで使用するデバイスを選択すればよさそうです。

 

なお、私がM5Stack、M5StickCの使い方を習得するのにあたっては、以下の書籍を参考にさせていただきました。


ごく基本的なところから、かなり複雑なスケッチや、ネットワーク接続など、比較的高度なものまで、つまづかずに読み進めていけるような構成になっており、大変わかりやすい本です。