ArduinoとRTCモジュールRX8900を使ったLCD時計の製作(2):電波時計モジュールで時刻合わせ

電波時計モジュールで受信したJJYタイムコードを復号した日時データとRTCモジュールRX8900を同期させて時刻合わせを行うLCD時計を作りました。
ビル内など電波を良好に受信できない環境では、疑似JJY電波を発生させるスマートフォンアプリを使っていつでも時刻合わせができます。

受信して復号した日時情報でRTCを更新してLCD表示
目次

電波時計モジュールでJJY電波(タイムコード)から日時情報の取得

長波標準電波の伝搬については、NICT-情報通信研究機構サイト「標準電波の伝播(電波の飛び方)、都道府県別の電界強度の予測値」で詳しい説明があります。

JJY電波(タイムコード)

公開されている「JJY – 標準電波で送信する時刻符号 」「JJY標準電波の出し方について」を参考に受信した信号(疑似JJY信号)をデコードします。

  • 1周期60秒(60ビット)の組み合わせ。受信完了時には1分前の時刻となる。
    • 1分加算と桁上がり(分、時、日、年、うるう年、曜日)を計算。
  • 6つのゾーン(分、時、通算日、西暦(下2桁)、曜日など)に分かれている。
    • 1月から順に月の日数を引いて月、日を計算。月の日数はうるう年を考慮。
  • 秒の信号は、パルス信号の立ち上がり。パルス幅の長さによって、その秒での情報を符号化。
  • ゾーン毎に0.2秒のマーカーパルス( M(0秒)、P1(9秒)、P2(19秒)、P3(29秒)、P4(39秒)、P5(49秒)、P0(59秒) )が出る。その後に続くパルス幅 0.5秒が「1」、0.8秒が「0」。
    • 59秒と0秒でマーカーが2つ重なることで先頭のM(0秒)を判定。
    • 今回のスケッチではP0~P5も表記はMで処理。
  • 毎時15分、45分の40秒からは呼出符号 JJY(モールス符号)列が送出されるため、この間は秒信号、年のデータが取得できない。
    • 今回のスケッチでは60秒間の全データが取得できない時はスキップ処理。
コード
「1」の重み
0M
140(分)
220(分)
310(分)
40
58(分)
64(分)
72(分)
81(分)
9P1(M)
100
110
1220(時)
1310(時)
140
158(時)
164(時)
172(時)
181(時)
19P2(M)
コード
「1」の重み
200
210
22200(日)
23100(日)
240
2580(日)
2640(日)
2720(日)
2810(日)
29P3(M)
308日
314日
322日
331日
340
350
36パリティ(時)
37パリティ(分)
38予備
39P4(M)
コード
「1」の重み
40予備
4180(年)
4240(年)
4320(年)
4410(年)
458(年)
464(年)
472(年)
481(年)
49P5(M)
504(曜日)
512(曜日)
521(曜日)
53うるう秒
54うるう秒
550
560
570
580
59P0(M)

参考:
JJY – 標準電波で送信する時刻符号 | NICT-情報通信研究機構
 標準電波のタイムコード、標準電波の伝播(電波の飛び方)、都道府県別の電界強度の予測値
JJY標準電波の出し方について
・標準電波送信所
 おおたかどや山標準電波送信所(40 kHz)
 はがね山標準電波送信所(60 kHz)

スマホアプリの疑似JJY信号を使って時刻合わせ

ビル内では電波の受信環境が良くなかったのでスマホアプリの疑似JJY信号を使って時刻合わせしています。iPhone12(iOS16) と Pixel7 (Anroid13) で動作確認できました。

  iPhoneアプリ:JJY Simulatorなど
 Androidアプリ: JJYEmulatorなど

JJY Simulatorの使い方(iPhone画面右下の青いアイコン)には「日本の電波時計の基準局(JJY)で使用される標準電波を模擬した信号を、13.3kHzの音声として出力し、3倍高調波(40kHz)を利用して時刻を合わせます」との記載があります。

・最近のスマホにはイヤホンジャックがないのでスピーカで再生しています。スマホのスピーカからは確認用の「プツプツ」低めの音と「チー」という高い周波数(13.3kHz)のモスキート音が聞こえます。
・人間が聞き取れる周波数(音の高さ)は20Hzから20,000(20k)Hzといわれています。13.3kHzの音声の聞こえ方は、年代やスマホのスピーカ性能にもよりますので音量に注意ください。下記サイトなどに年代別の可聴周波数域の記載がありました。
モスキート音 測定 | sainokuni-rionet.jp
・時刻合わせしたい時に、疑似JJY信号を発生するアプリを起動して最大ボリュームで再生、(高調波成分は弱い信号なので)スマホのスピーカ付近を電波時計モジュールのバーアンテナに密着します。

