Poradnik ESP32 53/55 - Zbuduj internetowy zegar LCD | Zestaw edukacyjny SunFounder ESP32 IoT
W tym samouczku zbudujemy zegar LCD podłączony do Internetu, wykorzystując mikrokontroler ESP32 firmy SunFounder. Zegar ten będzie automatycznie synchronizował się z aktualnym czasem przez Internet, wyświetlając czas w formacie 12- lub 24-godzinnym, wraz z dniem tygodnia, datą i miesiącem. Zastosowanie protokołu NTP (Network Time Protocol) zapewnia, że zegar pozostaje dokładny bez ręcznych regulacji.
Ten projekt wykorzystuje wbudowane możliwości Wi-Fi modułu ESP32 do pobierania aktualnego czasu z serwera NTP. Do wyświetlania czasu użyjemy wyświetlacza ciekłokrystalicznego (LCD), który można sformatować zgodnie z preferencjami użytkownika. W celu dalszego wyjaśnienia poszczególnych kroków, zapoznaj się z filmem (na filmie w 00:30).
Omówienie sprzętu
Główne komponenty tego projektu to mikrokontroler ESP32, wyświetlacz LCD 20x4 oraz źródło zasilania. ESP32 to wydajny mikrokontroler z wbudowanym Wi-Fi i Bluetooth, co czyni go odpowiednim do projektów IoT. Wyświetlacz LCD służy do pokazywania czasu i daty i można go skonfigurować dla różnych rozmiarów wyświetlania.
Wyświetlacz LCD działa poprzez protokół I2C, który umożliwia komunikację za pomocą dwóch przewodów (SDA i SCL). Upraszcza to okablowanie i zmniejsza liczbę pinów potrzebnych na ESP32. Połączenie z serwerem NTP jest realizowane za pomocą funkcji Wi-Fi modułu ESP32, co umożliwia aktualizacje w czasie rzeczywistym.
- Zapewnij prawidłowe napięcie zasilania (5 V).
- Użyj kondensatorów odsprzęgających w pobliżu pinów zasilania dla stabilności.
- Zachowaj ostrożność przy połączeniach I2C, aby uniknąć konfliktów na magistrali.
- Zweryfikuj adres I2C wyświetlacza LCD (0x27 lub 0x3F).
- Sprawdź dane logowania do Wi-Fi, aby zapewnić prawidłowe połączenie.
- Uwzględnij zmiany czasu letniego/zimowego w swoim kodzie.
- Użyj prawidłowego serwera NTP dla swojej lokalizacji geograficznej.
- Zawsze czyść wyświetlacz LCD przed aktualizacją ekranu.
Instrukcje okablowania

Aby podłączyć ESP32 do wyświetlacza LCD, zacznij od podłączenia pinów zasilania. Podłącz VCC wyświetlacza LCD do pinu 5V na ESP32, a pin GND wyświetlacza LCD do pinu GND na ESP32. Do komunikacji I2C podłącz pin SDA wyświetlacza LCD do GPIO 21 na ESP32, a pin SCL do GPIO 22. Upewnij się, że połączenia są pewne, aby uniknąć problemów z komunikacją.
Podczas konfigurowania okablowania użyj przewodów połączeniowych męsko-żeńskich, aby ułatwić podłączanie. Jeśli Twój wyświetlacz LCD ma inny adres I2C lub konfigurację pinów, odpowiednio dostosuj kod. W razie potrzeby zapoznaj się z filmem (na filmie w 05:30) w celu uzyskania alternatywnych opcji okablowania.
Przykłady kodu i omówienie
Kod inicjalizuje wyświetlacz LCD i konfiguruje połączenie Wi-Fi w celu pobierania danych czasu z serwera NTP. Kluczowe identyfikatory, takie jak ssid i password, służą do połączenia z siecią Wi-Fi, natomiast ntpServer1 i ntpServer2 określają serwery NTP do użycia.
const char* ssid = "dars";
const char* password = "llllllllllllll";
const char* ntpServer1 = "pool.ntp.org";
const char* ntpServer2 = "time.nist.gov";
Ten fragment pokazuje dane logowania do sieci i adresy serwerów. Upewnij się, że poprawnie wprowadziłeś swoją nazwę SSID i hasło Wi-Fi, ponieważ każdy błąd uniemożliwi ESP32 połączenie z Internetem.
W funkcji printLocalTime() bieżący czas jest formatowany do wyświetlenia. Struktura tm służy do przechowywania informacji o czasie, a strftime pomaga sformatować czas w czytelny ciąg znaków.
void printLocalTime() {
struct tm timeinfo;
if(!getLocalTime(&timeinfo)) {
Serial.println("No time available (yet)");
return;
}
char timeHour[5];
strftime(timeHour, 5, "%H", &timeinfo);
Ten kod sprawdza, czy czas lokalny jest dostępny, i pobiera godzinę. Sformatowana godzina jest następnie używana do wyświetlania bieżącego czasu na wyświetlaczu LCD. Jeśli czas nie jest jeszcze dostępny, wypisuje komunikat w monitorze szeregowym.
Na koniec funkcja setup() inicjalizuje wyświetlacz LCD i łączy się z Wi-Fi. Konfiguruje również ustawienia serwera NTP i ustawia funkcję zwrotną do synchronizacji czasu.
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);
Ten fragment inicjalizuje monitor szeregowy do debugowania, konfiguruje wyświetlacz LCD i próbuje połączyć się z określoną siecią Wi-Fi. Status połączenia zostanie wypisany w monitorze szeregowym, co pozwoli zweryfikować połączenie.
Demonstracja / Czego się spodziewać
Po pomyślnej konfiguracji wyświetlacz LCD pokaże bieżący czas, dzień tygodnia i datę. Możesz oczekiwać, że czas będzie aktualizowany co 5 sekund dzięki funkcji loop(). Jeśli połączenie z serwerem NTP nie powiedzie się, w monitorze szeregowym pojawi się komunikat informujący, że czas nie jest jeszcze dostępny (na filmie w 12:00).
Typowe problemy obejmują nieprawidłowe okablowanie, błędne adresy I2C i nieprawidłowe dane logowania do Wi-Fi. Upewnij się, że wszystkie połączenia są pewne i że serwer NTP jest osiągalny z Twojej sieci.
Znaczniki czasu w filmie
- 00:00 Start
- 2:10 Wprowadzenie
- 5:15 Omówienie okablowania
- 7:32 Omówienie kodu Arduino
- 18:43 Wybór płytki ESP32 i portu COM w Arduino IDE
- 20:27 Demonstracja zegara internetowego
/*
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
Rzeczy, których możesz potrzebować
-
AmazonBuy LCD1602-I2C from Amazonamzn.to
-
AllegroPurchase LCD1602-I2C from eBayebay.us
-
BanggoodPurchase LCD1602 display from Banggoodbanggood.com
Zasoby i odniesienia
-
ZewnętrznyPurchase LCD1602 display from Banggoodbanggood.com
Pliki📁
Wymagany plik (.h)
-
TZ.h
TZ.h0.02 MB