NTPで取得した時刻をRTCへセットする(続編)

 「NTPで取得した時刻をRTCへセットする」の続編です。


NTPとRTCを組み合わせる方法を考えてみました。

NTPから時刻を取得し、取得出来た時のみRTCを

合わせます。

(スケッチ例や作例を公開している方々に感謝します。)


今回は

Arduion UNOとEthernet shield、DS3231 I2C RTCモジュール

を使って、スケッチ例Ethernet2 UdpNtpCilentの改変でやっ

てみました。


ArduinoUNOとEthernetShieldとI2C RTC DS3231













スケッチを紹介します。

※変更のないところは省略していますので、オリジナルの

スケッチ例からコピペして下さい。わかりやすくするため、

変更がなくても表示している所もあります。


/* Arduino UNO ,Ethernet shield ,ds3231 I2C RTC

* スケッチ例Ethernet2 Udp NTP Clientにds3231 RTCを追加して、RTCを

* adjustする機能を追加して取得できた時はNTP時刻でRTCをadjustする。

* 取得できなかった時は取得できるまでアクセス間隔を短く変更する。

* 日本時間に直して、シリアルモニタへ表示する。

* 改変 hiro yamamoto works 2020.08.21*/


#include <SPI.h>

#include <Ethernet2.h>

#include <EthernetUdp2.h>

#include <Time.h>

#include <TimeLib.h>

#include <Wire.h>

#include "RTClib.h"

#define UTC_TOKYO +9

// Enter a MAC address for your controller below.

// Newer Ethernet shields have a MAC address printed on a sticker on the shield

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };

unsigned int localPort = 8888; // local port to listen for UDP packets

char timeServer[] = "time.nist.gov"; // time.nist.gov NTP server

const int NTP_PACKET_SIZE = 48; // NTP time stamp is in the first 48 bytes of the message

byte packetBuffer[ NTP_PACKET_SIZE]; //buffer to hold incoming and outgoing packets

unsigned long unixtime;//

char date_ymdhms[21]; // yyyy/mm/dd,hh:mm:ssn0

unsigned long previousMillis = 0;//

const long interval = 60000;//60000 :1分 3600000 :1h

int ntpAccsCount = 0;//NTP accsess count

int accsInterval = 60;//NTP accsess interval 1分を60回なので60分

// A UDP instance to let us send and receive packets over UDP

EthernetUDP Udp;

RTC_DS3231 rtc;

void setup() {

// Open serial communications and wait for port to open:

Serial.begin(9600);

/*while (!Serial) {//Leonardoなら/**/取ってcodeを有効にして下さい。

; // wait for serial port to connect. Needed for Leonardo only

}*/

// start Ethernet and UDP

if (Ethernet.begin(mac) == 0) {

Serial.println("Failed to configure Ethernet using DHCP");

// no point in carrying on, so do nothing forevermore:

for (;;)

;

}

//Serial.println(Ethernet.localIP());

Udp.begin(localPort);

if (! rtc.begin()) {

Serial.println("Couldn't find RTC");

while (1);

}

if (rtc.lostPower()) {

Serial.println("RTC lost power, lets set the time!");

// following line sets the RTC to the date & time this sketch was compiled

rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));

// This line sets the RTC with an explicit date & time, for example to set

// January 21, 2014 at 3am you would call:

// rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));

}

}

void loop() {

/* 起動初期はRTC時刻は合っていない。rtc.lostPower()の時は

コンパイル時刻が設定されている。

起動初期だけ早くNTP時刻を取得して、RTC時刻を合わせたい。

通常動作時のNTPアクセス頻度は1日あたり数回(RTCの日差を補正できる

妥当な回数を設定)intervalを1分ぐらいにしておいて、繰返し回数を

カウント、指定回数になったらNTPアクセス。起動時ntpAccsCountは

0でNTPアクセス、アクセス後Udp.parsePacket()の戻り値がなかったら

繰返しカウントを指定回数まで進めて、NTPアクセス頻度を上げる。*/

unsigned long currentMillis = millis();

if (currentMillis - previousMillis >= interval) {

previousMillis = currentMillis;

if (ntpAccsCount == 0) {

//変更がないところ中略


time_t t = unixtime + (UTC_TOKYO * 60 * 60);//日本時間へ調整

// wait ten seconds before asking for the time again

//delay(10000);

//adjust RTC time

rtc.adjust(DateTime(year(t), month(t), day(t), hour(t), minute(t), second(t)));

Serial.println("adjust RTC time");

} else {

Serial.println("no packet yet");

ntpAccsCount = accsInterval;/*NTPアクセスできなかった時はカウント値を変えて

アクセスタイミングを早める。*/

}

}

ntpAccsCount++;//NTP accsess count

if (ntpAccsCount >= accsInterval) {//accsess interval

ntpAccsCount = 0;

}

}

delay(1000);

DateTime now = rtc.now();//RTCの現在時刻を読む

sprintf(date_ymdhms, "%04d/%02d/%02d,%02d:%02d:%02d", now.year(), now.month(), now.day(), now.hour(), now.minute(), now.second());//

Serial.println(date_ymdhms);//


}

//以降変更がないので省略


無保証自己責任でよろしくおねがいします。

コメント

このブログの人気の投稿

ESP32pcntカウンタをテストしてみた

データロガーで温湿度記録計を作る。