Arduino筆記(47):NodeMCU對網絡時間協定(NTP) 校時後顯示時間

上一篇 Arduino筆記(46):使用 I2C轉接板在LCD 1602顯示日期時間,將 RTC 的時間顯示在 16x2的 LCD上,另外做了兩個按鍵調整時間,想說如果將開發板改成具有無線功能的 NodeMCU,透過網路跟遠端的 NTP 伺服主機進行校時,這樣就可以不用 RTC模組跟按鍵,直接透過網路設定時間,時間會更準確。實作結果如下圖,顯示在LCD的時間跟電腦經過NTP校時的時間比較,完全一樣。

[網絡時間協定NTP]

網絡時間協定(英語:Network Time Protocol,縮寫:NTP)是在資料網路潛伏時間可變的電腦系統之間通過封包交換進行時鐘同步的一個網路協定,位於OSI模型的應用層。自1985年以來,NTP是目前仍在使用的最古老的網際網路協定之一。NTP由德拉瓦大學的David L. Mills設計。NTP意圖將所有參與電腦的協調世界時(UTC)時間同步到幾毫秒的誤差內。[維基百科]


[安裝NTPClient Library]

NTPClient 函式庫提供與NTP伺服主機的連線,並回傳日期時間,可以用 getFormattedTime()函數取得字串,字串格式為 2018-05-28T16:00:13Z。或是使用 getEpochTime() 取得自 1970/01/01起算的妙數,這個函式主要是用來更新 RTC 時間模組的 。

先到 Github 下載 taranais/NTPClient,按右邊綠色選項「Clone or download」,再選「Download ZIP」。
注意:NTPClient 在 Github上有好幾個,有的Library 沒有 getFormattedTime() 這個函式,編譯時會出現「Error: ‘class NTPClient’ has no member named ‘getFormattedDate」,就需要更換成上述 taranais 的 NTPClient 函式庫。

• 將下載的壓縮檔解壓縮,放在 Arduino 主程式下的 libraries目錄內,以我的電腦來說,Arduino安裝在  C:\User\[登入的帳號]\Documents\Arduino,點進目錄有一個 libraries的子目錄,下載後解壓縮的目錄,整個放進  libraries 目錄,重新啟動 Arduino即可。

[材料]

• NodeMCU V3 x 1
• 1602 LCD模組 x 1
• IIC/I2C/介面 LCD1602轉接板 x 1
• 連接線 x 4
• 麵包板電源 x 1
• 麵包板 x 1

[線路圖]

NodeMCU
I2C 1602 LCD
VIN
VCC
GND
GND
GPIO 4(D2)
SDA
GPIO 5(D1)
SCL

[程式]

#include <LiquidCrystal_I2C.h>
#include <ESP8266WiFi.h>
#include <NTPClient.h>
#include <WiFiUdp.h>

// 儲存日期及時間的變數
String formattedDate;
String dayStamp;
String timeStamp;

// 設定無線基地台SSID跟密碼
const char* ssid     = "MyHome";
const char* password = "12345678";

WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP);

// 設定 LCD的欄和列數
LiquidCrystal_I2C lcd(0x27,16,2);

void setup() {
  // 初始化 LCD
  lcd.init();
  // 開啟LCD背光模式
  lcd.backlight();
//  Wire.begin();
  
  Serial.begin(9600);

  // 連接無線基地台
  WiFi.begin(ssid, password);
  Serial.print("\n\r \n\rWorking to connect");

  // 等待連線,並從 Console顯示 IP
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  timeClient.begin();

  // 設定時區 *60分 * 60秒,例如:
  // GMT +1 = 3600
  // GMT +8 = 28800  台灣時區
  // GMT 0 = 0
  timeClient.setTimeOffset(28800);
}

void loop() {

  while(!timeClient.update()) {
    timeClient.forceUpdate();
  }
  // formattedDate函式取得的日期格式為: 2018-05-28T16:00:13Z
  formattedDate = timeClient.getFormattedDate();
  Serial.println(formattedDate);

  // 取得日期
  int splitT = formattedDate.indexOf("T");
  dayStamp = formattedDate.substring(0, splitT);
  Serial.print("DATE: ");
  Serial.println(dayStamp);

  // 設定顯示位置
  lcd.setCursor(0, 0);
  // 顯示日期
  lcd.print("DATE:");
  lcd.print(dayStamp);

  // 取得時間
  timeStamp = formattedDate.substring(splitT+1, formattedDate.length()-1);
  Serial.print("TIME:");
  Serial.println(timeStamp);
  lcd.setCursor(0, 1);
  lcd.print("TIME: ");
  lcd.print(timeStamp);
 
  delay(1000);
}

[實作結果]

我的NodeMCU開發板上的VIN接到 DS1602 LCD顯示器時,完全亮燈,看起來是沒有電源,後來改接 開發板上的 3.3V,顯示的字有點暗,不太明顯 (如下圖)。就改用外接 5V 電源,顯示就正常了 ( 如最上面的圖)。


[參考資料]

• Randomnerdtutorials:How to Use I2C LCD with ESP32 on Arduino IDE (ESP8266 compatible)
• Github:taranais/NTPClient

3 留言

  1. 您好 想請教下,LCD和NodeMCU間不用做level shifing嗎?
    感謝

    回覆刪除
  2. NodeMCU並沒有+5V的輸出端,但它有兩個電源輸入端,分別為USB的+5V和Vin,這兩個輸入端分別串接一個蕭特基二極體再接到穩壓器1117的輸入端,所以USB的+5V被二極體阻斷無法在Vin端取得電壓,用電錶量測Vin端的電壓在空載的時候可能會有約4.7V的電壓值,但它只是二極體的漏電流產生的,當你加上LCD,Vin的電壓就降為0了,LCD無法動作,你可以從穩壓器1117的輸入端焊一條線到Vin,提供電源給LCD,否則必須額外外加+5V給LCD,另外當你從Vin供應電壓給NodeMCU時LCD並且電源接在Vin,請注意電壓不可以超過LCD的額定電壓

    回覆刪除

張貼留言

較新的 較舊