ESP32 教學 53/55 - 建立 LCD 網絡時鐘 | SunFounder 嘅 ESP32 IoT 學習套件
喺呢個教學入面,我哋會用SunFounder嘅ESP32微控制器嚟整一個連上互聯網嘅LCD時鐘。呢個時鐘會自動透過互聯網同步到當前時間,以12小時或24小時格式顯示時間,仲有星期、日期同月份。使用網絡時間協定(NTP)確保時鐘保持準確,唔使手動調整。
呢個項目利用ESP32內置嘅Wi-Fi功能,從NTP伺服器攞當前時間。我哋會用一個液晶顯示器(LCD)嚟展示時間,可以按照用戶嘅喜好嚟格式化。如果有任何步驟唔清楚,請參考影片(影片喺00:30)。
硬件講解
呢個項目嘅主要組件包括ESP32微控制器、一個20x4 LCD顯示器同一個電源。ESP32係一個功能強大嘅微控制器,內置Wi-Fi同藍牙,好適合物聯網項目。LCD用嚟顯示時間同日期,可以配置唔同嘅顯示尺寸。
LCD透過I2C協定運作,可以用兩條線(SDA同SCL)嚟通訊。咁樣簡化咗接線,減少咗ESP32上需要嘅引腳數量。連接NTP伺服器係用ESP32嘅Wi-Fi功能,實現實時更新。
- 確保電源電壓正確(5 V)。
- 喺電源引腳附近加退耦電容以保持穩定。
- 小心I2C連接,避免匯流排衝突。
- 確認LCD嘅I2C地址(0x27或0x3F)。
- 檢查Wi-Fi憑證以確保連接準確。
- 喺程式碼入面處理夏令時間調整。
- 根據你嘅地理位置使用正確嘅NTP伺服器。
- 更新顯示之前一定要清除LCD。
接線說明

