NodeMCU1.0 or ESP32 Dev Module を使って 8x8 dotmatrix LEDでデジタル時計をつくる


朝からず~と取り組んで、やっとこさ完成! ハードウェアはここにあるように、CPU1個とLEDデジタル表示器1個を5本のケーブルで繋ぐだけだけどね・・・。 電源はUSB(5V)で動いている。 肝心なのはソフト! 1週間ほど前に似たようなものを、習作で制作したのですが、表示フォントと表示の方法が気に入らなくて、何とか自分のアイデアで纏めたいと思い、今日は表示フォントも作った! ちょっと太目のフォントなので離れていても見やすい! ソフトが動いて、時間が表示できるようになるまで手古摺った~! 時間はWiFiから入力し処理している。
Sketchには、いろいろ試しながら構築したので、不要な所も多々あると思うが、ご覧になる方にはご容赦願いたい。
中央付近に、時間と分表示の区切り「:」を入れると、時間部分の表示と分の表示部分に同じものを使うと、アンバランスな表示になってしまうので、時の表示と分の表示でフォントのデザインを変更した。
《その後、当日ですが・・・》
手元にあった ESP32-WROOM-32 (Espressif) 「技適済」で動作確認したので、Sketchも修正しておく
使用部品
又は ESP32 Dev Module (ESPRESSIF ESP32-WROOM-32) Amazonで2個2000円くらいです。
・8x8ドットマトリックスLED(MAX7219 ドット LED マトリックス MCU 制御 LED) Amazonで@1200円くらいです。
・5本ジャンパーケーブル
・ブレッドボード(スイッチサイエンス製を使った)
Sketch
// NodeMCU 1.0(ESP12-E Module) / ESP32 Dev Module / ESP32 Wrover Module
// Vcc to Vin .................. Vin or 5V or 3V3
// GND to GND
// Din to D7 .................... D27
// CS to D6 .................... D26
// CLK to D5 .................... D25
#ifdef ESP32
#include <WiFi.h>
#else
#include <ESP8266WiFi.h>
#endif
#include <LedControl.h>
#include <NTPClient.h>
#include <WiFiUdp.h>
const char* ssid = "your SSID";
const char* password = "your Password";
const long utcOffsetInSeconds = 9*3600;
char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
// Define NTP Client to get time
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "pool.ntp.org", utcOffsetInSeconds);
int month,dayOfMonth,dayOfWeek,hour,minute,s;
int i=0;
int x=0;
int bstflag= 0;
int twelve = 0; //variable for 12 hour hour counter
// Convert normal decimal numbers to binary coded decimal
byte decToBcd(byte val)
{
return( (val/10*16) + (val%10) );
}
// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val)
{
return( (val/16*10) + (val%16) );
}
// set up display - data, clock, cs, numdevices
LedControl lc = LedControl(D7,D5,D6,4); //pins for Din, CLK, CS
//matrix table for display
//first element on each row is the bottom row of the display, then rising up through the display
const int numh[10][8] = {
// ここに用意したフォントは、左側2文字、"Hour"表示用
{0x00,0x1e,0x33,0x33,0x33,0x33,0x33,0x1e}, // zero
{0x00,0x3f,0x0c,0x0c,0x0c,0x0c,0x0f,0x0c}, // one
{0x00,0x3f,0x06,0x0c,0x18,0x30,0x33,0x1e}, // two
{0x00,0x1e,0x31,0x30,0x1e,0x30,0x31,0x1e}, // three
{0x00,0x30,0x30,0x7f,0x33,0x32,0x34,0x38}, // four
{0x00,0x1e,0x31,0x30,0x30,0x1f,0x03,0x3f}, // five
{0x00,0x1e,0x33,0x33,0x1f,0x03,0x23,0x1e}, // six
{0x00,0x06,0x06,0x0c,0x18,0x30,0x33,0x3f}, // seven
{0x00,0x1e,0x33,0x33,0x1e,0x33,0x33,0x1e}, // eight
{0x00,0x1e,0x33,0x30,0x3e,0x33,0x33,0x1e} // nine
};
const int numm[10][8] = {
// ここに用意したフォントは、右側2文字、"Minute"表示用
{0x00,0x78,0xcc,0xcc,0xcc,0xcc,0xcc,0x78}, // zero
{0x00,0xfc,0x30,0x30,0x30,0x30,0x3c,0x30}, // one
{0x00,0xfc,0x18,0x30,0x60,0xc0,0xcc,0x78}, // two
{0x00,0x78,0xc4,0xc0,0x78,0xc0,0xc4,0x78}, // three
{0x00,0x60,0x60,0xfe,0x66,0x64,0x68,0x70}, // four
{0x00,0x78,0xc4,0xc0,0xc0,0x7c,0x0c,0xfc}, // five
{0x00,0x78,0xcc,0xcc,0x7c,0x0c,0x8c,0x78}, // six
{0x00,0x18,0x18,0x30,0x60,0xc0,0xc4,0xfc}, // seven
{0x00,0x78,0xcc,0xcc,0x78,0xcc,0xcc,0x78}, // eight
{0x00,0x78,0xcc,0xc0,0xf8,0xcc,0xcc,0x78} // nine
};
void drawhNum(int number, int display_div)
{ // drawNum は、数値"number"を、デバイス"display_div"に表示させる
lc.setRow(display_div, 7, numh[number][7]); // デバイス display_div の 1行分(x,y)を纏めて表示設定
lc.setRow(display_div, 6, numh[number][6]); // 変数名num [数値] [行目] 表示を示している
lc.setRow(display_div, 5, numh[number][5]);
lc.setRow(display_div, 4, numh[number][4]);
lc.setRow(display_div, 3, numh[number][3]);
lc.setRow(display_div, 2, numh[number][2]);
lc.setRow(display_div, 1, numh[number][1]);
lc.setRow(display_div, 0, numh[number][0]);
}
void drawmNum(int number, int display_div)
{ // drawNum は、数値"number"を、デバイス"display_div"に表示させる
lc.setRow(display_div, 7, numm[number][7]); // デバイス display_div の 1行分(x,y)を纏めて表示設定
lc.setRow(display_div, 6, numm[number][6]); // 変数名num [数値] [行目] 表示を示している
lc.setRow(display_div, 5, numm[number][5]);
lc.setRow(display_div, 4, numm[number][4]);
lc.setRow(display_div, 3, numm[number][3]);
lc.setRow(display_div, 2, numm[number][2]);
lc.setRow(display_div, 1, numm[number][1]);
lc.setRow(display_div, 0, numm[number][0]);
}
void setup()
{
Serial.begin(115200);
WiFi.begin(ssid,password);
while (WiFi.status() != WL_CONNECTED ) {
Serial.print(".");
delay(500);
}
timeClient.begin();
// power up led matrices
for (i=0; i<4; i++)
{
lc.shutdown(i,false); // デバイス i をシャットダウンしてモードを切り替え
lc.setIntensity(i,0); // set brightness 0-15 デバイス i の明るさを指定
lc.clearDisplay(i); // デバイス i の表示を全クリア
}
}
void displayTime()
{
//modify brightness
for (i=0; i<4; i++)
}
// print hour to led =======================================================
//first set hours to show just 0 in second module after midnight
if (hour==24)
{
twelve=0; // midnight is 00:00
// drawNum は 数値を、デバイスに表示させる
drawhNum(0,3); //place 0 in second module
}
//change time display for BST/GMT - 'hour' is in 24H format and set for GMT
//first set BST summer time flag for months from April through Septemebr
if ((month>3) && (month<10))
{
bstflag=1;
}
else
{
bstflag=0;
}
// Now set the summer time flag after the last Sunday in March ===============
if ((month==3) && (dayOfMonth>24) && (dayOfWeek==1) && (hour>1))
{
bstflag=1;
}
//and remove the BST flag after the last sunday in October
if ((month==10) && (dayOfMonth>24) && (dayOfWeek==1) && (hour>1))
{
bstflag=0;
}
//from here on use bstflag to increment the displayed hour ====================
//work out display for 12 hour format
hour += bstflag;
/*
if (hour>12)
{ // 下記が有効になると12時間表示になる
hour -= 12;
}
*/
twelve = hour;
if (twelve<10)
{
// drawNum は、数値 numberを、デバイスdisplay_div に表示させる
drawhNum(twelve,2); //and write whole hour in second module
}
if (twelve>9)
{
drawhNum(twelve/10,3); //write first digit in first module
drawhNum(twelve%10,2); //and write whole hour in second module
}
if (minute < 10)
{
// drawNum は数値 numberを、デバイスdisplay_div に表示させる
drawmNum(0,1); //put 0 in module 3
}
else
{
drawmNum(minute/10,1); //or put minutes/10 in mod 3
}
drawmNum(minute%10,0); //and the rest of the minutes/10 in module 4
// 10で分を割っているので、10以下の分の値が求められる
}
void loop()
{
timeClient.update();
Serial.print(daysOfTheWeek[timeClient.getDay()]);
Serial.print(", ");
Serial.print(timeClient.getHours());
Serial.print(":");
Serial.print(timeClient.getMinutes());
Serial.print(":");
Serial.println(timeClient.getSeconds());
hour = timeClient.getHours();
minute = timeClient.getMinutes();
displayTime(); // display the real-time clock data on the Serial Monitor,
// blinking dot to show we are working
if (x==0)
{
lc.setLed(2, 1, 0, true); // これはデバイス2 の row=1 col=0 を点灯(true)させる
lc.setLed(2, 2, 0, false);
lc.setLed(2, 5, 0, false);
lc.setLed(2, 6, 0, true);
delay(1000); // every second
x=1;
}
else
{
lc.setLed(2, 1, 0, false); // これはデバイス2 のrow=1 col=0 を消灯(false)させる
lc.setLed(2, 2, 0, true);
lc.setLed(2, 5, 0, true);
lc.setLed(2, 6, 0, false);
delay(1000); // every second
x=0;
}
それに、HEX Arryの枠には、私が使いたいデータが打ち出されるので、そのままコピーしてSketchに貼り付けることが出来た。
NodeMCUを使った8x8ドットマトリックスLED時計の作り方
Simple Dot Matrix Clock Using Node MCU
これは、RTC Clock を使った方法で、WiFiから時間データを読み取る方法は記載されていない。
そのため、下記のURLを参考にして、NTPサーバーから時間データを読み取るようにした。
使っている表示フォントは気に入ったので、使わせて戴いた。但し”7”は少し変更を加えた。
NTPサーバーからの時間入力方法
Getting Date & Time From NTP Server With ESP8266 NodeMCU
ESP32用のLED matrix 接続ピン
Demo 5: How to use Arduino ESP32 to display information on SPI LED matrix
《更にその後、当日ですが・・・》
Espressif ESP32-Wrover-B も ESP32 Dev Module と同じようなピン配列なので、D25,D26,D27 ピンに8x8ドットマトリックスを接続して起動を確認してみた ・・・ 問題なく時間を表示出来た!

《その後》
上図にあるEspressif ESP32 Wrover-B で運用しているのですが・・・いくつか問題が見つかりました。未だ直していません。
➀ある時間経過すると表示が消えてしまう。「RST」ボタンで直ぐに復帰します。スリープ状態なのでしょうか?
➁24時を過ぎてもどんどん時間数表示を加算してゆく。例えば27時とか表示する。なにかのトリガーが入ると、正常な表示になる。
Recent Comments