前回から引き続き7セグLEDを利用したNTP同期型時計の作成。
先日の「超大型4桁LED表示キット」は秋月電子通商が販売している「超大型表示マイコンデジタル時計キットVer.4」の表示部分だけの基板なのだが、これを入手した当時はVer.4は販売されておらず、Ver.3が販売されていた。
で、Ver.3と超大型~表示キットを購入した結果、ver.3に元々付いていた表示部分の基板と7セグLEDが丸ごと使わずに残った。
このまま使わずに放置するのも勿体ないし、ICやマイコンも余分に買って余っているので、前回と同じような物の小型版を作る事にした。
このぐらいの大きさになるとケースは分割しなくても印刷可能で、表面のアクリル板も小さくて済む。端材を使ったので微妙に大きさが足りないが、自分で使う分には困らないだろう。
WeMOS D1 Mini互換ボードの取付部分は前回のケースで作ったから、少し微調整してほぼそのまま。縦横サイズはなるべく小さくしようと思ったので、今回ボタンは表示面に実装する。
適当な高さのタクトスイッチを表示基板の上に接着してタクトスイッチ用のスナップカバーを使って、表示面のアクリルからボタンが1~2mm程度飛び出すような感じにする。ボタンの接着位置は適当なので、アクリル板の穴位置は現物合わせで。穴径はスナップカバーがスムーズに動くギリギリのサイズを狙ってドリル径を0.1mmずつ太くして調整。
タクトスイッチとスナップカバーはAliexpressで購入。この手の部品はamazonで購入しても結局中国から送ってくる事が多いから、amazonで購入する意味は殆ど無い。
因みにピン配列は「超大型4桁LED表示キット」と微妙に異なっていたので、DPと月日表示用のLEDの取り扱い部分を入れ替えたり、TM1637と基板のピンヘッダとの接続を少し変えたりしたけれど、基本的には殆ど前回と同じ。
まだマイコンとTM1637は余っているので、次は月差が1分ぐらい発生してしまう安物LED時計を改造してみようかな。
つい最近まで数万円で購入できる半導体レーザーで彫刻なんて出力が小さくて時間がかかるから面倒くさいと思っていたのだが、いつの間にか3.5万円も出せばレーザー出力10Wの彫刻機が手に入るようになっていた。(ブラックフライデー価格だったようで、今は5万円弱ぐらいするみたい)
今回購入したのは「ATOMSTACK P9 M50」という製品でXYのプロッター部分は1アーム式のお手軽な感じの物。
5Wレーザーを2本タンデムして10Wを稼ぎ出しているのだが、10万円出せば4本タンデムして20W出力の製品や、20万円出せば6本タンデムの30W出力の製品もある。
レーザーを束ねて出力を上げるには、プリズムやレンズ、レーザー発信機の取付、その他諸々の精度が重要になると思うのだけれど、なるほどホビーユース程度の精度ならこの金額で販売できるのか…
この手の製品は3Dプリンター同様、日本のamazonでも売られているので、色々な中華ECサイトと値段を比べなら、購入すれば良いと思う。メーカーや工場が中国や台湾なので、はっきり言って価格メリットが無ければ日本のECサイトで買うメリットは無い。amazonのマケプレ出品の商品を買ったところで、不具合があってもamazonが保証してくれる訳でも無く、出品者と交渉する必要があるなら、Aliexpressと何ら変わらない。
とりあえず、Inkscapeで画像を作ってLaserGRBLでレーザー彫刻機用のデータを作成。 1mm厚のアクリル板を四角く切り出すだけなら、LaserGRBLでも特に問題無く加工できた。
ATOMSTACKのM50を使って2.8mm厚のアクリルを切る際の設定はLaserGRBLの「Laser & Material Database」によると、100%出力、移動速度180mm/minで1パスらしいので、1mm厚なら200mm/minぐらいにすれば良いかと思ったのだが、余裕でカットできてしまったので、もう少し速度を上げても大丈夫かもしれない。
因みにLaserGRBLはラスターデータメインのソフトなので、カットの順番をセットできないから、本格的にレーザーカットを始めるならLightBurnを買った方が良いかな。
今のところは四角や丸に切るか、画像取り込みの彫刻しかしていないので、LaserGRBLでも問題ない。
問題があるとすれば、対象物をレーザーで焼くので、当たり前の事ながら煙と臭いが凄く出るから、屋内ではまともに作業する事ができない点だろう。特に火災報知器が設置されている場所では煙感知式だと間違いなく発報してしまうだろうし、樹脂や木材が焦げた臭いは、思いのほか長く室内に滞留するので、家族から忌み嫌われる事は確実だ。
住宅街やマンションのベランダでの作業でも臭いが隣近所に流れるので、何事かと思われるだろうし、レーザーカットそのものよりも作業環境づくりの方が大変かもしれない。
尚、今回カットしたアクリル板は、先日作成した7セグLED時計の表示パネルカバーとして使用。
鋸やカッターよりも精度が出ていて、切断面もかなり綺麗に切れたので、グレアのまま使ってみたのだけれど、やっぱり色々と反射して見え辛いかなぁ。見た目は綺麗なんだけど…
超大型と書かれているが、先日作成した4インチ7セグLEDよりは小さい。
2.2インチの16セグLEDを7セグLEDとして利用する為の基板で、別売のマイコンデジタル時計キットと合わせて利用する前提の基板として販売されている。
2.2インチのアノードコモン16セグLEDは随分前にデジットで投げ売りされていた物を購入していて、長らく放置状態だった。
元々時計として使うつもり購入していたので、この秋月の基板もほぼ同時期に購入していたのだが、買って満足してしまって同様に放置状態。
放置される原因は概ね基板むき出しで使うのが嫌で、ケースを用意するのが面倒くさいからなのだけれど、ここ数年で3Dプリンターの利用環境が随分と良くなった事で積んだままの電子工作が捗るようになった。
今回はこの4桁LED表示キットを利用して、日付表示ユニットを作成する。まぁ、折角なのでボタンを押せば時計が表示できるようにはしておきたい。
基板の回路図は秋月の公式ページに書かれているので、そちらを参照すれば良い。
マイコンに関してはWeMOS D1 Miniの互換ボードを使用。
Arduino IDE上でのボード選択は「LOLIN(WEMOS)D1 R2 & mini」で問題無く動作した。USBのコネクターがType-Cになっているので、microUSBよりは抜挿への耐久性は期待できるかもしれない。
このボードはESP8266(ESP-12F)が使われているのでWiFiが利用できる。技適は通過しているのかどうかは分からないが、技適マークは無い。
既に無許可の海外製品だらけで汚れまくっている2.4GHz帯ではあるが、日本の法律では特定の条件を除いてFCCやCEやWi-Fi CERTIFIEDに通っていたところで、周囲に電波を出してはいけない事になっているから、電波を出す際にはその辺りを留意する事。
まぁ理屈だけで考えればアクセスポイントと繋いで使うのであれば、その周波数の波しか出ない訳で、技適に通っているAPを使って繋ぐ分には、何ら迷惑がかかる事は無いと思う。実際に計測したわけじゃないから想像でしかないけど。 たぶんUSB3.0の放射ノイズの方が酷い。
話が逸れた。今回の時計兼日付表示器の仕様としては、ESP8266を使ってNTPサーバーにアクセスして時刻を補正。 基本的に無線LANが繋がらない場所に持って行く予定は無いのでRTCは無し。 電源投入時とその後適当な間隔でNTPで時刻補正をかける事で対応する。
7セグLEDの制御はEPS8266で直接ドライブするにはピン数や電流量が足りないので、何故か10個程ストックしていたDIP仕様のTM1637というドライバーICを利用する。データシートはこちら。
TM1637のDIP仕様はもう秋月では売っていなくて、amazonやaliexpressあたりで怪しげなのを買うしかない。国内流通在庫は探せばあるのかもしれないが面倒くさいので、素直にSOP仕様を購入するか、4桁までしか使わないなら、TM1630のDIP仕様を買った方が良いかもしれない。
ドライバーICを使うと抵抗とか考えなくても良くなるのが地味に有難い。
例によってラッピングワイヤーで繋ぐので、ピン配列だけ回路図で追いかけて、一覧表にまとめる。
LED_信号 | TM1637 | 基板(K-04380) | D1 mini |
A | 2 | 17 | |
B | 3 | 18 | |
C | 4 | 12 | |
D,月日LED-K | 5 | 14 | |
E | 6 | 13 | |
F | 7 | 16 | |
G | 8 | 15 | |
LED1,LED2-K | 9 | 19 | |
DP | 3 | ||
DIG5(月日LED-A) | 11 | 8 | |
DIG4,LED1-A | 12 | 5,20 | |
DIG3 | 13 | 1 | |
DIG2 | 14 | 2 | |
DIG1 | 15 | 4 | |
GND | 1 | GND | |
VDD | 16 | 5V | |
DIO | 17 | D1 | |
CLK | 18 | D2 | |
切替ボタン | D5 |
ドライバーICとマイコン間の接続は4芯だけなので楽だけど、ドライバーICと表示基板の間は結構接続ピン数が多い。
この秋月の基板で一か所に纏めてくれてるだけでも随分と有難いのだけれど…5台以上作るなら基板を作った方が良いかもしれない。
マイコンへのコーディングはいつも通りネット上に公開されているコードや既成ライブラリのサンプルコードのコピペ&改変。
esp8266のNTPを利用しての時間設定については、こちらのコードを拝借した。
先のページの解説によると、1時間に1回NTPサーバーに時刻を問い合わせているらしい。
今回利用したライブラリは「Seeed-Studio/Grove_4Digital_Display」と、前回に引き続き「ButtonEvents」。
Grove_4Digital_Displayについては、リンク先の説明を読めばわかるとおり、TM1637を利用した4桁7セグの時計ユニットを対象としたライブラリで、当然の事ながらそれが使いやすいような形になっているのだが、ライブラリ内の設定ファイル「TM1637.h」の最後の方に「const int DIGITS = 」という項目があって、利用桁数を変更できるようになっている。
今回はClockPoint(時計モードの際に0.5秒毎に点滅するアレ)とは別に月日表示の際にLEDを点灯させたいので、5桁目の適当なセグメントを利用する事にした。
このライブラリに付属しているClockDisplay.inoというサンプルプログラムの一部を利用してTM1637を制御する。
ClockPointの制御に関しては、DPセグメントをON/OFFしているので、秋月基板上のDPには接続せず、基板上のClockPoint(LED1,2)に接続する。
秋月基板のDPはLED4/LED6(時・分のそれぞれ一桁目)にしか接続されていないので月日表示の目印として使うには丁度良かったのだけれど、日付や時間を表示している際には、いずれのLEDも常時電圧が印加されているので、TM1637以外でGNDに落とす必要があって面倒くさかったので、別に2つLEDを用意して5桁目のアノードとDセグメントに接続した。
Dセグメントは7セグの下の横棒の事なので、5桁目を「1」や「8」に切り替えて点灯、消灯を制御している。
詳しい制御はコードを読んだ方が早いかもしれない。
#include Arduino.h
#include ESP8266WiFi.h
#include time.h
#include TM1637.h
#include ButtonEvents.h
#define WIFI_SSID "hoge_ID"
#define WIFI_PASSWORD "hoge_Pass"
#define JST 3600*9
#define ON 1
#define OFF 0
#define WAT 500 //ウェイト時間(ms)
// Define Digital Pins
#define CLK 4
#define DIO 5
TM1637 tm1637(CLK, DIO);
int8_t TimeDisp[] = {0x00, 0x00, 0x00, 0x00, 0x00};
unsigned char ClockPoint = 1;
const int mdled_pin = 12; //月日LED
const int button_pin = 14; //表示切替ボタン
unsigned char DispMode = 0;
unsigned long wattime;
ButtonEvents change_button;
void setup() {
Serial.begin(115200);
delay(100);
Serial.print("\n\nReset:\n");
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
while(WiFi.status() != WL_CONNECTED) {
Serial.print('.');
delay(500);
}
Serial.println();
Serial.printf("Connected, IP address: ");
Serial.println(WiFi.localIP());
configTzTime("JST-9", "ntp.nict.jp", "ntp.jst.mfeed.ad.jp"); // 2.7.0以降, esp32コンパチ
tm1637.init();
tm1637.set(BRIGHTEST);//BRIGHT_TYPICAL = 2,BRIGHT_DARKEST = 0,BRIGHTEST = 7;
tm1637.clearDisplay();
pinMode(mdled_pin, OUTPUT);
pinMode(button_pin, INPUT_PULLUP);
change_button.attach(button_pin);
change_button.doubleTapTime(200);
change_button.holdTime(5000);
wattime = millis();
}
void loop() {
while((millis() - wattime)
change_button.update();
if(change_button.tapped() == true) {
DMode();
}
}
if(DispMode) {
TimeUpdate();
} else {
DateUpdate();
}
tm1637.display(TimeDisp);
wattime = millis();
//time_t t;
//struct tm *tm;
//static const char *wd[7] = {"Sun","Mon","Tue","Wed","Thr","Fri","Sat"};
//t = time(NULL);
//tm = localtime(&t);
/*Serial.printf("ESP8266/Arduino ver%s : %04d/%02d/%02d(%s) %02d:%02d:%02d\n",
__STR(ARDUINO_ESP8266_GIT_DESC),
tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday,
wd[tm->tm_wday],
tm->tm_hour, tm->tm_min, tm->tm_sec);
delay(1000); */
}
void TimeUpdate() {
digitalWrite(mdled_pin, LOW);
time_t t;
struct tm *tm;
t = time(NULL);
tm = localtime(&t);
ClockPoint = (~ClockPoint) & 0x01;
if (ClockPoint) {
tm1637.point(POINT_ON);
} else {
tm1637.point(POINT_OFF);
}
TimeDisp[0] = ((tm->tm_hour) / 10);
TimeDisp[1] = ((tm->tm_hour) % 10);
TimeDisp[2] = ((tm->tm_min) / 10);
TimeDisp[3] = ((tm->tm_min) % 10);
TimeDisp[4] = 1;
}
void DateUpdate() {
digitalWrite(mdled_pin, HIGH);
time_t t;
struct tm *tm;
t = time(NULL);
tm = localtime(&t);
tm1637.point(POINT_OFF);
TimeDisp[0] = ((tm->tm_mon+1) / 10);
TimeDisp[1] = ((tm->tm_mon+1) % 10);
TimeDisp[2] = ((tm->tm_mday) / 10);
TimeDisp[3] = ((tm->tm_mday) % 10);
TimeDisp[4] = 8;
}
void DMode() {
DispMode = (~DispMode) & 0x01;
}
各基板を収めるケースは手持ちの3Dプリンターでは一体形成品が印刷できなかったので、前回同様分割して印刷した。
今回は手抜きせずにマイコンボードを収める場所を作ったり、Type-Cのコネクターを繋いでメンテナンスができるように穴をあけたりしている。
なるべく高さを抑えたかったので、コンタクトピンを付けるにしても、高さを考えてカットする必要がある。
基板を作って直接実装してしまえば、あと3mmは追い込めるし、スッキリするから良いとは思うけれど、そこまでの完成度は求めていないからこの辺りが妥当なところだろう。
で、配線した基板とドライバーIC、ボタンスイッチをケースに入れて、グルーガンで固定。LEDが載ってる基板は更に4隅をネジ止めしておく。
あとはコレに適当な暗さのアクリル板を貼ってやれば、そこそこ見やすい時計&日付表示器になる。
因みに電源はType-CのコネクターからD1 mini互換ボードを経由し、D1 miniの5V出力をTM1637のVDDに接続している。 電流が足りるか分からなかったのだけれど、1週間以上動作させて問題無く動いているので、たぶん大丈夫なのだろう。
また、RTCを実装していないので、電源投入時に無線LANをつかみ損ねると暫く時計が初期化された状態で表示されるから、時刻補正されるまでは少し不安になるが、極力シンプルかつ安価に作りたかったので、我慢する事にしよう。