07.CoreInkで実用時計
7.CoreInkで実用時計
wifi経由で時刻をntp.nict.jpから取得して時計を作成します。15秒ごとに更新しているので年月日・曜日・時分秒が実際と十数秒以内で違っている場合があります。
説明
スケッチ例にあるRTC_BM8563.inoを改良しました。西暦y年m月d日の曜日を求める式。
- 1月と2月は、前年の13月と14月とする。例) 2021/1/15→2020/13/15
- [x]は、xを超えない最大の整数
- x mod n は、xをnで割った剰余
- Y=y mod 100
- h=0(土),1(日),2(月),…,6(金)
h={d+[26(m+1)/10]+Y+[Y/4]-2[y/100]+[[y/100]/4]} mod 7
で求まります。ただし、実際の計算は、
- m<=2 なら y=y-1; m=m+12
- [x]=floor(x)で、#include <math.h>が必要
- y2=y%100
- 上式 -2 の所は7加算した +5 でも可。(全部加算になる)
h=(d + floor(2.6*(m+1)) + y2 + floor(y2*0.25) + 5*floor(y*0.01) + floor(y*0.0025)) % 7
となります。
https://ja.wikipedia.org/wiki/%E3%83%84%E3%82%A7%E3%83%A9%E3%83%BC%E3%81%AE%E5%85%AC%E5%BC%8F
スケッチ
スケッチ内のxxxxxに、自分のwifiのSSIDとそのパスワードを記入します。
// 時計 wifi経由して時刻をntpから取得
#include <M5CoreInk.h> // M5Stack CoreInk使用
#include <WiFi.h> // wifi使用
#include <time.h> // time.hの構造体使用
#include <math.h> // floor関数を使用
const char* ssid = "xxxxx"; // 自分のwifiのSSID
const char* password = "xxxxx"; // wifiのパスワード
static const char *wd[7] = {"SAT", "SUN", "MON", "TUE", "WED", "THU", "FRI"};//曜日配列
char timeStr[64]; // 表示文字列 64文字の配列の宣言
int y, y2, m, d, youbi; // 年4桁,年下2桁,月,日,曜日の変数
Ink_Sprite InkPageSprite(&M5.M5Ink); //
RTC_TimeTypeDef RTCtime; // 定義
RTC_DateTypeDef RTCDate; // 定義
void inkSet() { // お決まり
M5.begin(); // E-Ink,RTC,I2C,ブザーを初期化
if (!M5.M5Ink.isInit()) { // 初期化出来なければ
Serial.println("エラー Ink Init"); // シリアルモニタに表示
while (1) delay(100); // ずっと待つ
}
M5.M5Ink.clear(); // 画像クリア
delay(1000); // 1秒待つ
if (InkPageSprite.creatSprite(0, 0, 200, 200, true) != 0) {
// 画像領域が作成できなければ
Serial.println("エラー Ink Sprite creat"); // シリアルモニタに表示
}
}
void wifiSet() { // お決まり
Serial.print(ssid); // シリアルモニタに表示
Serial.print("に接続中"); // シリアルモニタに表示
WiFi.begin(ssid, password); // ネット設定を初期化
while (WiFi.status() != WL_CONNECTED) { // 接続状態が接続完でない時
delay(500); // 0.5秒待つ
Serial.print("."); // シリアルモニタに表示
}
Serial.println("ok"); // シリアルモニタに表示
}
void setup() {
struct tm timeInfo; // 構造体定義
inkSet(); // CoreInkの設定
wifiSet(); // wifiの設定
configTime(9 * 3600L, 0, "ntp.nict.jp", "ntp.jst.mfeed.ad.jp");
// ntpの設定 (UTC→JSTのオフセット秒,夏時間オフセット,日本標準時刻サーバー)
getLocalTime(&timeInfo); // 時刻取得
RTCDate.Year = timeInfo.tm_year; // 年
RTCDate.Month = timeInfo.tm_mon; // 月
RTCDate.Date = timeInfo.tm_mday; // 日
M5.rtc.SetData(&RTCDate); // RTC日付構造体を設定
RTCtime.Hours = timeInfo.tm_hour; // 時
RTCtime.Minutes = timeInfo.tm_min; // 分
RTCtime.Seconds = timeInfo.tm_sec; // 秒
M5.rtc.SetTime(&RTCtime); // RTC時刻構造体を設定
WiFi.disconnect(true); // ネットワークから切断
WiFi.mode(WIFI_OFF); // wifiの動作モード
Serial.print("wifi offか="); // シリアルモニタに表示
Serial.println(WiFi.status()); // wifiの接続状態
// 0(WiFi.beginが呼出され3or4になるまで),1(使用可能なSSIDがない)
// 2(スキャン完了),3(WiFi接続),4(すべての試行で接続失敗)
// 5(接続が失われた),255(WiFiシールドがない)
}
void loop() {
M5.rtc.GetData(&RTCDate); // RTC日付構造体を取得
M5.rtc.GetTime(&RTCtime); // RTC時刻構造体を取得
y = RTCDate.Year + 100; // 年
m = RTCDate.Month + 1; // 月
if (m <= 2) { // ツェラーの公式参照
y = y - 1;
m = m + 12;
}
y2 = y % 100;
d = RTCDate.Date; // 日
youbi = (d + (int)(floor(2.6 * (m + 1))) + y2 + (int)(floor(y2 * 0.25)) + 5 * (int)(floor(y * 0.01)) + (int)(floor(y * 0.0025))) % 7;
sprintf(timeStr, "%04d/%02d/%02d(%3s) %02d:%02d:%02d",
RTCDate.Year + 100, RTCDate.Month + 1, RTCDate.Date,
wd[youbi], RTCtime.Hours, RTCtime.Minutes,
RTCtime.Seconds); // 文字列を作る
Serial.println(timeStr); // シリアルモニタに表示
InkPageSprite.drawString(4, 5, timeStr); // (x,y)に文字列を描く
InkPageSprite.pushSprite(); // 画面更新
delay(15000); // 15秒(=最小間隔)ごとに時刻更新
}