在透過Blynk的RTC工具製作自動對時TM1637七節顯示時鐘的文章中,我使用Blynk的RTC工具抓取伺服器的標準時間,然後在顯示在TM1637上。而我今天要顯示在LCD1602的螢幕上,因為LCD可以顯示比較多的資訊,好比溫濕度、時間日期等等,比起單純七節時鐘顯示器TM1637有更多可以拓展的用途,而且之後還可以搭配更大塊的液晶(或oled)顯示更多的資訊。
首先我使用的是帶有IIC的LCD1602模組,因為這樣可以省下相當多的接腳問題,而因為這塊液晶是5V的電壓,所以我使用的Vcc是NodeMCU的Vin腳(5V)。至於訊號腳電平轉換的問題,我倒是沒有去考慮,因為我看國外不少人也是這樣直接連接的,至少到目前為止還沒有任何問題,然後將SCL接上D1;SDA接上D2。
接下來我先使用i2c_scanner掃描LCD1602的硬體位址,接著再使用Wiring NodeMCU ESP8266 12E with i2C 16×2 LCD Screen這篇文章的程式碼測試NodeMCU點亮LCD1602,確認好可以顯示後我就準備將這個程式與Blynk的RTC程式做結合。
接著我整併LCD與RTC的程式碼,並且與電腦端的NTP校時軟體進行對照,總體來說大概都會差約一秒左右的時間,但考慮到網路的延遲之類的就別太勉強了,至少我不用去進行調整它就會自動較正時間。
然而在寫時間顯示的程式時有遇到一個問題,那就是時間數字補零的問題,如果個位數時它會往前跑(等於靠左),這樣在顯示上會不太好看,這個問題我在Real Time Clock Module, LCD Display and Controller Time這篇文章找到很好的解決方案,它另外寫了一個副程式去進行判斷,讓程式碼看起來不會落落長。
#define BLYNK_PRINT Serial
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
#include <TimeLib.h>
#include <WidgetRTC.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
char auth[] = "";
char ssid[] = "";
char pass[] = "";
BlynkTimer timer;
WidgetRTC rtc;
void setup()
{
//Serial.begin(9600);
Blynk.begin(auth, ssid, pass);
rtc.begin();
lcd.init();
lcd.clear();
lcd.backlight();
timer.setInterval(500L, digitalClockDisplay);
setSyncInterval(3600);
}
void loop()
{
Blynk.run();
timer.run();
}
void digitalClockDisplay()
{
bool result = Blynk.connected();
if (result) {
lcd.setCursor(3, 0);
lcd.print(year());
lcd.setCursor(7, 0);
lcd.print("/");
lcd.setCursor(8, 0);
printDigits(month());
lcd.setCursor(10, 0);
lcd.print("/");
lcd.setCursor(11, 0);
printDigits(day());
lcd.setCursor(4, 1);
printDigits(hour());
lcd.setCursor(6, 1);
lcd.print(":");
lcd.setCursor(7, 1);
printDigits(minute());
lcd.setCursor(9, 1);
lcd.print(":");
lcd.setCursor(10, 1);
printDigits(second());
}
else {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Disconnected");
}
}
void printDigits(int digits) {
if (digits < 10)
lcd.print('0');
lcd.print(digits);
}
但是只有顯示RTC的時間不夠看,我還想要測試在Blynk的APP上利用Terminal發送訊息,讓LCD上面可以顯示一些我輸入在裡面的字串,同時在上方顯示時間,測試後是沒有問題的,只是要注意不要超過16個字元不然會截尾。
#define BLYNK_PRINT Serial
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
#include <TimeLib.h>
#include <WidgetRTC.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
char auth[] = "";
char ssid[] = "";
char pass[] = "";
WidgetTerminal terminal(V1);
BlynkTimer timer;
WidgetRTC rtc;
void setup()
{
//Serial.begin(9600);
Blynk.begin(auth, ssid, pass);
rtc.begin();
lcd.init();
lcd.clear();
lcd.noBacklight();
timer.setInterval(500L, digitalClockDisplay);
setSyncInterval(3600);
}
void loop()
{
Blynk.run();
timer.run();
}
void digitalClockDisplay()
{
bool result = Blynk.connected();
if (result) {
lcd.setCursor(4, 0);
printDigits(hour());
lcd.setCursor(6, 0);
lcd.print(":");
lcd.setCursor(7, 0);
printDigits(minute());
lcd.setCursor(9, 0);
lcd.print(":");
lcd.setCursor(10, 0);
printDigits(second());
}
else {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Disconnected");
}
}
void printDigits(int digits) {
if (digits < 10)
lcd.print('0');
lcd.print(digits);
}
BLYNK_WRITE(V1)
{
lcd.setCursor(0, 1);
lcd.print(" ");
lcd.setCursor(0, 1);
lcd.print(param.asStr());
}
總算是完成LCD的顯示工作了,在我接著想做的多功能雲端智慧時鐘專案中,我還想加入溫溼度、PM2.5等等的設計,只是目前還在物色哪一些模組比較適合(DHT11真的太不準了),因此現在先多方面的測試單一元件,到時候再將它整併再一起。
至於1602實在能顯示的字太少了,這個之後看看能不能用Oled來克服。
接下來我先使用i2c_scanner掃描LCD1602的硬體位址,接著再使用Wiring NodeMCU ESP8266 12E with i2C 16×2 LCD Screen這篇文章的程式碼測試NodeMCU點亮LCD1602,確認好可以顯示後我就準備將這個程式與Blynk的RTC程式做結合。
接著我整併LCD與RTC的程式碼,並且與電腦端的NTP校時軟體進行對照,總體來說大概都會差約一秒左右的時間,但考慮到網路的延遲之類的就別太勉強了,至少我不用去進行調整它就會自動較正時間。
然而在寫時間顯示的程式時有遇到一個問題,那就是時間數字補零的問題,如果個位數時它會往前跑(等於靠左),這樣在顯示上會不太好看,這個問題我在Real Time Clock Module, LCD Display and Controller Time這篇文章找到很好的解決方案,它另外寫了一個副程式去進行判斷,讓程式碼看起來不會落落長。
#define BLYNK_PRINT Serial
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
#include <TimeLib.h>
#include <WidgetRTC.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
char auth[] = "";
char ssid[] = "";
char pass[] = "";
BlynkTimer timer;
WidgetRTC rtc;
void setup()
{
//Serial.begin(9600);
Blynk.begin(auth, ssid, pass);
rtc.begin();
lcd.init();
lcd.clear();
lcd.backlight();
timer.setInterval(500L, digitalClockDisplay);
setSyncInterval(3600);
}
void loop()
{
Blynk.run();
timer.run();
}
void digitalClockDisplay()
{
bool result = Blynk.connected();
if (result) {
lcd.setCursor(3, 0);
lcd.print(year());
lcd.setCursor(7, 0);
lcd.print("/");
lcd.setCursor(8, 0);
printDigits(month());
lcd.setCursor(10, 0);
lcd.print("/");
lcd.setCursor(11, 0);
printDigits(day());
lcd.setCursor(4, 1);
printDigits(hour());
lcd.setCursor(6, 1);
lcd.print(":");
lcd.setCursor(7, 1);
printDigits(minute());
lcd.setCursor(9, 1);
lcd.print(":");
lcd.setCursor(10, 1);
printDigits(second());
}
else {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Disconnected");
}
}
void printDigits(int digits) {
if (digits < 10)
lcd.print('0');
lcd.print(digits);
}
但是只有顯示RTC的時間不夠看,我還想要測試在Blynk的APP上利用Terminal發送訊息,讓LCD上面可以顯示一些我輸入在裡面的字串,同時在上方顯示時間,測試後是沒有問題的,只是要注意不要超過16個字元不然會截尾。
#define BLYNK_PRINT Serial
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
#include <TimeLib.h>
#include <WidgetRTC.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
char auth[] = "";
char ssid[] = "";
char pass[] = "";
WidgetTerminal terminal(V1);
BlynkTimer timer;
WidgetRTC rtc;
void setup()
{
//Serial.begin(9600);
Blynk.begin(auth, ssid, pass);
rtc.begin();
lcd.init();
lcd.clear();
lcd.noBacklight();
timer.setInterval(500L, digitalClockDisplay);
setSyncInterval(3600);
}
void loop()
{
Blynk.run();
timer.run();
}
void digitalClockDisplay()
{
bool result = Blynk.connected();
if (result) {
lcd.setCursor(4, 0);
printDigits(hour());
lcd.setCursor(6, 0);
lcd.print(":");
lcd.setCursor(7, 0);
printDigits(minute());
lcd.setCursor(9, 0);
lcd.print(":");
lcd.setCursor(10, 0);
printDigits(second());
}
else {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Disconnected");
}
}
void printDigits(int digits) {
if (digits < 10)
lcd.print('0');
lcd.print(digits);
}
BLYNK_WRITE(V1)
{
lcd.setCursor(0, 1);
lcd.print(" ");
lcd.setCursor(0, 1);
lcd.print(param.asStr());
}