M5Stack CORE2でネットから現在時刻を取得

M5Stack NTPサーバー

M5Stack CORE2でWiFi接続によりインターネットでNTPサーバーから現在時刻を取得してLCD画面に年月日時刻を表示します。

目次

NTPサーバーからの時刻取得

ネットに接続された機器の時刻を合わせるためにNTPサーバーというものがあります。NTP(Network Time Protocol)サーバーは国内にもいくつかあるようですが代表的なものとして情報通信研究機構(NICT)の公開NTPサーバー「ntp.nict.jp」があります。

NTPサーバーから受信したデータはUNIX時間といって、1900年1月1日0時0分0秒(UTC)からの経過秒数を表しています。よって現在時刻の「年」を表示するときには受信したデータに1900を足す必要があります。また、UTCとは協定世界時のことであり、日本標準時(JST)を表示するにはUTCから9時間進めた時間(UTC+9)にします。

WiFiによるインターネット接続

インターネットに接続されているWiFiに接続します。WiFi設定は、WiFi.mode()にて子機(WIFI_STA)設定、WiFi.begin()でSSIDとパスワードを設定します。WiFi接続は、WiFi.status()を実行します。今回作成したプログラムは500ms毎に接続を試みて接続成功が返ってきたらループを抜けるようにしています。

NTPサーバーから時刻取得するプログラム

ArduinoIDEのサンプルスケッチTime.inoを参考に作成しました。NTPサーバーからの時刻取得はsetup()の中で起動時にWiFi接続して1回だけ実施しています。configTime()により時刻を取得するとESP32のシステム時間に反映されます。その後はloop()内で毎秒ESP32からgetLocalTime()でESP32のシステム時間を取得し、LCDに表示します。

configTime()の各引数ですが、「gmtOffset_sec」はタイムゾーンによる時差設定で、UTCからJSTの時差は9時間であり、9行目の変数設定で3600*9秒となります。 「daylightOffset_sec」はサマータイムの時差設定ですが日本はサマータイムが無いため0秒を設定しています。 「ntpServer」はNTPサーバーのアドレスでNICTのNTP公開サーバーである”ntp.nict.jp”を設定しました。

時刻の取得とLCD表示はサブルーチンprintLocalTime()にしており、loop()から1秒毎に呼び出しています。getLocalTime(&timeinfo)で時間取得すると構造体tmのtimeinfoに値が入ります。timeinfo.tm_yearは1900年が起点の値なので1900を加算します。timeinfo.tm_monは1月は0なので1を加算します。

#include <M5Unified.h>
#include <WiFi.h>

const char* ssid = "**************";    //WiFi SSID
const char* password = "*************"; //WiFi password

const char* ntpServer = "ntp.nict.jp";  //NTPサーバーNICT
const long gmtOffset_sec = 3600 * 9;    //日本のタイムゾーンはGMT+9:00
const int daylightOffset_sec = 0;       //日本はサマータイムなし

void printLocalTime() {
    struct tm timeinfo; //NTPサーバーからの時間情報の構造体

    if (!getLocalTime(&timeinfo)) { //NTPサーバーから時間取得
        M5.Display.println("Failed to obtain time");
        return;
    }
    
    M5.Display.printf("DATE: %04d/%02d/%02d\n", 
        timeinfo.tm_year +1900, //1900年が起点の値 
        timeinfo.tm_mon + 1, //0が1月
        timeinfo.tm_mday);
    
    M5.Display.printf("TIME: %02d:%02d:%02d\n", 
        timeinfo.tm_hour, 
        timeinfo.tm_min, 
        timeinfo.tm_sec);
}

void setup() {   
    auto cfg = M5.config();
    M5.begin(cfg);
    
    M5.Display.setTextSize(2);
    M5.Display.print("--- WiFi NTP server---\n\n");
    M5.Display.print("Connecting");

    WiFi.mode(WIFI_STA);    //子機接続設定
    WiFi.begin(ssid, password);

    while (WiFi.status() != WL_CONNECTED) { //WiFi接続
        delay(500);
        M5.Display.print(".");
    }

    M5.Display.println("\n\nWiFi connected!");
    configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);//NTPサーバー設定
}

void loop() {
    M5.Display.setCursor(0, 120);
    M5.Display.setTextSize(3);

    printLocalTime();
    delay(1000);
}

時刻取得の実行結果

WiFi接続されるとNTPサーバーから現在時刻を取得しLCD表示します。1秒毎に時刻が更新されます。このプログラムだと起動時に数秒だけ2022年2月19日13:06:03などと表示されました。ESP32のシステム時間がNTPサーバーの値に更新されるのに少し時間がかかり、最初のgetLocalTime()でESP32の時刻を読みに行ったタイミングではまだ更新されていなかったのだと思われます。configTime()の直後に3秒のディレイを入れたら更新された値が表示されました。

まとめ

ライブラリでNTPサーバーから時刻を取得する関数configTime()とカレンダー時刻の構造体tmが準備されており、これらを使うだけで簡単に時刻を取得することができます。

WiFi接続はSSIDとパスワード、NTPサーバーのアドレスを設定します。取得データはUNIX時間なのでカレンダー時刻に変換します。時刻取得値は年は1900年起点であること、月は1月は0であること、今回は曜日表示しませんでしたが0が日曜日です。

目次