NTP時計の製作
ESP32-WROOM-32を搭載したLOLIN32ボードを使って、時計を作ります。表示はコントローラTM1637が搭載された4桁の赤色7セグメントLEDです。こちらの記事でも利用しました。LOLIN32ボードは、ebayで入手しました。現在、600円前後です。ESP32のマイコン・ボードのI/Oはみんなが同じではありません。
開発は、Arduino IDE1.8.10を利用しました。
●接続
前記の記事と同じに配線したところ、書き込みに失敗しました。2番を隣の15番に変更しました。
| TM1637 | LOLIN32 |
|---|---|
| CLK | 2 -> 15 |
| DIO | 3 |
| Vcc | 3V3 |
| GND | GND |
TM1637のライブラリは、前出の記事と同じくTM1637 by Avishay Orpaz ver1.2.0を利用しました。
サンプルのTM1637testの #define CLK 2 を15に変更して書き込み、表示を確認します。
●NTPで時刻を得る
マイコン・ボードLOLIN32は、Wi-Fiでインターネットに接続できます。NTPサーバから正確な時刻を読みます。LOLIN32用のサンプル、ESP32->timeからsimpletimeを読み込み、下記の2行を自分のWi-Fiアクセス・ポイントに変更して実行します。
| const char* ssid = "YOUR_SSID"; const char* password = "YOUR_PASS"; |
このスケッチをベースに、上記のTM1637の表示スケッチと合成します。tmという構造体に時刻や年月日の情報が入っています。時と分の情報は、その構造体の要素を抜き出します。
| getLocalTime(&timeinfo); Hour = timeinfo.tm_hour; Min = timeinfo.tm_min; |
4桁の表示データはdata[]配列に入れます。時と分は2桁の数値なので、それぞれ分離して、TM1637DisplayのライブラリにあるencodeDigit()関数を使って桁データに変換します。
2番目の桁はコロン(通常はドット)を表示したいので、最上位ビットを'1'にしています。
| data[0] = display.encodeDigit(Hour / 10); data[1] = display.encodeDigit(Hour % 10) | 0b10000000; data[2] = display.encodeDigit(Min / 10); data[3] = display.encodeDigit(Min % 10); |
スケッチです。
#include <WiFi.h>
#include "time.h"
#include <TM1637Display.h>
#define CLK 15
#define DIO 3
const char* ssid = "Buffalo-G-20EA";
const char* password = "********";
const char* ntpServer = "ntp.nict.jp";
const long gmtOffset_sec = 3600*9; // JST
const int daylightOffset_sec = 0;
TM1637Display display(CLK, DIO);
uint8_t data[] = { 0xff, 0xff, 0xff, 0xff }; // all '1'
struct tm timeinfo;
byte Hour = 0;
byte Min = 0;
void printLocalTime(){
if(!getLocalTime(&timeinfo)){
Serial.println("Failed to obtain time");
return;
}
Serial.println(&timeinfo, "%H:%M");
}
void setup(){
display.setBrightness(0x0f);
Serial.begin(115200);
//connect to WiFi
Serial.printf("Connecting to %s ", ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println(" CONNECTED");
//init and get the time
configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
printLocalTime();
//disconnect WiFi as it's no longer needed
WiFi.disconnect(true);
WiFi.mode(WIFI_OFF);
}
void loop(){
delay(1000);
getLocalTime(&timeinfo);
Hour = timeinfo.tm_hour;
Min = timeinfo.tm_min;
Serial.print(Hour);Serial.print(":");Serial.println(Min);
data[0] = display.encodeDigit(Hour / 10);
data[1] = display.encodeDigit(Hour % 10) | 0b10000000;
data[2] = display.encodeDigit(Min / 10);
data[3] = display.encodeDigit(Min % 10);
display.setSegments(data);
}
実行例です。
スタンドアロンで動作するように組み替えました。
(2020/01/03)時刻の先頭の文字が0を表示すると煩わしいので、下記の記述でゼロサプレスします。
data[0] = (Hour / 10) ? display.encodeDigit(Hour / 10) : 0x00; data[1] = display.encodeDigit(Hour % 10) | 0b10000000; data[2] = (Min / 10) ? display.encodeDigit(Min / 10) : 0x00; data[3] = display.encodeDigit(Min % 10);
(※) 二つのスケッチを合成したので、型の指定などが統一されていません。
(※) 本Webのプログラム中、インデントなどのスペースもしくは改行は、通常のプログラム内ではごみ文字になるので、コピペした後、エディタでスペース文字などを入れなおしてください。