要將ESP32同LCD接線,首先連接電源引腳。將LCD嘅VCC連接到ESP32上嘅5V引腳,將LCD嘅GND引腳連接到ESP32上嘅GND引腳。對於I2C通訊,將LCD嘅SDA引腳連接到ESP32上嘅GPIO 21,將SCL引腳連接到GPIO 22。確保連接穩固,避免任何通訊問題。
設置接線時,使用公對母跳線方便連接。如果你嘅LCD有唔同嘅I2C地址或引腳配置,請相應調整程式碼。如有需要,請參考影片(影片喺05:30)了解其他接線選項。
程式碼示例同講解
程式碼初始化LCD並設置Wi-Fi連接,從NTP伺服器攞時間數據。關鍵標識符好似ssid同password用嚟連接Wi-Fi網絡,而ntpServer1同ntpServer2指定要使用嘅NTP伺服器。
const char* ssid = "dars";
const char* password = "llllllllllllll";
const char* ntpServer1 = "pool.ntp.org";
const char* ntpServer2 = "time.nist.gov";
呢段代碼顯示網絡憑證同伺服器地址。確保準確輸入你嘅Wi-Fi SSID同密碼,因為任何錯誤都會令ESP32無法連接到互聯網。
喺printLocalTime()函數入面,當前時間會被格式化用嚟顯示。結構tm用嚟儲存時間資訊,而strftime幫手將時間格式化為可讀嘅字符串。
void printLocalTime() {
struct tm timeinfo;
if(!getLocalTime(&timeinfo)) {
Serial.println("No time available (yet)");
return;
}
char timeHour[5];
strftime(timeHour, 5, "%H", &timeinfo);
呢段程式碼檢查本地時間係咪可用,並攞返小時。格式化嘅小時之後用嚟喺LCD上顯示當前時間。如果時間仲未可用,佢會喺Serial Monitor度打印一條訊息。
最後,setup()函數初始化LCD並連接Wi-Fi。佢仲配置NTP伺服器設置,並設置一個時間同步嘅回調函數。
void setup() {
Serial.begin(115200);
lcd.init(); // initialize the lcd
lcd.backlight(); // Turns on the LCD backlight.
Serial.printf("Connecting to %s ", ssid);
WiFi.begin(ssid, password);
呢段摘錄初始化Serial Monitor用嚟調試,設置LCD,並嘗試連接到指定嘅Wi-Fi網絡。連接狀態會打印到Serial Monitor,等你可以驗證連接。
示範 / 預期效果
成功設置之後,LCD會顯示當前時間、星期同日期。你可以預期時間每5秒更新一次,全靠loop()函數。如果連接NTP伺服器失敗,Serial Monitor會出現一條訊息,表示時間仲未可用(影片喺12:00)。
常見問題包括接線錯誤、I2C地址錯誤同Wi-Fi憑證錯誤。確保所有連接穩固,而且NTP伺服器可以從你嘅網絡到達。
影片時間戳
- 00:00 開始
- 2:10 介紹
- 5:15 接線講解
- 7:32 Arduino程式碼講解
- 18:43 喺Arduino IDE入面選擇ESP32開發板同COM端口
- 20:27 互聯網時鐘示範
/*
Internet Clock using SunFounder's IoT ESP32 Learning kit
Full video instruction https://youtu.be/0KnuNqfiVug
📚⬇️ Download and resource page https://robojax.com/RJT686
Internet Clock for ESP32
Written by Ahamd Shasmhiri on Dec 31, 2023 at 19:29
www.Robojax.com
*/
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
//SDA->21,SCL->22
LiquidCrystal_I2C lcd(0x27,16,2); // set the LCD address to 0x27 for a 16 chars and 2 line display
const bool showSeconds = true;//set to "true" to show seconds and "false" to hide
const bool showShortMonth = false;//December = false, Dec=true
const bool show24Hours = true;//true to have 18:30 or false to have 6:30
#include <WiFi.h>
#include "time.h"
#include "sntp.h"
#include "TZ.h"
//TZ.h is taken from https://github.com/esp8266/Arduino/blob/master/cores/esp8266/TZ.h
const char* ssid = "dars";
const char* password = "llllllllllllll";
const char* ntpServer1 = "pool.ntp.org";
const char* ntpServer2 = "time.nist.gov";
const long gmtOffset_sec = -5 * 3600;
const int daylightOffset_sec = 3600;
const String months[][2] ={
"January","Jan",
"February","Feb",
"March","Mar",
"April","Apr",
"May","May",
"June","Jun",
"July","Jul",
"August","Aug",
"September","Sep",
"October","Oct",
"November","Nov",
"December","Dec"
};
void printLocalTime()
{
struct tm timeinfo;
if(!getLocalTime(&timeinfo)){
Serial.println("No time available (yet)");
return;
}
//Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S 12Hours: %I:%M:%S");
// get time format HH:MM
char timeHour[5];
strftime(timeHour,5, "%H", &timeinfo);
String hourString = String(timeHour);//convert timeHour to string
char timeMinute[3];
strftime(timeMinute,3, "%M", &timeinfo);
String minuteString = String(timeMinute);
//Serial.println(hourString);
if(!show24Hours)
{
if(hourString.toInt() >= 12)
{
minuteString = minuteString + "PM";
}else{
minuteString = minuteString + "AM";
}
}
char timeSeconds[3];
strftime(timeSeconds,3, "%S", &timeinfo);
char timeDayofWeek[10];
strftime(timeDayofWeek, 10 , "%A", &timeinfo);
char timeMonth[10];
strftime(timeMonth, 10 , "%B", &timeinfo);
String Month = String(timeMonth);
if(showShortMonth)
{
for(int m=0; m <12; m++)
{
if(Month == months[m][0] )
{
Month = months[m][1];
//Serial.println(months[m][1]);
}
}
}
char timeDayofMonth[3];
strftime(timeDayofMonth,3 , "%d", &timeinfo);
char timeYear[5];
strftime(timeYear, 5 , "%Y", &timeinfo);
String time = String(timeHour) + ":" + minuteString ;
if(showSeconds) time = time +":" + String(timeSeconds);//add seconds if showSeconds=true
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(time);
lcd.print(" ");
lcd.print(String(timeDayofWeek));
//
lcd.setCursor(0, 1);
lcd.print(timeDayofMonth);
lcd.print(" ");
lcd.print(Month);
lcd.print(" ");
lcd.print(timeYear);
}
// Callback function (get's called when time adjusts via NTP)
void timeavailable(struct timeval *t)
{
Serial.println("Got time adjustment from NTP!");
printLocalTime();
}
void setup()
{
Serial.begin(115200);
lcd.init();// initialize the lcd
lcd.backlight(); // Turns on the LCD backlight.
lcd.print("Internet Clock");
delay(3000);//waif 3 seconds
// set notification call-back function
sntp_set_time_sync_notification_cb( timeavailable );
/**
* NTP server address could be aquired via DHCP,
*
* NOTE: This call should be made BEFORE esp32 aquires IP address via DHCP,
* otherwise SNTP option 42 would be rejected by default.
* NOTE: configTime() function call if made AFTER DHCP-client run
* will OVERRIDE aquired NTP server address
*/
sntp_servermode_dhcp(1); // (optional)
/**
* This will set configured ntp servers and constant TimeZone/daylightOffset
* should be OK if your time zone does not need to adjust daylightOffset twice a year,
* in such a case time adjustment won't be handled automagicaly.
*/
// configTime(gmtOffset_sec, daylightOffset_sec, ntpServer1, ntpServer2);
/**
* A more convenient approach to handle TimeZones with daylightOffset
* would be to specify a environmnet variable with TimeZone definition including daylight adjustmnet rules.
* A list of rules for your zone could be obtained from https://github.com/esp8266/Arduino/blob/master/cores/esp8266/TZ.h
*/
//configTzTime(TZ_America_Toronto, ntpServer1, ntpServer2);
configTzTime(TZ_America_Toronto, ntpServer1, ntpServer2);
//connect to WiFi
Serial.printf("Connecting to %s ", ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println(" CONNECTED");
}
void loop()
{
delay(5000);
printLocalTime(); // it will take some time to sync time :)
}
Common Course Links
Common Course Files
你可能需要嘅嘢
-
亞馬遜Buy LCD1602-I2C from Amazonamzn.to
-
易贝Purchase LCD1602-I2C from eBayebay.us
-
邦购Purchase LCD1602 display from Banggoodbanggood.com
資源與參考資料
-
外部Purchase LCD1602 display from Banggoodbanggood.com
文件📁
所需文件 (.h)
-
TZ.h
TZ.h0.02 MB