網頁

基於Blynk雲端平台的RTC工具之LCD1602時鐘加上序列留言功能



透過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來克服。