🔌
M5StickC Plus2の省電力化
やったこと
M5StickC Plus2の省電力化を目的に以下を実施して、電源が切れるまでの時間を調査した。
検証
常時Wi-Fiに接続している状態で毎秒mqttでjsonを送信し、バッテリーがなくなるまで秒数を記録した。
今回は4つのパターンでバッテリーの持ち時間を確認した。
- 何も行わない(バックライトの輝度=50)
- バックライトの輝度=0
- LCDをスリープ
- CPUを80MHz(Wi-Fiが使える最低の周波数) + 5V出力を無効化
検証結果
1.の条件で輝度を50にしてしまったことが原因である可能性はあるが、バックライトのみを変更しても結果に差はなかった。一方で、3.と4.の有効性は確認することができた。

検証用のコード
Aボタンを押すごとにモードが切り替わる仕様にした。
#include <Arduino.h>
#include <M5Unified.h>
#include <WiFi.h>
#include <PubSubClient.h>
// ======== Wi-Fi設定 ========
const char* WIFI_SSID = "ssid";
const char* WIFI_PASSWORD = "password";
// ======== MQTT設定 ========
const char* MQTT_HOST = "192.168.1.108"; // ←ブローカのIPに変更
const uint16_t MQTT_PORT = 1883;
const char* MQTT_CLIENT_ID = "M5StickCPlus2_BatteryTest";
const char* MQTT_TOPIC = "test/m5stickcplus2/battery";
// ======== グローバル ========
WiFiClient espClient;
PubSubClient mqttClient(espClient);
unsigned long lastPublishMs = 0;
unsigned long publishIntervalMs = 1000; // 1秒間隔
uint32_t seq = 0; // 送信カウンタ
// ecoMode: 0=通常, 1=バックライトのみOFF, 2=LCD OFF, 3=CPU80MHz+5V出力無効化
int ecoMode = 0;
const int ECO_MODE_NORMAL = 0;
const int ECO_MODE_BACKLIGHT_OFF = 1;
const int ECO_MODE_LCD_OFF = 2;
const int ECO_CPU = 3;
uint8_t normalBrightness = 50; // 通常モード時の明るさ
uint8_t ecoBrightness = 5; // (使いたければ省エネ時の明るさに利用)
// ---------- Wi-Fi接続 ----------
void connectWiFi() {
M5_LOGI("Connecting to WiFi: %s", WIFI_SSID);
WiFi.mode(WIFI_STA);
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
M5_LOGI("WiFi connecting...");
}
M5_LOGI("WiFi connected: %s", WiFi.localIP().toString().c_str());
}
// ---------- MQTT接続 ----------
void connectMQTT() {
mqttClient.setServer(MQTT_HOST, MQTT_PORT);
while (!mqttClient.connected()) {
M5_LOGI("Connecting to MQTT...");
if (mqttClient.connect(MQTT_CLIENT_ID)) {
M5_LOGI("MQTT connected");
} else {
M5_LOGW("Failed MQTT connect, rc=%d. Retry in 2s", mqttClient.state());
delay(2000);
}
}
}
// ---------- 画面表示 ----------
void updateDisplay() {
// LCD OFF モードのときは描画しない(見えないため)
if (ecoMode == ECO_MODE_LCD_OFF) {
return;
}
M5.Display.fillScreen(BLACK);
M5.Display.setCursor(0, 0);
M5.Display.setTextSize(1);
M5.Display.println("Battery test");
M5.Display.println("1 msg / second");
M5.Display.println("");
if (ecoMode == ECO_MODE_NORMAL) {
M5.Display.println("Mode: NORMAL (0)");
} else if (ecoMode == ECO_MODE_BACKLIGHT_OFF) {
M5.Display.println("Mode: BACKLIGHT OFF (1)");
} else if (ecoMode == ECO_MODE_LCD_OFF) {
M5.Display.println("Mode: LCD OFF (2)");
} else if (ecoMode == ECO_CPU) {
M5.Display.println("Mode: CPU80MHz+Not 5V OUT (3)");
}
M5.Display.println("");
M5.Display.println("Btn A: change mode");
}
// ---------- モード適用 ----------
void applyMode() {
switch (ecoMode) {
case ECO_MODE_NORMAL:
// LCDの電源ON・バックライトON
M5.Display.wakeup(); // LCDは有効
M5.Display.setBrightness(normalBrightness);
updateDisplay();
break;
case ECO_MODE_BACKLIGHT_OFF:
// LCDは動かすが、バックライトのみOFF
M5.Display.wakeup(); // LCDは有効
M5.Display.setBrightness(0); // 見た目は真っ暗
// 明るさ戻したとき用に中身は描いておく
updateDisplay();
break;
case ECO_MODE_LCD_OFF:
// LCD自体をパワーセーブ(さらに省電力)
M5.Display.sleep(); // 念のためバックライトも0
M5.Display.setBrightness(0); // 見た目は真っ暗
// このモードでは updateDisplay() は呼ばない
break;
case ECO_CPU:
M5.Display.wakeup(); // LCDは有効
M5.Display.setBrightness(normalBrightness);
setCpuFrequencyMhz(80);
M5.Power.setExtOutput(false);
updateDisplay();
break;
}
}
// ---------- メッセージ送信 ----------
void publishBattery() {
seq++;
// バッテリー残量(%)
int8_t batLevel = M5.Power.getBatteryLevel();
// ecoModeに応じた文字列
const char* modeStr = "normal";
if (ecoMode == ECO_MODE_BACKLIGHT_OFF) {
modeStr = "backlight_off";
} else if (ecoMode == ECO_MODE_LCD_OFF) {
modeStr = "lcd_off";
} else if (ecoMode == ECO_CPU) {
modeStr = "80MHz";
}
// JSON生成
// 例: {"seq":1,"battery":78,"millis":12345,"ecoMode":1,"mode_str":"backlight_off"}
char payload[192];
snprintf(
payload,
sizeof(payload),
"{\"seq\":%lu,\"battery\":%d,\"millis\":%lu,\"ecoMode\":%d,\"mode_str\":\"%s\"}",
(unsigned long)seq,
(int)batLevel,
(unsigned long)millis(),
ecoMode,
modeStr
);
bool ok = mqttClient.publish(MQTT_TOPIC, payload);
if (!ok) {
M5_LOGW("MQTT publish failed");
} else {
M5_LOGI("Published: %s", payload);
}
}
// ---------- 初期化 ----------
void setup() {
auto cfg = M5.config();
M5.begin(cfg);
M5.Display.setBrightness(normalBrightness);
ecoMode = ECO_MODE_NORMAL;
applyMode();
connectWiFi();
connectMQTT();
lastPublishMs = millis();
}
// ---------- メインループ ----------
void loop() {
M5.update();
// Aボタンで ecoMode を 0→1→2→0… とローテーション
if (M5.BtnA.wasPressed()) {
ecoMode = (ecoMode + 1) % 4;
applyMode();
}
// MQTT接続確認
if (!mqttClient.connected()) {
connectMQTT();
}
mqttClient.loop();
// 1秒ごとに送信
unsigned long now = millis();
if (now - lastPublishMs >= publishIntervalMs) {
lastPublishMs = now;
publishBattery();
}
delay(1);
}
Discussion