かつて、秋月電子の「K-00798」(http://www.narimatsu.net/nari_page/led-matrix-module.html)という赤色の単色マトリックスLEDを使ってArduinoのデジタル時計を作った。そのマトリックスLEDはもう販売していないが、密度の高い32x16表示というのが気に入っていた。それを横に2枚並べて、数字を4つ表示するだけの時計だ。ただし、NTPサーバで時刻合わせをする。
当初は普通のArduinoUNO(+Ethernetシールド)だったが、小さく作りたくなり、WIFIが最初からついた Arduino YÚN mini に、そして最近YÚNがぶっ壊れたので、スイッチサイエンスで売っていたESP8266搭載の「ESPr® Developer」(https://www.switch-science.com/catalog/2652/)に。これが小さくて安くて高性能、とのこと。NTPでの時計合わせは h_nari さんの記事(https://qiita.com/h_nari/items/d0374d1e1e36b9d988c0)を参考にさせていただいた。大感謝。
これでハマった。これまでマトリックスLED表示には arms22 さん作成のAkiMatrix(https://github.com/arms22/arms22/tree/master/AkiMatrix)モジュールを使っていた(大感謝)が、AkiMatrixがArduinoIDEのコンパイルを通らない。ArduinoIDEは、1.6、1.8系統を試した(1.7はそもそもESP8266用のコンパイルが出来ない)。どうもESP8266は若干仕様が違うらしく、完全互換とはいかないようだ。
色々調べてみてもわからず、AkiMatrixを使うのは断念した。うろうろしていたら grassbigboy 氏の記事(http://grassbigboy.hatenablog.jp/entry/2019/01/07/223000)を見つけ、それを使わせていただき、無事完成。大感謝。
やはりこの単色LEDの感じはいい。フォントは自作で、同じ数字で微妙に違うものを交互に表示させてアンチエイリアス風味にしているというスグレモノ(自画自賛)。
イカソース
#include <ESP8266WiFi.h>
#include <time.h>
#define WIFI_SSID "自宅SSID"
#define WIFI_PASSWORD "パスワード"
#define JST 3600*9
int hourflg = 1;
int hourcheck;
int i=0;
int h=0;
int ha;
int dms=0;
int hr0=0;
int hr1=1;
int mn0=2;
int mn1=3;
int tog=1;
unsigned int sin1 = 0x0001;//縦
unsigned int sin2;//横1 hr0
unsigned int sin3;//横2 hr1
unsigned int sin4;//横3 mn0
unsigned int sin5;//横4 mn1
unsigned int sina;//横1+3
unsigned int sinb;//横2+4
unsigned int Adigi[2][10][16] =
//0_0,,,,,,,,,,,,,,,
{{{960,4080,3120,6168,4104,12300,12300,12300,12300,12300,12300,4104,6168,3120,4080,960},
//1_0,,,,,,,,,,,,,,,
{128,448,960,1984,3776,1216,192,192,192,192,192,192,192,192,192,192},
//2_0,,,,,,,,,,,,,,,
{960,4080,6168,14348,4108,12,24,56,112,224,448,896,1792,3584,8188,16380},
//3_0,,,,,,,,,,,,,,,
{960,4080,6168,14348,4108,24,56,224,224,56,24,4108,14348,6168,4080,960},
//4_0,,,,,,,,,,,,,,,
{304,304,816,560,1584,1072,3120,2096,6192,4144,16380,16380,48,48,48,48},
//5_0,,,,,,,,,,,,,,,
{2040,2040,1536,3072,3072,4032,8176,6168,24,12,12,4108,14360,7224,4080,960},
//6_0,,,,,,,,,,,,,,,
{32,112,224,448,896,1984,4080,7224,6168,12300,12300,12300,6168,7224,4080,960},
//7_0,,,,,,,,,,,,,,,
{4088,8188,12312,4120,16,48,32,96,64,192,128,384,256,768,512,1536},
//8_0,,,,,,,,,,,,,,,
{960,4080,6168,12300,12300,6168,7224,2016,2016,6168,4104,12300,12300,6168,4080,960},
//9_0,,,,,,,,,,,,,,,
{960,4080,7224,6168,12300,12300,12300,6168,7224,4080,992,448,896,1792,3584,1024}},
//0_1,,,,,,,,,,,,,,,
{{2016,4080,7800,6168,14364,12300,12300,12300,12300,12300,12300,14364,6168,7800,4080,2016},
//1_1,,,,,,,,,,,,,,,
{128,448,960,1984,3776,1216,192,192,192,192,192,192,192,192,192,192},
//2_1,,,,,,,,,,,,,,,
{2016,4088,7228,14364,4124,28,28,56,112,224,448,896,1792,3584,8188,16380},
//3_1,,,,,,,,,,,,,,,
{2016,4088,7228,14364,4124,28,56,240,240,56,28,4124,14364,7228,4088,2016},
//4_1,,,,,,,,,,,,,,,
{432,944,816,1840,1584,3632,3120,7216,6192,14384,16380,16380,48,48,48,48},
//5_1,,,,,,,,,,,,,,,
{2040,2040,3584,3584,3072,8160,8184,7224,28,12,12,4108,14364,7800,4080,2016},
//6_1,,,,,,,,,,,,,,,
{32,112,224,448,896,2016,4080,7800,14364,14364,12300,14364,14364,7800,4080,2016},
//7_1,,,,,,,,,,,,,,,
{8188,16380,14364,4120,56,48,112,96,224,192,448,384,896,768,1792,1536},
//8_1,,,,,,,,,,,,,,,
{2016,8184,15420,14364,14364,14364,7800,4080,4080,7224,14364,14364,14364,15420,8184,2016},
//9_1,,,,,,,,,,,,,,,
{2016,4080,7800,14364,14364,12300,14364,14364,7800,4080,2016,448,896,1792,3584,1024}}};
unsigned int Ndigi[2][10][16] = {0};
void setup() {
//ピンをOutputモードに切り替え
pinMode(2, OUTPUT);//strobe
pinMode(12, OUTPUT);//sin1
pinMode(13, OUTPUT);//sin2
pinMode(14, OUTPUT);//sin3
pinMode(15, OUTPUT);//latch
pinMode(16, OUTPUT);//clock
timeset();
}
void bitchecker(unsigned int sin0,int portnum){
sin0 &=0x00000001;
if(sin0==1){
digitalWrite(portnum,HIGH);
}else{
digitalWrite(portnum,LOW);
}
}
// the loop function runs over and over again forever
void loop() {
//esp
time_t t;
struct tm *tm;
t = time(NULL);
tm = localtime(&t);
hourcheck = tm->tm_hour * hourflg;
if ( hourcheck == -4 ) hourflg = 1;
if ( hourcheck == 3 ) timeset();
int hr0 = tm->tm_hour / 10L;
int hr1 = tm->tm_hour % 10;
int mn0 = tm->tm_min / 10L;
int mn1 = tm->tm_min % 10;
for(h=0;h<32;++h){
ha=h%16;
if (hr0!=0){sin2=Adigi[tog][hr0][ha];}
else{sin2=Ndigi[0][0][0];}
sin4=Adigi[tog][mn0][ha];
sin3=Adigi[tog][hr1][ha];
sin5=Adigi[tog][mn1][ha];
sina=(sin2*65536)+sin4;
sinb=(sin3*65536)+sin5;
unsigned int tmp_sin1=sin1;
unsigned int tmp_sina=sina;
unsigned int tmp_sinb=sinb;
digitalWrite(15,HIGH);//LatchをHIGH
for(i=0;i<32;++i){ //sin32bit書き込み
digitalWrite(16,LOW); //clock
delayMicroseconds(dms);
bitchecker(tmp_sin1,12);
bitchecker(tmp_sina,13);
bitchecker(tmp_sinb,14);
digitalWrite(16,HIGH);//clock
delayMicroseconds(dms);
tmp_sin1 = tmp_sin1 >>1;
tmp_sina = tmp_sina >>1;
tmp_sinb = tmp_sinb >>1;
}
digitalWrite(15,LOW); //Latch low 書き込み
delayMicroseconds((1-tog)*300);
sin1 = sin1 <<1;
}
sin1 = 0x0001;
tog=1-tog;
}
void timeset()
{
Serial.begin(115200);
delay(100);
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
while(WiFi.status() != WL_CONNECTED) {
delay(500);
}
configTime( JST, 0, "ntp.nict.jp", "ntp.jst.mfeed.ad.jp");
hourflg = -1;
}
