03.M5Unifiedで時計表示


03.M5Unifiedで時計表示

4機種同一スケッチで時計表示します。ただし、電源offでも動作している内蔵時計RTCが無い機種があるため、電源起動時に毎回wifiで時刻合わせをし、RTCは使用しません。

説明

各機種の画面サイズに合わせました。

1行目 バッテリー残量 "BT???%"
y=2, x=右端に置くように調整
文字はlgfxJapanGothic_28でサイズ=1。しかしATOMS3はサイズを小さくしました
文字色は、CoreInk以外は緑色

2行目 "年/月/日(曜日)"
x=2, y=上から20%
文字は、lgfxJapanGothic_28。サイズは横幅と行間に合うように拡大縮小

3行目 "時:分"
x=2, y=上から50%
文字は、時計風文字のFont7。サイズは横幅と行間に合うように拡大縮小
時刻の更新はCoreInkがあるため15秒間隔とします

・M5Stack Basic
・CoreInk
・M5StickCPlus
・ATOMS3

4機種のRTC

・M5Stack Basic
 RTC:無し
https://www.switch-science.com/products/3647?_pos=2&_sid=abb768d3b&_ss=r

・ATOMS3
 RTC:無し
https://www.switch-science.com/products/8670?_pos=1&_sid=7b9b885e9&_ss=r

・CoreInk
 RTC:BM8563
https://www.switch-science.com/products/6735?_pos=5&_sid=d6ccee9d0&_ss=r

・M5StickCPlus
 RTC:BM8563
https://www.switch-science.com/products/6470?_pos=16&_sid=c41c47531&_ss=r

BM8563の安定度

上海贝岭股份有限公司
https://www.belling.com.cn
のBM8563のデータシートp4
https://www.alldatasheet.com/datasheet-pdf/view/1768247/BELLING/BM8563.html
より
発振安定度は、ΔfOSC/fOSC = 2x10^-7 = 0.2ppmTyp
これは、30x24x60x60秒x0.2ppm = 0.5秒 (1ケ月に0.5秒)
の安定度です。ただし、
動作温度: Ta = -40~85℃の内、25℃一定
電源電圧: VDD = 1.8~5.5Vの中で、ΔVDD=0.2Vのみ
GND側電圧: VSS = 0V
発振周波数: fosc = 32.768kHz固定 (発振器外付)
の時の平均値です。

スケッチ

"*****"の6ケ所は自分のssidとそのPWに入れ替えてください。

// clockM5Unified.ino
// 時計表示 wifiで時刻合わせ RTCは使用せず
// APPサイズを拡大する M5Stack Basic,CoreInk,AtomS3
#include <M5Unified.h>  // M5Unifiedライブラリを使用
#include <WiFi.h>       // wifiを使用
#include <WiFiMulti.h>  // 複数のssid使用
WiFiMulti wifiMulti;                              // WiFiMultiのインスタンスを準備
const char* ntpServer1 = "ntp.nict.jp";           // NICT(独立行政法人情報通信研究機構)
const char* ntpServer2 = "ntp.nc.u-tokyo.ac.jp";  // 東京大学
const char* ntpServer3 = "1.jp.pool.ntp.org";     // NTP POOL PROJECT
int32_t ntpTimeZone = 9 * 60 * 60;                // 日本時間 9H
const char* ssid1 = "*****";                      // 自分のwifiのssid1
const char* pass1 = "*****";                      // そのPW
const char* ssid2 = "*****";                      // 自分のwifiのssid2
const char* pass2 = "*****";                      // そのPW
const char* ssid3 = "*****";                      // 自分のwifiのssid2
const char* pass3 = "*****";                      // そのPW
int32_t WW, HH, batP;                             // 画面幅,高さ,バッテリー残量(0-100)
struct tm timeInfo;                               // tm構造体 time.hで宣言
static constexpr const char* const wd[7] = { "日", "月", "火", "水", "木", "金", "土" };

void SetDisplay() {             // 初期画面設定関数
  WW = M5.Display.width();      // 画面幅を取得
  HH = M5.Display.height();     // 画面高さを取得
  if (WW == HH) {               // 画面を横長にする
    M5.Display.setRotation(0);  // 0度回転
  } else {
    M5.Display.setRotation(1);  // 90度回転
  }
  if (HH > WW) {  // 横長なので交換 横:WW,縦:HHにする
    int32_t HHWW = HH;
    HH = WW;
    WW = HHWW;
  }
  // M5.Display.fillScreen(TFT_BLACK);             // 全画面黒
  M5.Display.setFont(&fonts::lgfxJapanGothic_28);  // ゴシック(8,12,16,20,24,28,32,36,40)
  M5.Display.setTextSize(1);                       // テキストサイズ(倍)
  M5.Display.setBrightness(100);                   // バックライト輝度(0-255)実際は数段階
  // M5.Display.setTextColor(TFT_GREEN, TFT_BLACK);// 色設定(文字色[,背景色])
}

