M5StickCのRTCをNTPサーバーからセットする

※現時点の情報ですので、最新情報はM5StickC非公式日本語リファレンスを確認してください。

M5Stick-Cはバッテリーも搭載されているので、RTC(Real Time Clock)で時間が保持できます。しかしながらサンプルスケッチではコードの中に時間を記述していたので、NTPから設定できるようにしてみました。

コード

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

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

const char* ntpServer =  "ntp.jst.mfeed.ad.jp";

RTC_TimeTypeDef RTC_TimeStruct;
RTC_DateTypeDef RTC_DateStruct;

void setup() {
  // put your setup code here, to run once:
  M5.begin();
  M5.Lcd.setRotation(3);
  M5.Lcd.fillScreen(BLACK);

  M5.Lcd.setTextSize(1);
  M5.Lcd.setCursor(40, 0, 2);
  M5.Lcd.println("RTC NTP TEST");

  // 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");

  // Set ntp time to local
  configTime(9 * 3600, 0, ntpServer);

  // Get local time
  struct tm timeInfo;
  if (getLocalTime(&timeInfo)) {
    M5.Lcd.print("NTP : ");
    M5.Lcd.println(ntpServer);

    // Set RTC time
    RTC_TimeTypeDef TimeStruct;
    TimeStruct.Hours   = timeInfo.tm_hour;
    TimeStruct.Minutes = timeInfo.tm_min;
    TimeStruct.Seconds = timeInfo.tm_sec;
    M5.Rtc.SetTime(&TimeStruct);

    RTC_DateTypeDef DateStruct;
    DateStruct.WeekDay = timeInfo.tm_wday;
    DateStruct.Month = timeInfo.tm_mon + 1;
    DateStruct.Date = timeInfo.tm_mday;
    DateStruct.Year = timeInfo.tm_year + 1900;
    M5.Rtc.SetData(&DateStruct);
  }

  //disconnect WiFi
  WiFi.disconnect(true);
  WiFi.mode(WIFI_OFF);
}

void loop() {
  static const char *wd[7] = {"Sun","Mon","Tue","Wed","Thr","Fri","Sat"};
  
  // put your main code here, to run repeatedly:
  M5.Rtc.GetTime(&RTC_TimeStruct);
  M5.Rtc.GetData(&RTC_DateStruct);
  M5.Lcd.setCursor(0, 30);
  M5.Lcd.printf("Data: %04d-%02d-%02d\n", RTC_DateStruct.Year, RTC_DateStruct.Month, RTC_DateStruct.Date);
  M5.Lcd.printf("Week: %s\n", wd[RTC_DateStruct.WeekDay]);
  M5.Lcd.printf("Time: %02d : %02d : %02d\n", RTC_TimeStruct.Hours, RTC_TimeStruct.Minutes, RTC_TimeStruct.Seconds);
  delay(500);
}

概要

RTCのサンプルスケッチをベースに、Wi-Fiで接続してNTPから現在時刻を取得するように変更しただけのコードです。

アクセスポイントの情報を書き換えて転送すれば時刻が設定されるので、複数のM5Stick-Cに時刻設定するのは楽になるかな?

