ESP32教程53/55 - 构建LCD网络时钟 | SunFounder的ESP32物联网学习套件
在本教程中,我们将使用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上所需的引脚数量。使用ESP32的Wi-Fi功能连接到NTP服务器,实现实时更新。
- 确保电源电压正确(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上显示当前时间。如果时间尚不可用,则会在串行监视器上打印一条消息。
最后,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);
此摘录初始化串行监视器以进行调试,设置LCD,并尝试连接到指定的Wi-Fi网络。连接状态将打印到串行监视器上,以便您验证连接。
演示 / 预期效果
成功设置后,LCD将显示当前时间、星期和日期。由于loop()函数的作用,时间将每5秒更新一次。如果与NTP服务器的连接失败,串行监视器上将出现一条消息,指示时间尚不可用(视频中12:00处)。
常见问题包括接线错误、I2C地址错误和Wi-Fi凭据不正确。确保所有连接牢固,并且NTP服务器可从您的网络访问。
视频时间戳
- 00:00 开始
- 2:10 介绍
- 5:15 接线说明
- 7:32 Arduino代码说明
- 18:43 在Arduino IDE中选择ESP32开发板和COM端口
- 20:27 互联网时钟演示
/*
* 使用SunFounder的IoT ESP32学习套件的互联网时钟
* 完整视频教程 https://youtu.be/0KnuNqfiVug
* 📚⬇️ 下载和资源页面 https://robojax.com/RJT686
* ESP32的互联网时钟
* 由Ahamd Shasmhiri于2023年12月31日19:29撰写
* www.Robojax.com
*/
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
// SDA->21,SCL->22
LiquidCrystal_I2C lcd(0x27,16,2); // 将LCD地址设置为0x27,以用于16个字符和2行显示。
const bool showSeconds = true; // 设置为"true"以显示秒,设置为"false"以隐藏
const bool showShortMonth = false; // 十二月 = 假,十二月 = 真
const bool show24Hours = true; // 在18:30时为真,或在6:30时为假
#include <WiFi.h>
#include "time.h"
#include "sntp.h"
#include "TZ.h"
// TZ.h 是从 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 12小时制: %I:%M:%S");
// 获取时间格式 HH:MM
char timeHour[5];
strftime(timeHour,5, "%H", &timeinfo);
String hourString = String(timeHour); // 将时间小时转换为字符串
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];
// 序列.println(个月[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); // 如果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);
}
// 回调函数(当时间通过NTP调整时被调用)
void timeavailable(struct timeval *t)
{
Serial.println("Got time adjustment from NTP!");
printLocalTime();
}
void setup()
{
Serial.begin(115200);
lcd.init(); // 初始化LCD
lcd.backlight(); // 打开液晶显示屏背光。
lcd.print("Internet Clock");
delay(3000); // 毫无价值 3秒
// 设置通知回调函数
sntp_set_time_sync_notification_cb( timeavailable );
/*
* NTP服务器地址可以通过DHCP获取,
*
* 注意:此调用应在esp32通过DHCP获取IP地址之前进行,否则SNTP选项42将默认被拒绝。
* 注意:如果在DHCP客户端运行后调用configTime()函数,将会覆盖获取的NTP服务器地址。
*/
sntp_servermode_dhcp(1); // (optional)
/*
* 这将设置配置的 NTP 服务器和常量时区/夏令时偏移,如果您的时区不需要每年调整两次夏令时偏移,应该是可以的,在这种情况下,时间调整不会自动处理。
*/
// configTime(时区偏移秒, 夏令时偏移秒, ntp服务器1, ntp服务器2);
/*
* 处理带有夏令时偏移的时区更方便的方法是指定一个环境变量,该变量包含时区定义和夏令时调整规则。您可以从 https://github.com/esp8266/Arduino/blob/master/cores/esp8266/TZ.h 获取您所在时区的规则列表。
*/
// configTzTime(TZ_America_Toronto, ntpServer1, ntpServer2);
configTzTime(TZ_America_Toronto, ntpServer1, ntpServer2);
// 连接到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(); // 需要一些时间来同步时间 :)
}
Common Course Links
Common Course Files
|||您可能需要的东西
-
亚马逊从亚马逊购买LCD1602-I2Camzn.to
-
易趣在eBay上购买LCD1602-I2Cebay.us
-
BanggoodPurchase LCD1602 display from Banggoodbanggood.com
资源与参考
-
外部Purchase LCD1602 display from Banggoodbanggood.com
文件📁
必需文件 (.h)
-
TZ.h
TZ.h0.02 MB