これまで、M5Stack社製のいくつかのマイコンデバイスを使ってIoTデバイスをつくってきました。
今回、あらたにつくりたいIoTデバイスがあるのですが、その仕様は以下のようなものです。
- 1日に数回だけデータを測定し、そのデータをインターネット上のサーバに送信したい。
- GROVEポートに外付けデバイスを接続したい(具体的には、モバイル通信のための「CAT-Mモジュール)を接続したい」。
- 乾電池駆動で、できるだけ長期間連続稼働させたい。
この仕様を実現するためには、以下のようなIoTデバイスが必要です。
- スリープ中は、できるだけ多くの部分への電源供給を遮断したい。
- スリープ中は、GROVEポートから外付けデバイスへの電源供給を遮断したい。
これまで使ってきた各マイコンデバイスについて調べたのですが、ほとんどのデバイスはマイコンへ電源供給するための電源端子とGROVEポートの電源端子が直結でした(GROVEポートからもマイコンへ電源供給できるようになっています)。
このような状態では、いくらマイコンデバイスをスリープ状態にしても、GROVEポートにつながっている外付けデバイスが電力消費をし続けてしまうため、電池は短期間しか保ちません。
いろいろと調べているうちに「M5StickS3」という製品を見つけました。
M5StickS3には「M5PM1」という仕組みが搭載されており、パワーマネジメントの機能が充実しているようです。
最も低電力のモードでは、電源制御用IC以外への電源供給を全て遮断することができ、何よりありがたいのは、プログラムからの制御でGROVEポートの電源端子からの電源供給をON/OFFできることです。
今回実現したい用途にはうってつけのデバイスです。
そんな訳で、早速試してみることにしました。
HATの「5VIN」端子に乾電池(単三Ni-MH電池4本)をつなぎます。GROVEポートの電源端子を電源出力として使いたい場合は、この端子もしくはUSBポートから電源供給する必要があるようです。
HATの「EXT5V」端子に抵抗内蔵型LEDを接続します。この「EXT5V」はGROVEポートの電源端子と同一ノードです。
乾電池とM5StickS3の間に、別途用意した電流観測用のデバイス(詳しくは こちら)を挿入します。これで、M5StickS3と外付けデバイス(今回はLED)で消費した電流を観測できるはずです(写真では右上のM5Stackと緑色の基板が電流観測用デバイスになります)。

スケッチはこちらです。
#include <M5Unified.h>
#include <M5PM1.h>
M5PM1 pm1;
unsigned long prevTime = 0;
int w, h;
void setup() {
auto cfg = M5.config();
M5.begin(cfg);
M5.Display.setRotation(1);
w = M5.Display.width();
h = M5.Display.height();
M5.Display.fillScreen(TFT_BLACK);
M5.Display.setTextColor(TFT_WHITE);
M5.Display.setTextFont(&fonts::Font2);
M5.Display.setTextDatum(ML_DATUM);
pm1.begin(&M5.In_I2C, M5PM1_DEFAULT_ADDR, M5PM1_I2C_FREQ_100K);
M5.Power.setExtOutput(false);
M5.Power.setBatteryCharge(false);
}
void loop() {
M5.update();
if(M5.BtnA.wasPressed()) {
M5.Power.setExtOutput(!M5.Power.getExtOutput());
}
if(M5.BtnB.wasPressed()) {
// M5.Display.fillScreen(TFT_BLACK);
pm1.timerSet(10, M5PM1_TIM_ACTION_POWERON);
pm1.shutdown();
}
unsigned long currentTime = millis();
if(currentTime - prevTime >= 1000) {
M5.Display.clear();
String str1 = "BATTERY CHARGING : " + String(M5.Power.isCharging() ? "YES" : "NO");
String str2 = "BATTERY LEVEL : " + String(M5.Power.getBatteryLevel()) + "%";
String str3 = "BATTERY VOLTAGE : " + String(M5.Power.getBatteryVoltage()) + "mV";
String str4 = "EXT5V OUT : " + String(M5.Power.getExtOutput() ? "ON" : "OFF");
M5.Display.drawString(str1, w/8*1, h/8*1);
M5.Display.drawString(str2, w/8*1, h/8*2);
M5.Display.drawString(str3, w/8*1, h/8*3);
M5.Display.drawString(str4, w/8*1, h/8*7);
prevTime = currentTime;
}
}
Aボタンを押すと「EXT5V」からの電源供給をON/OFFできます。この制御には「M5.Power.setExtOutput()」という関数を使います。これは「M5Unified」ライブラリで用意されているものです。
Bボタンを押すと、再起動までの時間を10秒にセットした上でシャットダウンします。「pm1.timerSet()」「pm1.shutdown()」という関数を使います。これらは「M5PM1」ライブラリで用意されているようです。
なお、M5StickS3にはバッテリーが内蔵されており、このバッテリーへの充放電により、消費電流を正確に観測できません。
そのため、今回は「M5.Power.setBatteryCharge()」という関数を使ってバッテリーへの充電をOFFにしています。バッテリーからの放電を制御する仕組みはありませんので、バッテリーをできるだけ空に近い状態にして、バッテリーの影響を小さくしています。
このデバイスを動作させ、消費電流波形を観測した結果は以下のとおりです。

おおよそ10秒ごとに、以下のように遷移しています。
- デバイスを起動、GROVE電源端子はOFF
- Bボタンを押してシャットダウン(10秒のスリープ)
- 自動的にデバイス再起動、GROVE電源端子はOFF
- GROVE電源端子をON(LEDが点灯する)
- Bボタンを押してシャットダウン(LEDが消灯する)
各状態の平均消費電流値は以下のとおりです。
| デバイス動作中、GROVE出力端子OFF(LED消灯) | 64.86mA |
| デバイス動作中、GROVE出力端子ON(LED点灯) | 125.51mA |
| シャットダウン中(スリープ中) | 0mA |
今回の調査で、以下のことが確認できました。
- スリープ中は非常に低消費電力になる。
- スリープ中は、GROVEポートの電源端子からの電源供給が遮断される。
- プログラムで、GROVEポートの電源端子からの電源供給をON/OFFできる。
当初の期待どおりの結果が得られました。今回つくりたいIoTデバイスにも適用できそうな見込みです。