【電子工作】RTC NTP時刻書込み テストボードの製作
RTCを利用するにあたり、時刻情報の確認やNTPサーバから時刻情報を取得し、時刻合わせが可能な ”RTC簡易テスト時計”を製作します。
RTCとは
RTC:リアルタイムクロックの略称、年月日・時刻などの情報を処理する専用の電子部品、モジュールまたそれらのソフトウエアを指します。
構成
簡易・テスト用に便利なブレッドボードで構成し組上げます。
マイコン
Wi-Fi機能を搭載した小型マイコンボード「XIAO ESP32C3」を使用します。
BluetoothとWi-Fi機能を搭載したマイコンボード。
21 x 17.5 mmと小型(ポータブル・軽量)で、IoT、簡易アプリケーションに最適
ディスプレイ
マイコン接続で定評のある、有機LED(OLED)を用い、
I2C接続、128×64グラフィックディスプレイモジュールを使用します。
機能
RTCに設定されている現状の時刻情報をディスプレイに表示
(年月日+時分秒を簡易秒単位にて時計表示)
初期状態やバックアップ電池交換時等のリセット、または時刻ずれ時等
WI-FI接続によるNTPサーバーから時刻情報を取得し再設定を行います。
廉価タイプ
通販でお馴染みのアマゾンにて、比較的容易に入手可能で汎用的な、
ブランド:FTVOGUE DS3231搭載 RTCモジュール
安価ですが、品質には問題がありそうです(実験には十分ですが・・・)
※本モジュール入手時、はんだ付けに難があり劣化(腐食)が見られました
その他の構成する主要部品も、同アマゾンで入手可能な製品にて構成してみました。
- RTC
- マイコン
回路図
プログラム(スケッチ)
#include <WiFi.h>
#include <time.h>
#include <DS3232RTC.h>
#include <esp_sntp.h>
#include <stdio.h>
#include <string.h>
#include <Wire.h>
#include "SSD1306Wire.h"
SSD1306Wire display(0x3c, 6, 7);
DS3232RTC myRTC(false);
const char* weekStr[7] = {"Sun","Mon","Tue","Wed","Thr","Fri","Sat"};
// const char* ssid = "your ssid";
// const char* password = "your password";
const char* ssid = "SSSSSSSS";
const char* password = "pppppppp";
const char* ntpServer = "ntp.nict.jp";
const long gmtOffset_sec = 32400;
const int daylightOffset_sec = 0;
const long tmmYear = 0;
struct tm timeInfo;
char rdate[30], rtime[30];
// d-s/w , W-LED
#define int_pin 20
#define deb_pin 8
void setup() {
pinMode(int_pin, INPUT);
pinMode(deb_pin, OUTPUT);
// SSD1306 Initial pocess;
display.init(); // 初期化
display.flipScreenVertically(); // 反転
display.setFont(ArialMT_Plain_10); // 10フォント
display.drawString(0,0,"= DS3231 Setting board ="); // TITLE文字
display.display(); // 初期表示
delay(500);
display.setFont(ArialMT_Plain_16); // 16フォント
// TIME Initial process;
Serial.begin(9600);
myRTC.begin();
digitalWrite(deb_pin, LOW);
}
void loop() {
// RTC 表示
rtc_disp();
// time set S/W 判定
if(digitalRead(int_pin) == HIGH) {
jst_time_set();
digitalWrite(deb_pin, LOW);
}
delay(1000);
}
// RTC DISP process
void rtc_disp() {
// RTCから時刻取得
tmElements_t tm;
myRTC.read(tm);
// LCD表示
display.clear();
display.setFont(ArialMT_Plain_10); // 10フォント
display.drawString(0,0,"= DS3231 Setting board ="); // TITLE
display.setFont(ArialMT_Plain_16); // 16フォント
sprintf(rdate, " %04d/%02d/%02d [%s]",
tm.Year+1970, tm.Month, tm.Day, weekStr[tm.Wday - 1]);
sprintf(rtime, " %02d:%02d:%02d",
tm.Hour, tm.Minute, tm.Second);
display.drawString(0, 32,rdate);
display.drawString(18, 48,rtime);
display.display();
}
// W-TIME process
void jst_time_set() {
digitalWrite(deb_pin, HIGH);
// Wi-Fi接続
WiFi.begin(ssid, password);
while(WiFi.status() != WL_CONNECTED) {
display.drawString(0, 16,"Wi-Fi connecting..");
display.display();
delay(500);
}
// Wi-Fi接続表示
display.clear();
display.drawString(0, 16,"Wi-Fi Connected");
delay(1000);
display.display();
display.clear();
// NTPからJST取得
configTime(gmtOffset_sec, daylightOffset_sec,ntpServer);
display.drawString(0, 16,"JST Getting...");
display.display();
delay(2000);
display.clear();
// RTC - NTP マッチング
while (sntp_get_sync_status() == SNTP_SYNC_STATUS_RESET) {
display.drawString(0, 16,">...");
display.display();
delay(500);
}
// RTC Setting表示
display.clear();
display.drawString(0, 16,"TIME Setting...");
display.display();
delay(1000);
// RTC時刻取得
getLocalTime(&timeInfo);
// setTime(16, 0, 0, 12, 12, 2023); // 時刻設定(時、分、秒、日、月、年) 手動設定 , Debug
setTime(timeInfo.tm_hour, timeInfo.tm_min, timeInfo.tm_sec, timeInfo.tm_mday, timeInfo.tm_mon + 1, timeInfo.tm_year + 1900);
myRTC.set(now());
// Wi-Fi切断
WiFi.disconnect(true);
WiFi.mode(WIFI_OFF);
}
汎用タイプ
セイコーエプソン “RX-8025NB” を使用した、「秋月電子」のRTCモジュールを利用します。
モジュール化されていますが、バックアップ処理が未搭載の回路構成ですので、
同、秋月電子にて入手可能のリチウムボタン電池にてバックアップ回路を追加しました。
回路図
プログラム(スケッチ)
#include <WiFi.h>
#include <Wire.h>
#include <TimeLib.h>
#include <RTC_RX8025NB.h>
RTC_RX8025NB rtc;
#include <esp_sntp.h>
#include <stdio.h>
#include <string.h>
#include <Wire.h>
#include "SSD1306Wire.h"
SSD1306Wire display(0x3c, 6, 7);
const char* weekStr[7] = {"Sun","Mon","Tue","Wed","Thr","Fri","Sat"};
// const char* ssid = "your ssid";
// const char* password = "your password";
const char* ssid = "ssssssss";
const char* password = "pppppppp";
const char* ntpServer = "ntp.nict.jp";
const long gmtOffset_sec = 32400;
const int daylightOffset_sec = 0;
const long tmmYear = 0;
struct tm timeInfo;
tmElements_t tm;
char rdate[30], rtime[30];
int i_year, i_mon, i_mday, i_hour, i_min, i_sec;
// d-s/w , W-LED
#define int_pin 20
#define deb_pin 8
void setup() {
pinMode(int_pin, INPUT);
pinMode(deb_pin, OUTPUT);
// SSD1306 Initial pocess;
display.init(); // 初期化
display.flipScreenVertically(); // 反転
display.setFont(ArialMT_Plain_10); // 10フォント
display.drawString(0,0,"= 8025NB Setting board ="); // TITLE文字
display.display(); // 初期表示
delay(500);
display.setFont(ArialMT_Plain_16); // 16フォント
// TIME Initial process;
Serial.begin(9600);
Wire.begin();
}
// 曜日算出 Zeller's congruence
// in : year,month,day out : 0:日 ~ 6:土
byte calc_dayweek( int year, int month, int day ) {
if( month <= 2 ) {
month += 12;
year--;
}
return (byte)((year + year/4 - year/100 + year/400 + ((13 * month + 8)/5) + day) % 7);
}
void loop() {
// RTC 表示
rtc_disp();
// time set S/W 判定
if(digitalRead(int_pin) == HIGH) {
jst_time_set();
digitalWrite(deb_pin, LOW);
}
delay(1000);
}
// W-TIME process
void jst_time_set() {
digitalWrite(deb_pin, HIGH);
// Wi-Fi接続
WiFi.begin(ssid, password);
while(WiFi.status() != WL_CONNECTED) {
display.drawString(0, 16,"Wi-Fi connecting..");
display.display();
delay(500);
}
// Wi-Fi接続表示
display.clear();
display.drawString(0, 16,"Wi-Fi Connected");
delay(1000);
display.display();
display.clear();
// NTPからJST取得
configTime(gmtOffset_sec, daylightOffset_sec,ntpServer);
display.drawString(0, 16,"JST Getting...");
display.display();
delay(2000);
display.clear();
// RTC - NTP マッチング
while (sntp_get_sync_status() == SNTP_SYNC_STATUS_RESET) {
display.drawString(0, 16,">...");
display.display();
delay(2000);
}
// RTC Setting表示
display.clear();
display.drawString(0, 16,"TIME Setting...");
display.display();
delay(1000);
// RTC時刻取得
getLocalTime(&timeInfo);
tm.Year = timeInfo.tm_year;
tm.Month = timeInfo.tm_mon+1;
tm.Day = timeInfo.tm_mday;
tm.Hour = timeInfo.tm_hour;
tm.Minute = timeInfo.tm_min;
tm.Second = timeInfo.tm_sec;
rtc.setDateTime(tm.Year, tm.Month, tm.Day, tm.Hour, tm.Minute, tm.Second);
// rtc.setDateTime(2024, 7, 1, 12, 12, 12); // 時刻設定(時、分、秒、日、月、年) 手動設定 , Debug
// Wi-Fi切断
WiFi.disconnect(true);
WiFi.mode(WIFI_OFF);
}
// RTC DISP process
void rtc_disp() {
tmElements_t tm = rtc.read();
char s[20];
// Serial info , Debug
sprintf(s, "%d/%d/%d %d:%d:%d", tmYearToCalendar(tm.Year), tm.Month, tm.Day, tm.Hour, tm.Minute, tm.Second);
Serial.println(s);
// LCD表示
display.clear();
display.setFont(ArialMT_Plain_10); // 10フォント
display.drawString(0,0,"= 8025NB Setting board ="); // TITLE
display.setFont(ArialMT_Plain_16); // 16フォント
// Get Week ID
tm.Wday = calc_dayweek(tmYearToCalendar(tm.Year), tm.Month, tm.Day);
//
sprintf(rdate, " %04d/%02d/%02d [%s]",
tmYearToCalendar(tm.Year), tm.Month, tm.Day, weekStr[tm.Wday+0]);
sprintf(rtime, " %02d:%02d:%02d",
tm.Hour, tm.Minute, tm.Second);
display.drawString(0, 32,rdate);
display.drawString(18, 48,rtime);
display.display();
}
まとめ
”RTC簡易テスト時計”として、現状のRTC保存データから時を表示。
NTPサーバーから時刻情報を取得し再設定しました。
比較的に入手が容易な電子部品を採用し、2組としてテスト実施。
RTCを利用する目的としたテスト機に伴い、秒処理は簡素的にdelay loopで組合せ、
シンプルな簡易時計して表示し作成しました。