正確な時刻を、みんなで共有したいのよ
世はすっかりテレワーク時代、カレンダーだのTV会議だので、より一層「遅刻」が目立っちゃう、そんな時代になりました。
会社に出社しても、まあ人はまばらなのですが、だからこそ時間を忘れてゴニョゴニョしてしまう例もちらほら。
なのに会社の掛け時計、とまってたり盛大にずれていたりで、信用できません。
なので、NTPな掛け時計を作ってみることに。
LEDパネルとESP32で!
ま、表示器は、マトリックスLEDでいいでしょう。
一般的なHUB75な、64x32のP5をチョイス。
Adafruitのだと、このへんです。
https://www.marutsu.co.jp/pc/i/27108615/
信頼と実績のRaspberry Pi + rpi-rgb-led-matrixでもいいのですが。
まあ単機能なので、今回はESP32を使ってみることに。
ESP32には、「WROOM」という、BTやWIFIが入り且つモジュール化され技適もOKな素敵さんがあるので、それで。
・・・失敗です。
WROOMシリーズには、「ESP-WROOM-02」と「ESP-WROOM-32」があるのですが。
HUB75のような高速I/Fを担保するには、末尾32が必要っぽいです。
秋月だと、このへんです。
https://akizukidenshi.com/catalog/g/gM-11819/
今回はAmazonでてきとーなの入手して使いました。
ま、詳細は、以下サイトなどを参考にしました、とさ。
https://qiita.com/Yukiya_Ishioka/items/c455f7bfbcb240bb2ba7
一応I/Fは5Vなので、バスバッファ使って5V昇圧しています。
「TC74LCXR163245」を使って、、、双方向バスバッファですが、まあ単方向で使ってますよと。
https://akizukidenshi.com/catalog/g/gM-08250/
電源は5V4AのACアダプタで、ちゃんとジャック側も高電流対応型を、ね。
https://akizukidenshi.com/catalog/g/gK-06998/
下準備
まあまず、「デカい文字フォント」を作ります。
これはむかぁし作った変換プログラムで、BMPからサクっと。
配線
まあ特に言うことはありません。
ワイヤリングは、上記qiitaを参照しつつ、パパっと作りましたとさ。
強いて言えば、バッファのEN配線忘れてて不安定だったことくらいです!。
ソフトウェア
Arduinoでサクっと。
だいたい半日に1回くらい、時計合わせにいきますって感じで。
ntpclocl.ino
#include <WiFi.h>
#include <Adafruit_GFX.h> // Core graphics library
#include <P3RGB64x32MatrixPanel.h>
#define WIFI_SSID "wifi_no_SSID"
#define WIFI_PASSWORD "wifi_no_PASSWORD"
#define JST 3600*9
// constructor with default pin wiring
P3RGB64x32MatrixPanel matrix;
long ntpcounter = 0;
time_t tprev = 0;
char mprev;
const uint8_t moji_9[] PROGMEM = {
0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xe0,
0x0f,0xf8,0x1f,0xfc,0x1f,0xfc,0x3e,0x3e,
0x3c,0x1e,0x3c,0x1e,0x3c,0x1e,0x3c,0x1e,
0x3c,0x1e,0x3c,0x1e,0x3c,0x1e,0x3c,0x1e,
0x3e,0x3e,0x3f,0xfe,0x1f,0xfe,0x1f,0xde,
0x07,0x1e,0x00,0x1e,0x00,0x1e,0x3c,0x1e,
0x3c,0x1e,0x3e,0x3e,0x1f,0xfc,0x1f,0xfc,
0x0f,0xf8,0x03,0xe0,0x00,0x00,0x00,0x00,
0x00,0x00,
};
const uint8_t moji_8[] PROGMEM = {
0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xe0,
0x0f,0xf8,0x1f,0xfc,0x1f,0xfc,0x3e,0x3e,
0x3c,0x1e,0x3c,0x1e,0x3c,0x1e,0x3c,0x1e,
0x3c,0x1e,0x1e,0x3c,0x1f,0xfc,0x0f,0xf8,
0x0f,0xf8,0x1f,0xfc,0x1e,0x3c,0x3c,0x1e,
0x3c,0x1e,0x3c,0x1e,0x3c,0x1e,0x3c,0x1e,
0x3c,0x1e,0x3e,0x3e,0x1f,0xfc,0x1f,0xfc,
0x0f,0xf8,0x03,0xe0,0x00,0x00,0x00,0x00,
0x00,0x00,
};
const uint8_t moji_7[] PROGMEM = {
0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0xfe,
0x3f,0xfe,0x3f,0xfe,0x3f,0xfe,0x00,0x3e,
0x00,0x3c,0x00,0x3c,0x00,0x3c,0x00,0x7c,
0x00,0x78,0x00,0x78,0x00,0x78,0x00,0xf0,
0x00,0xf0,0x00,0xf0,0x01,0xf0,0x01,0xe0,
0x01,0xe0,0x01,0xe0,0x03,0xe0,0x03,0xc0,
0x03,0xc0,0x03,0xc0,0x07,0xc0,0x07,0x80,
0x07,0x80,0x0f,0x80,0x00,0x00,0x00,0x00,
0x00,0x00,
};
const uint8_t moji_6[] PROGMEM = {
0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xe0,
0x0f,0xf8,0x1f,0xfc,0x1f,0xfc,0x3e,0x3e,
0x3c,0x1e,0x3c,0x1e,0x3c,0x00,0x3c,0x00,
0x3c,0x00,0x3c,0x70,0x3d,0xfc,0x3f,0xfc,
0x3f,0xfe,0x3e,0x3e,0x3c,0x1e,0x3c,0x1e,
0x3c,0x1e,0x3c,0x1e,0x3c,0x1e,0x3c,0x1e,
0x3c,0x1e,0x3e,0x3e,0x1f,0xfc,0x1f,0xfc,
0x0f,0xf8,0x03,0xe0,0x00,0x00,0x00,0x00,
0x00,0x00,
};
const uint8_t moji_5[] PROGMEM = {
0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0xf8,
0x3f,0xf8,0x3f,0xf8,0x3f,0xf8,0x3c,0x00,
0x3c,0x00,0x3c,0x00,0x3c,0x00,0x3c,0x00,
0x3c,0xe0,0x3f,0xf8,0x3f,0xf8,0x3f,0xfc,
0x3c,0x7c,0x3c,0x3c,0x3c,0x3c,0x00,0x3c,
0x00,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,0x3c,
0x3c,0x3c,0x3c,0x7c,0x3f,0xf8,0x1f,0xf8,
0x0f,0xf0,0x07,0xc0,0x00,0x00,0x00,0x00,
0x00,0x00,
};
const uint8_t moji_4[] PROGMEM = {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,
0x00,0xf8,0x00,0xf8,0x01,0xf8,0x01,0xf8,
0x03,0xf8,0x03,0xf8,0x03,0xf8,0x07,0xf8,
0x07,0xf8,0x0f,0x78,0x0f,0x78,0x1e,0x78,
0x1e,0x78,0x1c,0x78,0x3c,0x78,0x3c,0x78,
0x78,0x78,0x7f,0xfe,0x7f,0xfe,0x7f,0xfe,
0x7f,0xfe,0x00,0x78,0x00,0x78,0x00,0x78,
0x00,0x78,0x00,0x78,0x00,0x00,0x00,0x00,
0x00,0x00,
};
const uint8_t moji_3[] PROGMEM = {
0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xe0,
0x0f,0xf8,0x1f,0xfc,0x1f,0xfc,0x3e,0x3e,
0x3c,0x1e,0x3c,0x1e,0x3c,0x1e,0x00,0x1e,
0x00,0x1e,0x00,0x3c,0x03,0xfc,0x03,0xf8,
0x03,0xf8,0x03,0xfc,0x00,0x3c,0x00,0x1e,
0x00,0x1e,0x3c,0x1e,0x3c,0x1e,0x3c,0x1e,
0x3c,0x1e,0x3e,0x3e,0x1f,0xfc,0x1f,0xfc,
0x0f,0xf8,0x03,0xe0,0x00,0x00,0x00,0x00,
0x00,0x00,
};
const uint8_t moji_2[] PROGMEM = {
0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xe0,
0x0f,0xf8,0x1f,0xfc,0x1f,0xfc,0x3e,0x3e,
0x3c,0x1e,0x3c,0x1e,0x3c,0x1e,0x3c,0x1e,
0x00,0x1e,0x00,0x3c,0x00,0x3c,0x00,0x78,
0x00,0xf0,0x01,0xf0,0x03,0xe0,0x07,0xc0,
0x0f,0x80,0x0f,0x00,0x1e,0x00,0x1e,0x00,
0x3c,0x00,0x3c,0x00,0x3f,0xfe,0x3f,0xfe,
0x3f,0xfe,0x3f,0xfe,0x00,0x00,0x00,0x00,
0x00,0x00,
};
const uint8_t moji_1[] PROGMEM = {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,
0x00,0xe0,0x01,0xe0,0x03,0xe0,0x0f,0xe0,
0x0f,0xe0,0x0f,0xe0,0x01,0xe0,0x01,0xe0,
0x01,0xe0,0x01,0xe0,0x01,0xe0,0x01,0xe0,
0x01,0xe0,0x01,0xe0,0x01,0xe0,0x01,0xe0,
0x01,0xe0,0x01,0xe0,0x01,0xe0,0x01,0xe0,
0x01,0xe0,0x01,0xe0,0x01,0xe0,0x01,0xe0,
0x01,0xe0,0x01,0xe0,0x00,0x00,0x00,0x00,
0x00,0x00,
};
const uint8_t moji_0[] PROGMEM = {
0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xe0,
0x0f,0xf8,0x1f,0xfc,0x1f,0xfc,0x3e,0x3e,
0x3c,0x1e,0x3c,0x1e,0x3c,0x1e,0x3c,0x1e,
0x3c,0x1e,0x3c,0x1e,0x3c,0x1e,0x3c,0x1e,
0x3c,0x1e,0x3c,0x1e,0x3c,0x1e,0x3c,0x1e,
0x3c,0x1e,0x3c,0x1e,0x3c,0x1e,0x3c,0x1e,
0x3c,0x1e,0x3e,0x3e,0x1f,0xfc,0x1f,0xfc,
0x0f,0xf8,0x03,0xe0,0x00,0x00,0x00,0x00,
0x00,0x00,
};
void setup() {
Serial.begin(9600);
tuneNtp();
}
void setLEDChibimoji(char datachar,char datachar2){
matrix.setTextSize(1);
matrix.setCursor(50, 24);
matrix.setTextColor(matrix.color444(0, 15 ,0));
matrix.print(datachar);
matrix.print(datachar2);
}
void setLEDChibimoji2(char datachar,char datachar2,char datachar3,char datachar4,char datachar5,char datachar6,char datachar7,char datachar8){
matrix.setTextSize(1);
matrix.setCursor(0, 0);
matrix.setTextColor(matrix.color444(15, 0, 0));
// matrix.print(datachar);
// matrix.print(datachar2);
// matrix.print(datachar3);
// matrix.print(datachar4);
matrix.print(datachar5);
matrix.print(datachar6);
matrix.print(datachar7);
matrix.print(datachar8);
}
void setLEDDekamoji(int keta,char datachar){
int data;
data = (int) datachar;
data = data - 48;
keta = keta * 16;
if (data == 0){
matrix.drawBitmap(keta, 0, (uint8_t*)moji_0, 16, 32, 0xFFF0,0x0000);
}
if (data == 1){
matrix.drawBitmap(keta, 0, (uint8_t*)moji_1, 16, 32, 0xFFF0,0x0000);
}
if (data == 2){
matrix.drawBitmap(keta, 0, (uint8_t*)moji_2, 16, 32, 0xFFF0,0x0000);
}
if (data == 3){
matrix.drawBitmap(keta, 0, (uint8_t*)moji_3, 16, 32, 0xFFF0,0x0000);
}
if (data == 4){
matrix.drawBitmap(keta, 0, (uint8_t*)moji_4, 16, 32, 0xFFF0,0x0000);
}
if (data == 5){
matrix.drawBitmap(keta, 0, (uint8_t*)moji_5, 16, 32, 0xFFF0,0x0000);
}
if (data == 6){
matrix.drawBitmap(keta, 0, (uint8_t*)moji_6, 16, 32, 0xFFF0,0x0000);
}
if (data == 7){
matrix.drawBitmap(keta, 0, (uint8_t*)moji_7, 16, 32, 0xFFF0,0x0000);
}
if (data == 8){
matrix.drawBitmap(keta, 0, (uint8_t*)moji_8, 16, 32, 0xFFF0,0x0000);
}
if (data == 9){
matrix.drawBitmap(keta, 0, (uint8_t*)moji_9, 16, 32, 0xFFF0,0x0000);
}
}
void tuneNtp() {
// wifi_set_sleep_type(NONE_SLEEP_T);
matrix.stop();
delay(1000);
Serial.printf("set wifi");
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
for(int i=0; i<30; i=i+1) {
if (WiFi.status() == WL_CONNECTED) {
break;
}
delay(500);
}
configTzTime("JST-9", "ntp.nict.jp", "ntp.jst.mfeed.ad.jp");
delay(500);
WiFi.disconnect();
delay(1000);
matrix.begin();
// wifi_set_sleep_type(LIGHT_SLEEP_T);
}
void loop() {
time_t t;
struct tm *tm;
static const char *wd[7] = {"Sun","Mon","Tue","Wed","Thr","Fri","Sat"};
char datebuffer[16];
t = time(NULL);
if (t == tprev){
delay(20);
return;
}
tm = localtime(&t);
Serial.printf("%04d/%02d/%02d(%s) %02d:%02d:%02d\n",
tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday,
wd[tm->tm_wday],
tm->tm_hour, tm->tm_min, tm->tm_sec);
sprintf(datebuffer, "%04d%02d%02d%02d%02d%02d", tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec);
if (datebuffer[11] != mprev) {
// matrix.fillScreen(matrix.color444(0, 0, 0));
int mdata;
mdata = (int) datebuffer[8];
if (mdata != 0){
setLEDDekamoji(0,datebuffer[8]);
}
setLEDDekamoji(1,datebuffer[9]);
setLEDDekamoji(2,datebuffer[10]);
setLEDDekamoji(3,datebuffer[11]);
setLEDChibimoji2(datebuffer[0],datebuffer[1],datebuffer[2],datebuffer[3],datebuffer[4],datebuffer[5],datebuffer[6],datebuffer[7]);
setLEDChibimoji(datebuffer[12],datebuffer[13]);
}
else {
setLEDDekamoji(3,datebuffer[11]);
setLEDChibimoji(datebuffer[12],datebuffer[13]);
}
ntpcounter++;
if (ntpcounter > 40000){
tuneNtp();
ntpcounter = 0;
}
tprev = t;
mprev = datebuffer[11];
}
できました!
遠くからでもクッキリで。
いやあ便利!。
それにしてもまあ、RTCとか何もつけてないのに、勝手に時刻が合うのがちょっとだいぶヘン!。
まあ、NTP時計は、市販もされていますが、結構お高いので。
自作したら、1万以内に納まっちゃうので、結構かなりオススメです!。
以上です。
投稿者の人気記事
-
eucaly
さんが
2021/02/17
に
編集
をしました。
(メッセージ: 初版)
ログインしてコメントを投稿する