あわせて読みたい
iPhoneの時刻合わせアプリで電波時計(CASIO PROTREK)が現役復帰 自宅マンションでは電波の入りが悪く使わなくなっていた2009年7月発売のCASIO PROTREK(PRW-1500CAJ)。最近になってiPhoneアプリで電波時計の時刻合わせができることを...

準備したパーツ

ネット通販(aitendo秋月電子通商など)でパーツを集めてブレッドボードで組み立てました。
今回、電波時計モジュールにはC-MAX社AMレシーバーチップCME6005を使ったD606Cを使いました。
D606Cの動作電源は1.5〜3.5VなのでArduino利用時は注意。動作電圧が1.5〜5VのMJU823RCCもあるようです。

# パーツ 個数 備考
1電波時計モジュール
[D606C]
40/60KHz  6P仕様
バーアンテナ付属
出力信号:負論理
1aitendo
2プルダウン抵抗
3.3kΩ
3手持ち
3トランジスタ
2SC1815
1手持ち
4LED(赤色)1手持ち
5電流制限抵抗
3.3kΩ
1手持ち
6Arduino Uno Rev31【M-07385】
7ブレッドボード
EIC-801
1【P-00315】
8ジャンパーワイヤ
オス-オス 10cm
適量手持ち

RTCジュールRX8900を使ったLCD時計のパーツです。温度補償発振器(DTCXO)を内蔵しており高精度で時刻を管理できます。

# パーツ 個数 備考
1RX8900CE UA
DIP化モジュール
1【K-13009】
2I2C接続 16×2行
白色バックライト
[ACM1602NI-FLW-FBW-M01]
1【P-05693】
3I2Cプルアップ抵抗
10kΩ
※モジュール内の抵抗を有効化しない場合
2手持ち
4半固定ボリューム
3362P 10KΩ
1【P-03277】
5電気二重層コンデンサ
1.5F 耐電圧 5.5V(タテ型)
1【P-04300】
6保護抵抗
200Ω
1 手持ち

結線図

電波時計モジュール D606C のピンアサインのメモです。

ピン実装D606Cの仕様
V3.3V動作電源 1.5〜3.5V
GGNDGND
Fプルダウン
lowレベル
動作モード設定:
・lowレベル  → 40KHzモード
 おおたかどや山標準電波送信所(40 kHz、大鷹鳥谷山)
 https://jjy.nict.go.jp/LFstation/otakado/index.html
・highレベル → 60KHzモード
 はがね山標準電波送信所(60 kHz、羽金山)
 https://jjy.nict.go.jp/LFstation/hagane/index.html
※iPhoneアプリの疑似JJY信号出力(40KHz)に合わせた
TN信号出力ネガティブ信号出力
TPポジティブ信号出力
PプルダウンPower ON制御、lowレベルでON状態
回路図
結線図

RTCモジュールRX8900を使ったLCD時計部分の結線は本サイトの下記記事と同じです。この記事のスケッチでは、起動時にArduino IDEのコンパイル時間を使って時刻合わせを行いました。今回電波時計モジュールを追加したことでJJY信号の日時情報を使ってPC接続なしで時刻合わせできます。