void printLocalTime() {                   // 表示関数
  if (!getLocalTime(&timeInfo)) {         // 現在時刻を取得できないなら
    M5.Display.println("失敗 時間取得");  // 表示
    return;                               // 戻る
  }

  // バッテリー残量 1行目
  M5.Display.setFont(&fonts::lgfxJapanGothic_28);     // ゴシック(8,12,16,20,24,28,32,36,40)
  M5.Display.setTextSize(1);                          // テキストサイズ(倍)
  switch (WW) {                                       // 機種ごとの画面設定
    case 128:                                         // ATOMS3
      M5.Display.setTextColor(TFT_GREEN, TFT_BLACK);  // 色設定(文字色[,背景色])
      M5.Display.setTextSize(0.6);                    // テキストサイズ(倍)
      M5.Display.setCursor(70, 2);                    // 表示位置(x,y)
      break;
    case 200:                        // CoreInk
      M5.Display.setCursor(110, 2);  // 表示位置(x,y)
      break;
    case 240:                                         // M5StickCPlus
      M5.Display.setTextColor(TFT_GREEN, TFT_BLACK);  // 色設定(文字色[,背景色])
      M5.Display.setCursor(150, 2);                   // 表示位置(x,y)
      break;
    case 320:                                         // M5Stack Basic
      M5.Display.setTextColor(TFT_GREEN, TFT_BLACK);  // 色設定(文字色[,背景色])
      M5.Display.setCursor(235, 2);                   // 表示位置(x,y)
      break;
    default:  // それ以外
      break;
  }
  if (WW == 128) {               // ATOMS3はバッテリーが無いので
    M5.Display.print("BT---%");  // 表示 バッテリ残量
  } else {
    batP = M5.Power.getBatteryLevel();   // バッテリー残量値を取得(0-100)
    M5.Display.printf("BT%3d%%", batP);  // 表示 バッテリ残量
  }

  // 年月日 2行目
  M5.Display.setCursor(2, (int16_t)(HH * 0.2));  // カーソル位置
  switch (WW) {                                  // 機種ごとの画面設定
    case 128:                                    // ATOMS3
      M5.Display.setTextSize(0.67);              // テキストサイズ(倍)
      break;
    case 200:  // CoreInk
      break;
    case 240:                            // M5StickCPlus
      M5.Display.setTextSize(1.2, 1.3);  // テキストサイズ(倍)
      break;
    case 320:                       // M5Stack Basic
      M5.Display.setTextSize(1.6);  // テキストサイズ(倍)
      break;
    default:  // それ以外
      break;
  }
  M5.Display.printf("%04d/%02d/%02d(%s)\n", timeInfo.tm_year + 1900,
                    timeInfo.tm_mon + 1, timeInfo.tm_mday, wd[timeInfo.tm_wday]);  // 表示 年/月/日(曜日)

  // 時分 3行目
  M5.Display.setCursor(2, (int16_t)(HH * 0.5));  // カーソル位置
  M5.Display.setFont(&fonts::Font7);             // 時計風文字
  switch (WW) {                                  // 機種ごとの画面設定
    case 128:                                    // ATOMS3
      M5.Display.setTextSize(0.9);               // テキストサイズ(倍)
      break;
    case 200:                       // CoreInk
      M5.Display.setTextSize(1.4);  // テキストサイズ(倍)
      break;
    case 240:  // M5StickCPlus
      break;
    case 320:                       // M5Stack Basic
      M5.Display.setTextSize(2.2);  // テキストサイズ(倍)
      break;
    default:  // それ以外
      break;
  }
  M5.Display.printf("%02d:%02d\n", timeInfo.tm_hour, timeInfo.tm_min);  // 表示 時:分
}

void setup() {
  auto cfg = M5.config();                                      // M5設定用の構造体を代入
  M5.begin(cfg);                                               // M5本体の初期化
  SetDisplay();                                                // 初期画面設定関数へ
  M5.Display.println("wifi接続開始");                          // 表示
  wifiMulti.addAP(ssid1, pass1);                               // ssid1を登録
  wifiMulti.addAP(ssid2, pass2);                               // ssid2を登録
  wifiMulti.addAP(ssid3, pass3);                               // ssid3を登録
  M5.Display.println("wifi接続中");                            // 表示
  for (int i = 20; i && WiFi.status() != WL_CONNECTED; --i) {  // 20回以内にwifi接続されなかったら
    wifiMulti.run();                                           // 一番強いアクセスポイントに接続
    M5.Display.print(".");                                     // 表示
    delay(1000);                                               // 1秒待つ
  }
  if (wifiMulti.run() == WL_CONNECTED) {                             // wifiが接続されたら
    M5.Display.print("\nwifi接続済\nssid:");                         // 表示
    M5.Display.println(WiFi.SSID());                                 // 接続したssidを表示
    configTime(ntpTimeZone, 0, ntpServer1, ntpServer2, ntpServer3);  // ntpサーバへ接続
    M5.Display.println("ntp取得済");                                 // 表示
  } else {
    M5.Display.println("\nwifi未接続");  // 表示
  }
  delay(2000);            // 2秒待つ
  printLocalTime();       // 表示関数へ
  WiFi.disconnect(true);  // wifi切断
  WiFi.mode(WIFI_OFF);    // wifi off
  M5.Display.clear();     // 画面クリア
}
void loop() {
  printLocalTime();  // 表示関数へ
  delay(15000);      // 15秒待つ
}
* ATOMS3の場合、flash memory(3.3Mbyte)のうち、スケッチが34%使用。RAM(328kbyte)のうち、global変数が14%使用、local変数で281kbyte使用可能。(1000byte=1kbyteで計算)