搜尋程式碼

ESP32 教學 53/55 - 建立 LCD 網絡時鐘 | SunFounder 嘅 ESP32 IoT 學習套件

ESP32 教學 53/55 - 建立 LCD 網絡時鐘 | SunFounder 嘅 ESP32 IoT 學習套件

喺呢個教學入面,我哋會用SunFounder嘅ESP32微控制器嚟整一個連上互聯網嘅LCD時鐘。呢個時鐘會自動透過互聯網同步到當前時間,以12小時或24小時格式顯示時間,仲有星期、日期同月份。使用網絡時間協定(NTP)確保時鐘保持準確,唔使手動調整。

esp32-53-internet-clock-main

呢個項目利用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-11_LCD-wiring

要將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伺服器攞時間數據。關鍵標識符好似ssidpassword用嚟連接Wi-Fi網絡,而ntpServer1ntpServer2指定要使用嘅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 互聯網時鐘示範

圖片

ESP32-11_LCD-wiring
ESP32-11_LCD-wiring
ESP32-11_LCD-wiring-schematic
ESP32-11_LCD-wiring-schematic
esp32-53-internet-clock-main
esp32-53-internet-clock-main
854-ESP32 Tutorial 53/55- Internet Clock
語言: C++

/*
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 :)
}

你可能需要嘅嘢

資源與參考資料

文件📁

所需文件 (.h)