あわせて読みたい
ArduinoとRTCモジュールRX8900を使ったLCD時計の製作(1) ArduinoとRX8900CE UAを搭載したRTC(リアルタイムクロック)モジュールを使ってLCD(液晶ディスプレイ)時計を作りました。 【 (2021/12/12追加) 】 ネット通販(...

スケッチ:受信状況をシリアルモニタに表示、RTCを更新してLCD表示

復号状況をシリアルモニタで観察

JJYのタイムコードに沿って、M、0、1のデコード進捗をリアルタイムでシリアルモニタに表示します。
配列に格納したデータが下記条件に合致すると「1」の重みづけに従って演算、日時を計算します。
・データ(0、1)と マーカー(M、P0~P5)の総数が「60」
・マーカー(M、P0~P5)の位置が 0秒、9秒、19秒、29秒、39秒、49秒、59秒 に存在

受信して復号した信号シリアルモニタで観察
デコード進捗をリアルタイムでシリアルモニタに表示中

・シリアルモニタでは、M、P0~P5の区別は行わず、すべてMと表示しています。
・Mの後に続く「(0)、(9)、(19)、(29)、(39)、(49)、(59)」は受信コードではありません。マーカーパルス(M)の出現タイミングを判り易くするためにプロラムで追加表示しています。

デジタルピンD2の入力信号波形をデジタルオシロスコープで観察

回路図中のTP端子(ArduinoデジタルピンD2とトランジスタ:2SC1815のコレクタ端子の間)にデジタルオシロスコープを接続して観察しました。

疑似JJYを受信した際のデジタルピンD2の入力信号波形は矩形波(振幅は約3.7V)でした。

デジタルオシロスコープで信号波形を観察
疑似JJYの信号波形

RTCモジュールRX8900を更新、LCDに日時、受信状況を表示

時刻合わせしたい時に、疑似JJY信号を発生するアプリを起動して最大ボリュームで再生、スピーカ付近を電波時計モジュールのバーアンテナに密着します。起動直後の受信状況のLCD表示は「i n i」です。

2~3分ほど密着してLCD画面上に「r e c」が表示されると同期完了です。下記スケッチでは密着して受信している間は1分に1回の頻度でRTCを更新(同期)しつづけます。

スマートフォンを遠ざけたり、アプリを終了するなど60秒間の全データの受信が正しくできなくなるとLCD表示が「 」変わり、RTCの更新(同期)処理は中断されます。RTCの更新(同期)が中断されてもLCDの時刻表示は続きます。

・3分以上たっても更新(同期)処理が完了しない時はArduino IDEのシリアルモニタで60個の取得データ(タイムコード)の並び順があっているかを確認します。
・スイッチング電源(ACアダプタ、スマートフォンのワイヤレス充電器)やノードPC等、電磁波を発生する機器が電波時計モジュールのバーアンテナの近くにあるとその影響で正しくデータ取得できないことがありました。影響の及ばない距離まで離して設置します。
・スマホで更新(同期)処理していない時もノイズなどを受信するとLEDが点滅します。ケースに実装する際はLED表示のON/OFFを付ける予定です。
・本スケッチは毎時15分、45分では時刻同期しません。

受信して復号した日時情報でRTCを更新してLCD表示
復号した日時情報でRTCを更新してLCD表示(「rec」表示で同期完了)

スケッチ(2023/02/26時点)

Arduino Uno Rev3で動作確認できたスケッチです。

スケッチ中の「//—-LCD時計x—」部分の5箇所がLCD時計に関係するスケッチ。それ以外のコードが電波時計モジュールから取得した日時信号をシリアルモニタに表示するスケッチです。LCD時計に関係するスケッチ部分を削除することでシリアルモニタのみで動作確認できます。

217~221行が電波時計モジュールで取得した日時データをLCD時計のRTCに書き込む箇所です。

arduino_radio_clock-v5.ino 
※ここをクリックするとコード表示を開閉できます。
//下記スケッチ中の「//----LCD時計x---」5箇所がLCD時計に関係するスケッチ
//それ以外のコードが電波時計モジュールから取得した日時信号をシリアルモニタに表示するスケッチ
//----LCD時計1--------------------------------------------
#include <Wire.h>          //Arduino IDE のI2Cライブラリ
#include <TimeLib.h>       //https://github.com/PaulStoffregen/Time
#include <RX8900RTC.h>     //https://github.com/citriena/RX8900RTC
#include <LcdCore.h>       //http://100year.cocolog-nifty.com/blog/2012/05/arduinoliquidcr.html
#include <LCD_ACM1602NI.h> //http://100year.cocolog-nifty.com/blog/2012/05/i2clcdarduino-b.html
RX8900RTC RTC;
LCD_ACM1602NI lcd(0xa0);   //0xa0は液晶モジュールのI2Cアドレス
//--------------------------------------------------------

char curr; //現在の読み込み値
char prev; //前回の読み込み値
long c_time; //ループ処理の経過時間
long p_time; //前回のループ処理の経過時間
long s_time; //ループ処理の経過時間の差分
char m01_code; //コード仕分け値(M、0、1)
int rp; //秒のカウント
int ct; //ループ回数のカウント、積算値
int ct_prev; //前回ループ時の回数
int ct_subt; //ループ回数の差分、正常読み込みであれば毎ループ終了時は「60」
int st_rec;  //受信フラグ(初期化、成功、失敗)
char d2bits[61]; //60間の読み込み値格納、null終端

void setup() {
Serial.begin( 9600 );
pinMode(2,INPUT); //D2ピンをINPUTモードに設定
c_time = 0;
p_time = 0;
s_time = 0;
m01_code = '0';
ct = 0;
ct_prev = 0;
ct_subt = 0;
st_rec  = 0; //受信フラグ:初期化

//----LCD時計2--------------------------------------------
Wire.begin();     //I2C初期化
lcd.begin(16, 2); //ディスプレイの行数(16)と桁数(2)
RTC.init();       //RTC初期化
//RTC.get()よりcompileTime()が新しい時はcompiletimeをRTC.set
time_t time_now, compiletime;;
time_now = RTC.get();
compiletime = compileTime();
if (time_now < compiletime) {
RTC.set(compiletime);  // set compiled time to RTC
//日時の手動設定(second, minute, hour, dayofweek, day, month, year)
//tmElements_t tm = {0, 0, 0, 4, 24, 3, CalendarYrToTm(2023)}; 
//RTC.write(tm);
}
//--------------------------------------------------------

}

 void loop() {
//----LCD時計3--------------------------------------------
serialTime(RTC.read());
//--------------------------------------------------------
//D2ポートから受信データの読み込み
  curr = digitalRead( 2 );
//前回読み込み値と現在の読み込み値の比較
    if( prev != curr ) {
      c_time = millis(); //ループ処理の経過時間(ms) 
//デジタルポートD2が 0(LOW)の場合の処理
      if( curr == LOW ) {
//前回処理と時間差がある場合のみ実行
        s_time = c_time - p_time;
//コード仕分け(パルス幅:M、P0~P5 200ms < 1:500ms < 0:800ms )
        //M、P0~P5 (200ms)の判定:マージンを見込んで(300ms)
        if( s_time < 300 ) { //マージンを見込んで300ms
          ct++;
          //前のコードがMか(Mが2回続いているか)のチェック、初期マーカー位置の判定
          //毎時15分と45分のコールサイン(モールス符号)受信時にctとct_prevの値はリセット
          if( m01_code == 'M' ) {  
            rp = 0; //60回(秒のカウント)のリセット、初期マーカー位置
            Serial.println( "" );
                         Serial.print( "読み込んだデータ数:" );
                         //Serial.print( ct ); 
                         //Serial.print( " - " );
                         //Serial.print( ct_prev ); 
                         //Serial.print( " = " );
            ct_subt = ct - ct_prev;
                         Serial.print( ct_subt ); 

//配列(タイムコード)をシリアルモニタに表示して確認
Serial.print( " ( " );
for(int mp=0;mp<60;mp++){
char c = char(d2bits[mp]);
Serial.print(c);
 }
Serial.print( " ) " );
Serial.println( "" );
//配列(タイムコード)内のマーカー位置の確認
int mp_chk = 0;
if(d2bits[0]=='M' && d2bits[9]=='M' && d2bits[19]=='M' && d2bits[39]=='M' && d2bits[49]=='M' && d2bits[59]=='M'){ 
 mp_chk = 1;
} else{
 mp_chk = 2; 
}
Serial.print( "マーカー位置の確認:" );
if( mp_chk == 1 ){ Serial.print( "OK" );}
if( mp_chk == 2 ){ Serial.print( "NG" );}
Serial.print( " ( " );
Serial.print( d2bits[0] );
Serial.print( "-" );
Serial.print( d2bits[9] );
Serial.print( "-" );
Serial.print( d2bits[19] );
Serial.print( "-" );
Serial.print( d2bits[29] );
Serial.print( "-" );
Serial.print( d2bits[39] );
Serial.print( "-" );
Serial.print( d2bits[49] );
Serial.print( "-" );
Serial.print( d2bits[59] );
Serial.println( " )" );
//60秒間のデータが揃ったか、マーカー位置チェックOKかの判定
if( ct_subt == 60 && mp_chk == 1) {
            st_rec  = 1; //受信フラグ:成功
//配列d2bitsから1bit毎に時刻データ取り出し、重みづけ
//分
int min = 0;
if(d2bits[8]=='1'){ min = min + 1; }
if(d2bits[7]=='1'){ min = min + 2; }
if(d2bits[6]=='1'){ min = min + 4; }
if(d2bits[5]=='1'){ min = min + 8; }
if(d2bits[3]=='1'){ min = min + 10; }
if(d2bits[2]=='1'){ min = min + 20; }
if(d2bits[1]=='1'){ min = min + 40; }
//時
int hour = 0;
if(d2bits[18]=='1'){ hour = hour + 1; }
if(d2bits[17]=='1'){ hour = hour + 2; }
if(d2bits[16]=='1'){ hour = hour + 4; }
if(d2bits[15]=='1'){ hour = hour + 8; }
if(d2bits[13]=='1'){ hour = hour + 10; }
if(d2bits[12]=='1'){ hour = hour + 20; }
//通算日
int day = 0;
if(d2bits[33]=='1'){ day = day + 1; }
if(d2bits[32]=='1'){ day = day + 2; }
if(d2bits[31]=='1'){ day = day + 4; }
if(d2bits[30]=='1'){ day = day + 8; }
if(d2bits[28]=='1'){ day = day + 10; }
if(d2bits[27]=='1'){ day = day + 20; }
if(d2bits[26]=='1'){ day = day + 40; }
if(d2bits[25]=='1'){ day = day + 80; }
if(d2bits[23]=='1'){ day = day + 100; }
if(d2bits[22]=='1'){ day = day + 200; }
//西暦(下2桁)
int year = 0;
if(d2bits[48]=='1'){ year = year + 1; }
if(d2bits[47]=='1'){ year = year + 2; }
if(d2bits[46]=='1'){ year = year + 4; }
if(d2bits[45]=='1'){ year = year + 8; }
if(d2bits[44]=='1'){ year = year + 10; }
if(d2bits[43]=='1'){ year = year + 20; }
if(d2bits[42]=='1'){ year = year + 40; }
if(d2bits[41]=='1'){ year = year + 80; }
//西暦(4桁)
int ayear = ( year + 2000 ) ;
//曜日
int youbi = 0;
if(d2bits[52]=='1'){ youbi = youbi + 1; }
if(d2bits[51]=='1'){ youbi = youbi + 2; }
if(d2bits[50]=='1'){ youbi = youbi + 4; }
//1分加算と分、時、日、年、うるう年、曜日への影響反映
min++; //1分加算
if(min>=60){ min=0; hour++;
  if(hour>=24){ hour=0; day++;
    int leap_year = ( (1 / (ayear % 4 + 1)) * (1 - 1 / (ayear % 100 + 1)) + (1 / (ayear % 400 + 1)) ); //うるう年判定
    int set_year = ( 365 + leap_year );
    if(day > set_year ){ day=1; year++; }
    youbi++;
    if( youbi>=7){ youbi=0; }
  }
}
//通算日から月、日への変換
int t_day = 0; //通算日の計算用
int mm; //月
int dd; //日
int leap_year = ( (1 / (ayear % 4 + 1)) * (1 - 1 / (ayear % 100 + 1)) + (1 / (ayear % 400 + 1)) ); //うるう年判定
int mdtable[2][12] = { 31,28,31,30,31,30,31,31,30,31,30,31, 31,29,31,30,31,30,31,31,30,31,30,31 }; //通年とうる年の日数
//1月から順に月の日数を引いて月、日を算出
for(int i=0;i<12;i++){
  if((t_day + mdtable[leap_year][i])>=day){
    mm = i+1;
    dd = day - t_day;
    break;
  }
  t_day = t_day + mdtable[leap_year][i];
}
//曜日を3桁英字への変換
char dayofweek[7][4] = {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"} ;
char f_youbi[4];
strcpy(f_youbi, dayofweek[youbi]);
//日時をシリアルモニタに表示して確認
Serial.print( "日時変換:" );
                Serial.print(ayear);
            Serial.print( "/" );
                Serial.print(mm);
            Serial.print( "/" );
                Serial.print(dd);
            Serial.print( "(" );
                Serial.print(f_youbi);
            Serial.print( ")" );
            Serial.print( " " );
                Serial.print(hour);
            Serial.print( ":" );
                Serial.print(min);
            Serial.print( ":" );
                Serial.print(rp); //秒
            Serial.println( "" );

//----LCD時計4--------------------------------------------
//受信した日時データをRTCに書込み
tmElements_t tm = {rp, min, hour, youbi, dd, mm, CalendarYrToTm(ayear)}; 
RTC.write(tm);
//--------------------------------------------------------

            } else {
            //配列クリア
             for(int i=0;i<60;i++){
             d2bits[i] = ' ';
             }
            //受信フラグ:失敗
            st_rec  = 9;
            Serial.println( "日時変換:SKIP" );
            }
            Serial.println( "" );
          ct_prev = ct; 
          }
          Serial.print( "M" );
                    Serial.print( "(" );
                    Serial.print( rp ); //マーカー位置の番号
                    Serial.print( ")" );
          m01_code = 'M';
          d2bits[rp] = 'M'; //rp番目の配列に格納
                  rp++; //60ループ回のカウントアップ
        //1(500ms)の判定:マージンを見込んで(600ms)
        } else if( s_time < 600 ) {
          ct++;
          Serial.print( "1" );
          d2bits[rp] = '1'; //rp番目の配列に格納
          m01_code = '1';
                  rp++; //60回ループのカウントアップ
        //0(800ms)の判定
        } else {
          ct++;
          Serial.print( "0" );
          d2bits[rp] = '0'; //rp番目の配列に格納
          m01_code = '0'; 
                  rp++; //60回ループのカウントアップ
        } 
      }
    }
  prev = curr;  //現在の読み込み値を保存
  p_time = c_time; //現在の経過時間(ms)を保存
}


//----LCD時計5---------------------------------------------
//秋月I2C液晶ディスプレイに日時を表示
void serialTime(tmElements_t tm) {
//年月日の表示
lcd.setCursor(0, 0);
lcd.print(tmYearToCalendar(tm.Year));
lcd.setCursor(4, 0);
lcd.print("/");
lcd.setCursor(5, 0);
lcdzeroSup(tm.Month);
lcd.setCursor(7, 0);
lcd.print("/");
lcd.setCursor(8, 0);
lcdzeroSup(tm.Day);
//曜日の表示 0=日曜  1=月曜  2=火曜  3=水曜  4=木曜  5=金曜  6=土曜
int day_week ;
char DayWeekData[7][4] = {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"} ;
day_week = getDayWeek(tmYearToCalendar(tm.Year), tm.Month, tm.Day) ;
lcd.setCursor(11, 0);
lcd.print("(");
lcd.print(DayWeekData[day_week]) ;
lcd.print(")");
//時分秒の表示
lcd.setCursor(0, 1);
lcdzeroSup(tm.Hour);
lcd.setCursor(2, 1);
lcd.print(":");
lcd.setCursor(3, 1);
lcdzeroSup(tm.Minute);
lcd.setCursor(5, 1);
lcd.print(":");
lcd.setCursor(6, 1);
lcdzeroSup(tm.Second);
lcd.setCursor(12, 1);
//受信状況の表示
       if (st_rec == 0) {
    lcd.print( "ini" ); //初期化完了
  }else if(st_rec == 1) {
    lcd.print( "rec" ); //受信成功
  }else if(st_rec == 9) {
    lcd.print( "---" ); //受信失敗
  }else{
    lcd.print( "ooo" );
  }
}
//曜日の計算(ツェラー(Zeller)の公式)
int getDayWeek(int year,int month,int day) {
int w ;
if(month < 3) {
year = year - 1;
month = month + 12 ;
 }
w = (year + (year/4) - (year/100) + (year/400) + (13*month+8)/5 + day ) % 7;
return w;
}
//月、日、時、分、秒が0~9の場合、1桁目を 空白 もしくは 0 に置換
void lcdzeroSup(int digit) {
if(digit < 10)
lcd.print(' '); //現在「空白」
lcd.print(digit);
}
// function to return the compile date and time as a time_t value
// from alarm_ex1.ino in Arduino DS3232RTC Library sample sketch by Jack Christensen.
time_t compileTime() {
const time_t FUDGE(10);    //fudge factor to allow for upload time, etc. (seconds, YMMV)
const char *compDate = __DATE__, *compTime = __TIME__, *months = "JanFebMarAprMayJunJulAugSepOctNovDec";
char compMon[4], *m;
strncpy(compMon, compDate, 3);
compMon[3] = '\0';
m = strstr(months, compMon);
tmElements_t tm;
tm.Month = ((m - months) / 3 + 1);
tm.Day = atoi(compDate + 4);
tm.Year = atoi(compDate + 7) - 1970;
tm.Hour = atoi(compTime);
tm.Minute = atoi(compTime + 3);
tm.Second = atoi(compTime + 6);
time_t t = makeTime(tm);
return t + FUDGE;        //add fudge factor to allow for compile time
}
//--------------------------------------------------------
よかったらシェアしてね!
  • URLをコピーしました!
目次