0. パワーオフとは
公式ドキュメントに記載があります。
電源オフ:USB 外部電源なしの時、"BUTTON C" を 6 秒以上長押し。
または USB 無しでプログラム中に HOLD(GPIO4)=0 に設定しシャットダウン。
USB 接続時は "BUTTON C" を 6 秒以上長押ししても断電せず スクリーンオフでスリープ状態。
以前投稿したM5StickC Plus2 で NTP時計を 内蔵のバッテリーで連続稼働させた場合、2時間13分ちょっと 動作しました。実際は、毎日起動して「秒を少しだけ確認」して すぐに電源オフしているのですが、ボタンCを6秒以上長押しすることは意外と面倒です。
そこで、「HOLD=0 に設定しシャットダウン」させる テクニックを組み込みました。
1. Bボタンが押されたらパワーオフする
前出の「HOLD=0 に設定しシャットダウン」を実装します。契機は「Bボタンが押されたとき」とします。
- 準備
setup()の先頭でパワーHOLD
(GPIO4をデジタル出力モードに設定、HIGHを設定)//setup pinMode(GPIO4, OUTPUT); // Set HOLD pin as an output digitalWrite(GPIO4, HIGH); // Power HOLD
- loop()内でBボタン判定、押されていたらパワーオフ
(GPIO4をLOWに設定)注)USB-Cに電源が接続されている場合は、パワーオフしません。// Bボタンが押されたらPower Off if (M5.BtnB.wasPressed()) { digitalWrite(GPIO4, LOW); // Power Off }
使い勝手が 良くなりました✌️
2. NTP時計のコード全体
前回から、次の2点を変更しました。
- Bボタンを判定しパワーオフ
- 年月日の表示形式の変更
ntp-clock2.ino
#include <M5StickCPlus2.h>
#include <WiFi.h>
#include <time.h>
#include <esp_sntp.h>
// Wi-Fi 設定(自分のWi-Fi情報に変更)
const char* ssid = "YOUR_WIFI_SSID"; // Wi-FiのSSID
const char* password = "YOUR_WIFI_PASS"; // Wi-Fiのパスワード
// NTPサーバー設定
const char* ntpServer1 = "jp.pool.ntp.org";
const char* ntpServer2 = "ntp.nict.jp";
bool showClock = false; // 時計を表示するフラグ
struct tm timeInfo;
int lastSec;
const int GPIO4 = 4; //HOLD pin Hi:Power-ON, Lo:Power-OFF
void setup() {
pinMode(GPIO4, OUTPUT); // Set HOLD pin as an output
digitalWrite(GPIO4, HIGH); // Power HOLD
M5.begin();
M5.Lcd.setRotation(3);
M5.Lcd.fillScreen(BLACK);
M5.Lcd.setTextColor(WHITE);
M5.Lcd.setTextSize(2);
// 起動時のメッセージ
M5.Lcd.println("Connecting to Wi-Fi.");
// Wi-Fi 接続
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
M5.Lcd.print(".");
delay(500);
}
M5.Lcd.println("\nWi-Fi Connected!");
// NTPで時刻を同期
configTzTime("JST-9", ntpServer1, ntpServer2);
// 同期周期を取得
auto default_interval = sntp_get_sync_interval(); // ミリ秒単位
M5.Lcd.printf("sync: %d hours ", default_interval / 1000 / 3600);
//同期するまで待つ
while (sntp_get_sync_status() != SNTP_SYNC_STATUS_COMPLETED) {
M5.Lcd.print(".");
delay(500);
}
M5.Lcd.println("\nSNTP sync completed.");
if (getLocalTime(&timeInfo)) {
lastSec = timeInfo.tm_sec;
} else {
M5.Lcd.println("Failed to obtain time.");
return;
}
/* 以降も同期周期にてNTP同期させる場合は、次の2行をコメント化する */
WiFi.disconnect(true);
WiFi.mode(WIFI_OFF);
M5.Lcd.println("Setup completed.");
}
void loop() {
M5.update();
// 現在時刻を取得
getLocalTime(&timeInfo);
// Aボタンが押されたら時計を表示
if (!showClock && M5.BtnA.wasPressed()) {
showClock = true;
M5.Lcd.setRotation(0);
}
// Bボタンが押されたらPower Off
if (M5.BtnB.wasPressed()) {
digitalWrite(GPIO4, LOW); // Power Off
}
// 時計を表示する場合、1秒ごとに更新
if (showClock && (lastSec != timeInfo.tm_sec)) {
lastSec = timeInfo.tm_sec;
displayClock();
}
}
void displayClock() {
M5.Lcd.startWrite();
M5.Lcd.fillScreen(BLACK);
M5.Lcd.setTextColor(DARKGREY);
M5.Lcd.setCursor(0, 0, 4); //x,y,font 4:26ピクセルASCIIフォント
M5.Lcd.printf("%02d:%02d", timeInfo.tm_hour, timeInfo.tm_min); // 時分を表示
M5.Lcd.setTextColor(GREEN);
M5.Lcd.setCursor(0, 42, 7); //x,y,font 7:48ピクセル7セグ風フォント
M5.Lcd.printf("%02d", timeInfo.tm_sec); // 秒を表示
M5.Lcd.setTextColor(DARKGREY);
M5.Lcd.setCursor(0, 152, 1); //x,y,font 1:Adafruit 8ピクセルASCIIフォント
M5.Lcd.printf("%04d", timeInfo.tm_year + 1900);
M5.Lcd.setCursor(55, 140, 2); //x,y,font 2:16ピクセルASCIIフォント
M5.Lcd.printf("%2d/%2d", timeInfo.tm_mon + 1, timeInfo.tm_mday);
double voltage = (double)M5.Power.getBatteryVoltage() / 1000.0;
M5.Lcd.setCursor(0, 206, 1); //x,y,font 1:Adafruit 8ピクセルASCIIフォント
M5.Lcd.printf("Bat: %.1f v", voltage);
M5.Lcd.endWrite();
}
以上