M5StickCで時刻と高度を表示する ~ その2

2020年7月28日

前回、M5StickCに時刻と高度を表示させてみましたが、 1時間ちょっとの駆動時間が問題として残りました。そこで今回は、2つの改良を加えました。

1.CPUの動作周波数を下げる

M5StickCのCPUにおける最大周波数は240MHzですが、可能な限り下げます。設定では10MHzまで下げられるのですが、80MHz以下ではWi-Fiが不安定になりました。

そこで、以下のロジックを用いてCPU動作周波数を80MHzにしました。

  // CPU速度を最低にする
  while(!setCpuFrequencyMhz(80)){
    // nop
  }

2.見る時だけバックライトをONにする

時間と高度を確認する時間は、ほんのわずかです。そのため、バックライトを点けたままにする必要がありません。そこで、ボタン(A)を押した時にバックライトを点けて、確認が終わったら再度ボタンを押してバックライトを消すことにします。

バックライトの明るさは0~12まで設定できますが、7からパネルの内容が確認できます。パネルを完全に消すとバッテリーが切れたタイミングが分からないので、7を消灯時の値とします。

  // LCDのON/OFF設定
  if ( M5.BtnA.wasReleased() ) {
    if (lcdValue == 7) {
      lcdValue = 12 ;
    } else { 
      lcdValue = 7;
    }
  }

  M5.Axp.ScreenBreath(lcdValue);

「wasReleased」関数は、ボタンを押して離したらフラグが立ちます。よって、 wasReleased関数が呼ばれた時にボタンが押されていなくても、過去に押したフラグが立っているのでtrueが返ります。

3.動かしてみる

動かしてみると、2時間30分ほど駆動しました。前回よりも倍の時間駆動したことになります。

今回行った改良の効果が大きいですが、2時間30分ではまだまだ足りません。他の方法を考えることにします。

4.すべてのソースコード

#include <M5StickC.h>
#include <WiFi.h>
#include <WiFiUdp.h>
 
#define BUFSIZE 1024
 
const char* ssid     = "**********"; // 各自設定してください
const char* password = "**********";
const int port = 60000;

int lcdValue = 12 ;
 
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
  }

  // 最初はLCDの明るさを最低にする
  M5.Axp.ScreenBreath(lcdValue);
  
  M5.Lcd.setRotation(3);
 
  setup_wifi();

}

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();
  
  // LCDのON/OFF設定
  if ( M5.BtnA.wasReleased() ) {
    if (lcdValue == 7) {
      lcdValue = 12 ;
    } else { 
      lcdValue = 7;
    }
  }    
  
  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.Axp.ScreenBreath(lcdValue);
    
    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");

  }
}

バックライトの明るさが切り替わるタイミングは、UDPソケット通信でデータを受信した時であることに注意してください。