M5StickCで時刻と高度を表示する ~ その3
前回は、CPU動作周波数を下げて、かつバックライトを消す対処法を試しましたが、まだまだ駆動時間が足りませんでした。
そこで今回は、見たい時以外はM5StickCを眠らせることにします。
1.DeepSleepを使う
行動中における時間を高度の確認は、数回程度すれば十分です。そのため、電源のオンオフでも差し支えないのですが、もう少しスマートにしたいです。
そこで、DeepSleepという機能を使います。DeepSleepを使うことで、通常は待機状態にしておいて、ボタンが押された時だけ復帰して、時間と高度を確認します。また復帰した時は10秒ほど表示して、その後DeepSleepに戻るようにします。
この方法も問題があって、DeepSleepから復帰する時は、最初から処理が再び行われてしまいます。そのため、時刻と高度が表示されるまでに余計な時間が掛かります。
2.DeepSleepの指定方法
DeepSleepまわりのコードは以下のとおりです。
esp_sleep_enable_ext0_wakeup(GPIO_NUM_37, 0);
M5.Axp.SetSleep();
ESP.deepSleep(24*3600*1000000*30);
前回はバックライトの明るさを低くして消費電力を押さえましたが、今回はSetSleepでバックライトを消しています。
また、DeepSleepのタイムアウトを約一か月後にしていますが、1時間程度で復帰したりします。やはり長時間は無理なようですが、どのくらいの時間が有効なのかはまだ調査中です。復帰してしまった時は、10秒ほど表示して、再びDeepSleepに戻ります。
DeepSleepから強制的に復帰する場合は、ボタン(A)を押します。
※追記:以下コードで、ディープスリープは継続します。コードを置き換えてみてください。
pinMode(GPIO_NUM_37, INPUT_PULLUP);
esp_sleep_enable_ext0_wakeup(GPIO_NUM_37, LOW);
// ディープスリープスタート
M5.Axp.SetSleep();
esp_deep_sleep_start();
3.動作確認
DeepSleepのおかげで、駆動時間が大幅に伸びました。まだバラツキがあってはっきりとは言えませんが、5時間前後は動作します。この5時間も微妙です。同じようなことをしている投稿を検索しましたが、1日以上動作させることは無理みたいです。
やっぱりM5StickCでの長時間駆動には、外部電源が必要だと思います。つい先日にM5StickC Plusが登場しましたが、それでもバッテリー容量は不足しそうです。
4.全ソースコード
#include <M5StickC.h>
#include <WiFi.h>
#include <WiFiUdp.h>
#define BUFSIZE 1024
const char* ssid = "********";
const char* password = "********";
const int port = 60000;
WiFiUDP udp;
void print_wifi_state(){
M5.Lcd.fillScreen(BLACK);
M5.Lcd.setTextColor(YELLOW);
M5.Lcd.setCursor(3, 3);
M5.Lcd.println("WiFi connect");
M5.Lcd.print("IP address: ");
M5.Lcd.println(WiFi.localIP());
M5.Lcd.print("Port: ");
M5.Lcd.println(port);
}
void setup_wifi(){
M5.Lcd.setTextColor(RED);
M5.Lcd.setTextSize(2);
M5.Lcd.setCursor(3, 3);
M5.Lcd.print("Connecting to ");
M5.Lcd.println(ssid);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(100);
M5.Lcd.print(".");
}
print_wifi_state();
udp.begin(port);
}
void setup() {
M5.begin();
// CPU速度を下げる
while(!setCpuFrequencyMhz(80)){
// nop
}
M5.Lcd.setRotation(3);
setup_wifi();
esp_sleep_enable_ext0_wakeup(GPIO_NUM_37, 0);
}
void split(String data, String *lines){
int count = 0;
int datalength = data.length();
for (int i = 0; i < datalength; i++) {
char onec = data.charAt(i);
if ( onec == ',' ) {
count++;
if ( count == 2) {
break ;
}
}
else {
lines[count] += onec;
}
}
}
void loop() {
char packetBuffer[BUFSIZE];
String lines[2] ;
M5.update();
int packetSize = udp.parsePacket();
if (packetSize){
int len = udp.read(packetBuffer, packetSize);
if (len > 0){
packetBuffer[len] = '\0';
}
split(packetBuffer, lines) ;
M5.Lcd.fillScreen(BLACK);
M5.Lcd.setCursor(3, 3);
M5.Lcd.setTextColor(GREEN);
M5.Lcd.println(lines[0]);
M5.Lcd.setCursor(3, 27);
M5.Lcd.println(lines[1]+" m");
delay(10000);
WiFi.disconnect();
M5.Axp.SetSleep();
ESP.deepSleep(1000000*3600*24*30);
}
}
おまけ:時計だけなら
時計だけなら、M5StickCにRTCがあるので長時間駆動する例がありました。
電源を入れた時だけネットから時刻を取得して、あとは内部クロックで時間を管理し、ボタンが押されるまでDeepDleepする仕様です。このやり方であれば、1日は余裕で駆動します。私も少し変更して使っています。