えいあーるれいの技術日記

ROS2やM5 Stack、Ubuntuについて書いています

M5 Core2のRTCからUNIXTIMEを取り出す

 久しぶりに誰得情報を流したいと思います。この記事ではM5 Core2のRTCからUNIXTIMEを取り出すプログラムを解説します。


 M5 Stack Core2にはマイコンボードには珍しくRTC(リアルタイムクロック)が内蔵されています。

 RTCは時間を正確に刻むことができるデバイスで、PCや時間管理が必要な組み込みデバイスによく搭載されます。ソフトウェアタイマと異なり、とても精度がいいのにデバイスの電池切れに関わらず長期間動き続けることができます。

 M5 Core2のRTCを使えば、目覚まし時計や腕時計などの実装を行ってスリープモードを実装したとしても時間を保持することが容易になり、工作の幅が広がるというわけです!

 さて、私はそのRTCを使ってコンピュータに対して時間指定の命令をしたいと思ってしまいました。(誰がなるんかい)

 しかし、RTCのクラスにはxx年xx月xx日xx時xx分xx秒という表記を行うように設計されているため、最初からUNIXTIMEを取り出せない仕様になっています。一応、それを実現させるためのmktimeというTime.hの関数はあるものの、M5 Core2ではクラッシュしてしまいました。そこで、新しく自分用の時間管理プログラムをつかうことにしました。

時間設定

 初回出荷時のM5 Core2のRTCには時間が書き込まれているわけでもないので、設定が必要です。

 3110’s gists · GitHub氏が公開されていたプログラムを使ってRTCの設定を行いました。(後に解説するプログラムのベースにもなっています。ありがとうございます。)

NTPを使ってM5Stack Core2のRTCを設定する · GitHub

実際にRTCの時間からUNIXTIMEに変換

 実際にUNIXTIMEに変更します。

 基本的には、時間変更の式で日本時間のコンピュータ時間にする→3600×9でUNIXTIME(イギリス時間)に直すという順で変更します。

 下記リンクで公開しています。

github.com

 ソースコードを以下に示します。(timetools.cpp)

uint32_t timetools::makeTime(int tm_year, int tm_mon, int tm_mday, int tm_hour, int tm_min, int tm_sec) {
  int i;
  uint32_t seconds;
  static uint8_t monthDays[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

  seconds = tm_year * (SECS_PER_DAY * 365);
  for (i = 0; i < tm_year; i++) {
    if (LEAP_YEAR(i)) {
      seconds += SECS_PER_DAY;
    }
  }

  // add days for this year, months start from 1
  for (i = 1; i < tm_mon; i++) {
    if ( (i == 2) && LEAP_YEAR(tm_year)) {
      seconds += SECS_PER_DAY * 29;
    } else {
      seconds += SECS_PER_DAY * monthDays[i - 1]; //monthDay array starts from 0
    }
  }
  seconds += (tm_mday - 1) * SECS_PER_DAY;
  seconds += tm_hour * SECS_PER_HOUR;
  seconds += tm_min * SECS_PER_MIN;
  seconds += tm_sec;
  
  return seconds;
}

 引数を構造体にしたところM5 Core2がクラッシュしてしまったので、int型の引数を大量に付けてしまいました。まだまだ勉強不足です。C++むずい

 いわゆる典型的なunixtime->一般的な時間表記の逆バージョンになっています。実際に呼び出す際はtimetools *ttools;でクラスを宣言した状態で、

ttools = new timetools();
uint32_t unixtime = ttools->get_unixtime_from_RTC() - (3600*9);

でunixtimeを取得可能です。