NTPサーバから時刻を取得してM5Stackに表示する

はじめに

M5Stackのスケッチ例に「TFT_Clock_Digital」というものがあります。

デジタル時計のように時刻が画面上に表示され1秒ごとに変化しますが、表示される時刻はコンパイルした時刻が基準となります。
(厳密には違うと思いますが大雑把な認識としてだとお思いください。)

そのため、例えば15:47:00にコンパイルした場合、電源を入れる度に15:47:00がまず表示され、そこから1秒ごとに表示される時刻が変化します。

しかしながら、そのままでは時計としての役割を果たせないため、NTPサーバから時刻を取得して現在の時刻を表示できるものを作成しましたのでご紹介します。

完成品

画面に表示されている文字列の見た目はTFT_Clock_Digitalと同様ですが、こちらは電源ボタンを押して再度起動しても隣の時計とほぼ同じ時刻を表示してくれます。

開発環境

準備物

  • M5Stack Gray

M5Stack Gray(9軸IMU搭載)

M5Stack Gray(9軸IMU搭載)

※M5Stackであればどのシリーズ(Basic,FIRE等)でも問題ないと思います。

前提

Arduino IDEによるM5Stackの開発環境の構築が出来ている方を対象としています。

1.下記のスケッチを書き込む

スケッチ例にある「TFT_Clock_Digital」と「SimpleTime」の合わせ技となっております。
以下にそれぞれのスケッチ例がありますので、参考になるかと思います。

  • TFT_Clock_Digital

ファイル→スケッチ例→M5Stack→Advanced→Display→TFT_Clock_Digital

  • SimpleTime

ファイル→スケッチ例→ ESP32→Time→SimpleTime

#include <M5Stack.h>
#include <WiFi.h>
#include "time.h"

const char* ssid       = "";  
const char* password   = "";

const char* ntpServer =  "ntp.jst.mfeed.ad.jp";
const long  gmtOffset_sec = 9 * 3600;
const int   daylightOffset_sec = 0;


static uint8_t conv2d(const char* p); // Forward declaration needed for IDE 1.6.x

uint8_t hh = conv2d(__TIME__), mm = conv2d(__TIME__ + 3), ss = conv2d(__TIME__ + 6); // Get H, M, S from compile time

byte xcolon = 0, xsecs = 0;

void setup(void) {
  
  Serial.begin(115200);
  M5.begin();
  M5.Lcd.fillScreen(TFT_BLACK);
  M5.Lcd.setTextSize(1);
  M5.Lcd.setTextColor(TFT_YELLOW, TFT_BLACK);

  //connect to WiFi
  Serial.printf("Connecting to %s ", ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("CONNECTED");

  //init and get the time
  configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
      struct tm timeinfo;
  if (!getLocalTime(&timeinfo)) {
    Serial.println("Failed to obtain time");
    return;
  }
  //disconnect WiFi as it's no longer needed
  WiFi.disconnect(true);
  WiFi.mode(WIFI_OFF);

}

void loop() {
  
  struct tm timeinfo;
  if (!getLocalTime(&timeinfo)) {
    Serial.println("Failed to obtain time");
    return;
  }
  hh = timeinfo.tm_hour;
  mm = timeinfo.tm_min;
  ss = timeinfo.tm_sec;
  
  // Update digital time
  int xpos = 0;
  int ypos = 85; // Top left corner ot clock text, about half way down
  int ysecs = ypos + 24;

  // Draw hours and minutes
  if (hh < 10) xpos += M5.Lcd.drawChar('0', xpos, ypos, 8); // Add hours leading zero for 24 hr clock
  xpos += M5.Lcd.drawNumber(hh, xpos, ypos, 8);             // Draw hours
  xcolon = xpos; // Save colon coord for later to flash on/off later
  xpos += 29;
  if (mm < 10) xpos += M5.Lcd.drawChar('0', xpos, ypos, 8); // Add minutes leading zero
  xpos += M5.Lcd.drawNumber(mm, xpos, ypos, 8);             // Draw minutes
  xsecs = xpos; // Sae seconds 'x' position for later display updates
    
  if (ss % 2) { // Flash the colons on/off
    M5.Lcd.setTextColor(0x39C4, TFT_BLACK);        // Set colour to grey to dim colon
    M5.Lcd.drawChar(':', xcolon, ypos - 8, 8);     // Hour:minute colon
    xpos += M5.Lcd.drawChar(':', xsecs, ysecs, 6); // Seconds colon
    M5.Lcd.setTextColor(TFT_YELLOW, TFT_BLACK);    // Set colour back to yellow
  }else{
    M5.Lcd.drawChar(':', xcolon, ypos - 8, 8);     // Hour:minute colon
    xpos += M5.Lcd.drawChar(':', xsecs, ysecs, 6); // Seconds colon
  }
  
  //Draw seconds
  if (ss < 10) xpos += M5.Lcd.drawChar('0', xpos, ysecs, 6); // Add leading zero
  M5.Lcd.drawNumber(ss, xpos, ysecs, 6);                     // Draw seconds
}


// Function to extract numbers from compile time string
static uint8_t conv2d(const char* p) {
  uint8_t v = 0;
  if ('0' <= *p && *p <= '9')
    v = *p - '0';
  return 10 * v + *++p - '0';
}

参考

qiita.com

おわりに

NTPサーバから時刻を取得してM5Stackに表示する方法をご紹介しました。

Wi-Fiに繋がる環境下であればこちらの方が良いと思いますので、ぜひお試しください。