7件のコメント

  1. はじめまして。mkoga184と申します。
    お世話になります。
    上記プログラムですが、当方の開発環境で以下のエラーが出ています。

    Arduino:1.8.9 (Windows 10), ボード:”M5Stick-C, Default, 1500000, None”

    C:\Users\mkoga\Documents\Arduino\wifi_time1\wifi_time1.ino: In function ‘void setup()’:

    wifi_time1:37:21: error: ‘amp’ was not declared in this scope

    if (getLocalTime(&timeInfo)) {

    ^

    wifi_time1:37:24: error: expected ‘)’ before ‘;’ token

    if (getLocalTime(&timeInfo)) {

    ^

    wifi_time1:37:33: error: expected ‘;’ before ‘)’ token

    if (getLocalTime(&timeInfo)) {

    ^

    C:\Users\mkoga\Documents\Arduino\wifi_time1\wifi_time1.ino: In function ‘void loop()’:

    wifi_time1:65:19: error: ‘amp’ was not declared in this scope

    M5.Rtc.GetTime(&RTC_TimeStruct);

    ^

    wifi_time1:65:37: error: expected ‘;’ before ‘)’ token

    M5.Rtc.GetTime(&RTC_TimeStruct);

    ^

    wifi_time1:66:37: error: expected ‘;’ before ‘)’ token

    M5.Rtc.GetData(&RTC_DateStruct);

    ^

    「WiFi.h」に対して複数のライブラリが見つかりました
    使用済:C:\Users\m-koga\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.2\libraries\WiFi
    未使用:C:\Program Files (x86)\Arduino\libraries\WiFi
    exit status 1
    ‘amp’ was not declared in this scope

    対処法等ございましたら、ご教授いただけないでしょうか。
    よろしくお願いいたします。

  2. すみません、ブログで使っているWordpressの問題で&の文字が&amp;として表示されてしまうようです。

    amp;を消して&だけにすればコンパイルできると思います。
    もしくは、ちょっと違うコードですが

    https://lang-ship.com/reference/unofficial/M5StickC/UseCase/RTCSetNTP/

    上記を試してもらえればと思います。こっちはWi-Fiのパスワードを別プログラムで本体に保存しておき、そのパスワードで接続しますので、プログラムの中にパスワードを書かなくてもインタネット接続ができます。

    1. ご丁寧な返信ありがとうございました。
      amp;の削除のみで無事動きました。
      こちらは先日、Maker Faire 2019で何とかM5Stick-Cを購入して頑張っています。
      今後は赤外線学習リモコンの作成まで頑張ります。
      でも、屋外からのエアコン制御となると他のESP32の方が良いですかねぇ。
      固定で使うことを考えますと…。

      1. M5StickCだと赤外線LEDがちょっと奥まったところにあるので、あまり飛びが良くないみたいです(外付けで赤外線LED追加してもいいと思います)

        個人的にはESP32はたくさん持っているので、試作は使いやすいもので作ってから、実際に固定するときには、ほとんど同じコードが動くESP32の安いボードを使います

        ただ、まずは手持ちの材料で作ってみてから考えればいいかなーっては思います

  3. 初めまして。M5Stick-Cを使って自転車に取り付ける加速度ロガーを作っています。
    ログにマイクロ秒まで記録したいのですが、秒がカウントアップしたタイミングからカウントするようなプログラムを組むしかないのでしょうか? それとも、RTCの何らかの関数でマイクロ秒(あるいは、1秒以下の単位の時間)を取得することができるのでしょうか?
    知恵を借りさせていただきたいです。

    1. M5StickCに搭載しているRTCは秒未満は取得できないと思います。
      個人的には、起動時のRTCの秒+経過時間をmillis()で管理するぐらいの精度でも、実用的には問題ないのかなと思います。

      厳密に管理するのであれば、別タスクとかで毎秒カウントアップしたタイミングのmillis()を保存しておき、秒未満はそこからの差分を保存する形になると思います。

      millis()はESP32内蔵の時計で、精度はそれほど高くありません。長時間動かすとRTCのそれなりにちゃんとした時間精度より時間がずれてしまいます。精度の差は個体差があると思い、実測値ではないですがmillis()で1000秒カウントしたところ、RTCだと998秒しか経過していないみたいなことが起こりえます。

      ただ実際RTCから時刻取得するだけでミリ秒単位で時間がずれる可能性があります。
      とはいえ、加速度センサーとの通信もRTCも、同じ内蔵I2Cを利用するのであまり高頻度にRTCを取得するのはおすすめしません。

      あとは外部にGPSとかを追加すれば、座標とミリ秒単位の正確な時刻も取得可能ですが、GPSの信号を受信してから取得するまでにちょっと時間かかって遅延します。

      どこまでの精度が必要かによりますが、大抵は起動日時分秒+millis()での経過時間で管理するので問題がないことが多いと思います。

コメントする

メールアドレスが公開されることはありません。

管理者承認後にページに追加されます。公開されたくない相談はその旨本文に記載するかTwitterなどでDM投げてください。またスパム対策として、日本語が含まれない投稿は無視されますのでご注意ください。