1. はじめに
卓上にある 電波時計は 電子機器に囲まれているせいか まったく電波を拾いません。(上の写真は撮影前に、場所を移動させて 電波同期 させました。)
そこで、手元にあった M5StackC Plus2 で NTP同期時計 を実装して、どれほど 時刻がずれていくのかを 比較できるようにしました。そのため、秒を強調した表示としています。
Arduino-IDEを使用して、
大まかな構造は、次の記事を参考にさせていただきました。
NTP同期の完了を待つ処理を追加しました。
また、起動時に必ず NTP同期させるため、M5.RTCは未使用です。
2. コード
ntp-clock.ino
#include <M5StickCPlus2.h>
#include <WiFi.h>
#include <time.h>
#include <esp_sntp.h>
// Wi-Fi 設定(自分のWi-Fi情報に変更)
const char* ssid = "YOUR_WIFI_SSID"; // Wi-FiのSSID
const char* password = "YOUR_WIFI_PASS"; // Wi-Fiのパスワード
// NTPサーバー設定
const char* ntpServer1 = "ntp.nict.jp";
const char* ntpServer2 = "pool.ntp.org";
const long gmtOffset_sec = 9 * 3600; // 日本時間(UTC+9)
const int daylightOffset_sec = 0; // 夏時間なし
bool showClock = false; // 時計を表示するフラグ
struct tm timeInfo;
int lastSec;
bool sntp_sync_status_complete = false;
void SntpTimeSyncNotificationCallback(struct timeval* tv) {
if (sntp_get_sync_status() == SNTP_SYNC_STATUS_COMPLETED) {
sntp_sync_status_complete = true;
}
}
void setup() {
M5.begin();
M5.Lcd.setRotation(3);
M5.Lcd.fillScreen(BLACK);
M5.Lcd.setTextColor(WHITE);
M5.Lcd.setTextSize(2);
// 起動時のメッセージ
M5.Lcd.println("Connecting to Wi-Fi.");
// Wi-Fi 接続
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
M5.Lcd.print(".");
delay(500);
}
M5.Lcd.println("\nWi-Fi Connected!");
// NTPで時刻を同期
sntp_set_time_sync_notification_cb(SntpTimeSyncNotificationCallback);
configTime(gmtOffset_sec, daylightOffset_sec, ntpServer1, ntpServer2);
// 同期周期を取得
auto default_interval = sntp_get_sync_interval(); // ミリ秒単位
M5.Lcd.printf("sync: %d hours ", default_interval / 1000 / 3600);
//同期するまで待つ
while (!sntp_sync_status_complete) {
M5.Lcd.print(".");
delay(500);
}
M5.Lcd.println("\nSNTP sync completed.");
if (getLocalTime(&timeInfo)) {
lastSec = timeInfo.tm_sec;
} else {
M5.Lcd.println("Failed to obtain time.");
return;
}
/* 以降も同期周期にてNTP同期させる場合は、次の2行をコメント化する */
WiFi.disconnect(true);
WiFi.mode(WIFI_OFF);
M5.Lcd.println("Setup completed.");
//M5.Lcd.printf("w: %d, h: %d ", M5.Lcd.width(), M5.Lcd.height());
}
void loop() {
M5.update();
// 現在時刻を取得
getLocalTime(&timeInfo);
// Aボタンが押されたら時計を表示
if (M5.BtnA.wasPressed()) {
showClock = true;
M5.Lcd.setRotation(0);
}
// 時計を表示する場合、1秒ごとに更新
if (showClock && (lastSec != timeInfo.tm_sec)) {
lastSec = timeInfo.tm_sec;
displayClock();
}
}
void displayClock() {
M5.Lcd.startWrite();
M5.Lcd.fillScreen(BLACK);
M5.Lcd.setTextColor(DARKGREY);
M5.Lcd.setCursor(0, 0, 4); //x,y,font 4:26ピクセルASCIIフォント
M5.Lcd.printf("%02d:%02d", timeInfo.tm_hour, timeInfo.tm_min); // 時分を表示
M5.Lcd.setTextColor(GREEN);
M5.Lcd.setCursor(0, 40, 7); //x,y,font 7:48ピクセル7セグ風フォント
M5.Lcd.printf("%02d", timeInfo.tm_sec); // 秒を表示
M5.Lcd.setTextColor(DARKGREY);
M5.Lcd.setCursor(0, 132, 2); //x,y,font 2:16ピクセルASCIIフォント
M5.Lcd.printf("%04d/ %02d/%02d", timeInfo.tm_year + 1900, timeInfo.tm_mon + 1, timeInfo.tm_mday);
double voltage = (double)M5.Power.getBatteryVoltage() / 1000.0;
M5.Lcd.setCursor(0, 206, 1);
M5.Lcd.printf("Bat: %.1f v", voltage);
M5.Lcd.endWrite();
}
フォント(サイズ)については、次の記事を参考にさせていただきました。
3. 起動時
約2秒でWiFi接続が完了
Connecting to Wi-Fi.
....
Wi-Fi Connected!
NTP同期周期 3時間
sync: 3 hours
約5秒でNTP同期が完了
.........
SNTP sync completed.
同期周期は 3時間のようですが、起動時は速やかに同期しているようです。
セットアップ完了
Setup completed.
正面に大きく`M5`と見える ボタンを押して、時計表示へ
4. 時計表示
理論上、最大1秒未満のずれが発生します。
電波時計が”電波非同期”状態になったら、毎日ズレを観察して「電波時計を同期させる周期」を考える材料にしようと思います。
5. 使用した M5StickC Plus2 の ESP32情報
$ esptool --port /dev/cu.usbserial-586B0035891 --chip auto flash-id
esptool v5.1.0
Connected to ESP32 on /dev/cu.usbserial-586B0035891:
Chip type: ESP32-PICO-V3-02 (revision v3.1)
Features: Wi-Fi, BT, Dual Core + LP Core, 240MHz, Embedded Flash, Embedded PSRAM, Vref calibration in eFuse, Coding Scheme None
Crystal frequency: 40MHz
MAC: 10:06:1c:27:XX:YY
Stub flasher running.
Flash Memory Information:
=========================
Manufacturer: 20
Device: 4017
Detected flash size: 8MB
Flash voltage set by a strapping pin: 3.3V
Hard resetting via RTS pin...
Happy New Year 2026
10秒前〜
今年もどうぞよろしくお願いいたします。
以上
