Arduino-ESP32のNTP接続で時刻設定

Arduino環境でESP32を使いntp接続した時にちょっとはまった部分について。

ESP32の初期時刻の設定をWiFi経由のntpで行うことにした。
ググったところ、いろいろなサイトでその実装例が出されていたので、それらを参考にして見た。

また、時刻の設定は起動時のみでよかったので、時刻を取得(すると思うコード)を呼び出したのち、WiFiの接続を解除するようにしてみた。

void setup()
{
    // Wifiの設定と時刻の取得
    WiFi.mode(WIFI_STA);
    WiFi.disconnect();

    if (WiFi.begin(ssid, password) != WL_DISCONNECTED) {
        ESP.restart();
    }
    while (WiFi.status() != WL_CONNECTED) {
        delay(1000);
    }
    configTime(9 * 3600L, 0, "ntp.nict.jp", "time.google.com", "ntp.jst.mfeed.ad.jp");
    WiFi.disconnect(true);
    WiFi.mode(WIFI_OFF);
}

void loop()
{
    char buffer[256];
    struct tm timeInfo;
    getLocalTime(&timeInfo);
}

configTimeまでの実装はどこにでもあるようなものだが、その後にWiFiの接続を解除しているような実装はなかった。

上のコードを実行すると、loop内で得られる時刻は1970年のまま、つまり0クリアされたものだった。電源投入直後なので0クリアはわかるのだがconfigTime内でntpに接続し、時刻更新をしていると思ったのだが、どうやらそうではないらしい。

当初原因はわからなかったが、getLocalTimeの実装を見たところwhile文で時刻を取得するようなものになっていた。

もしやと思い、以下の様にconfigTimeの後に時刻を取得するコードを入れてみたところWiFiの接続を解除したのちもgetLocalTimeで正しい時刻が取得できるようになった。

    configTime(9 * 3600L, 0, "ntp.nict.jp", "time.google.com", "ntp.jst.mfeed.ad.jp");
    struct tm timeInfo;
    getLocalTime(&timeInfo);
    WiFi.disconnect(true);
    WiFi.mode(WIFI_OFF);

詳細は追えていないのだが、たぶんtime関数の中でntpを使った時刻同期を行うんだろうなとは思ってる。

esp-idf側のAPIとそのサンプルを見るとsntp_get_sync_statusで更新されているかを判断しているようだけど、Arduinoベースだとsntp_get_sync_statusをうまく呼び出すことができず(たぶんarduino-esp32がesp-idfのv4.0.xベースだからコンパイルエラーになる?)、上のような実装が一番簡単だった。

ntpでの時刻調整はデフォルト1時間間隔でntpサーバーに接続するようなのだが、WiFiを切ってしまった後はもちろんntpを使った時刻調整はできない。
WiFi再接続後もArduinoベースでは強制更新のAPIがないので、adjtimeで0クリアした後、getLocalTimeで時刻更新といった方法しかないかもしれない。

コメント

タイトルとURLをコピーしました