esp网络时钟
随便玩玩
·
配件
-
ESP32 30P CP2102 Type-C 开发板
-
0.96寸 OLED 屏幕 (I2C接口)
接线
#四针oled接线
SDA -> ESP32 的 G21
SCL -> ESP32 的 G22
VCC -> ESP32 的 3V3
GND -> ESP32 的 GND
IDE:Arduino IDE
安装U8g2lib字体库
#include <WiFi.h>
#include <U8g2lib.h>
#include <Wire.h>
#include "time.h"
const char* ssid = "xxx";
const char* password = "xxx";
// 2. NTP 服务器配置
const char* ntpServer = "ntp.aliyun.com"; // 阿里云 NTP 服务器
const long gmtOffset_sec = 8 * 3600; // 中国时区为 UTC+8,即 8*3600 秒
const int daylightOffset_sec = 0; // 中国没有夏令时
unsigned long syncInterval = 3600 * 1000;
unsigned long lastSyncTime = 0;
// 3. 硬件对象初始化
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);
void syncTimeNetwork() {
Serial.println("\n--- 开始网络对时任务 ---");
//必须先设置模式为 STA,才能唤醒 WiFi 硬件
WiFi.mode(WIFI_STA);
delay(10); // 给硬件一点点启动时间
WiFi.begin(ssid, password);
int retry = 0;
// 等待连接,最多等 15 秒 (30 * 500ms)
while (WiFi.status() != WL_CONNECTED && retry < 30) {
delay(500);
Serial.print(".");
retry++;
}
if (WiFi.status() == WL_CONNECTED) {
Serial.println("\nWiFi 已连接!正在同步时间...");
configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
// 给系统一点时间去获取 NTP 数据包
struct tm timeinfo;
if (getLocalTime(&timeinfo, 10000)) { // 增加一个10秒的超时等待
Serial.println("网络对时成功!当前时间: ");
Serial.println(&timeinfo, "%F %T");
lastSyncTime = millis(); // 【只有对时成功才重置一小时定时器】
} else {
Serial.println("时间获取超时,内部 RTC 将继续走时。");
// 如果对时失败,让它 5 分钟后再尝试,而不是 1 小时
lastSyncTime = millis() - (syncInterval - 300000);
}
// 任务完成,关闭 WiFi 模块省电
WiFi.disconnect(true);
WiFi.mode(WIFI_OFF);
Serial.println("WiFi 已关闭,已切回本地走时模式");
} else {
Serial.println("\nWiFi 连接失败,放弃本次对时。");
// 失败了,5 分钟后再次尝试
lastSyncTime = millis() - (syncInterval - 300000);
WiFi.mode(WIFI_OFF); // 即使失败也要关掉,避免一直耗电
}
}
void setup() {
Serial.begin(115200);
Wire.begin(21, 22);
u8g2.begin();
u8g2.enableUTF8Print();
syncTimeNetwork();
// 注意:不需要在 setup 里写 lastSyncTime = millis(),函数内部已经写了
}
void loop() {
if(millis() - lastSyncTime > syncInterval){
syncTimeNetwork();
lastSyncTime = millis();
}
struct tm timeinfo;
// --- 步骤 C: 获取本地时间 ---
if (!getLocalTime(&timeinfo)) {
Serial.println("无法获取时间");
return;
}
// --- 步骤 D: 在 OLED 上显示 ---
u8g2.clearBuffer();
// 显示日期 (年-月-日)
u8g2.setFont(u8g2_font_wqy12_t_gb2312a);
u8g2.setCursor(20, 15);
u8g2.printf("%04d-%02d-%02d",
timeinfo.tm_year + 1900,
timeinfo.tm_mon + 1,
timeinfo.tm_mday);
// 显示大字时间 (时:分:秒)
// 使用一种大号的数字字体(u8g2 内置很多数字字体)
u8g2.setFont(u8g2_font_logisoso24_tn);
u8g2.setCursor(10, 45);
u8g2.printf("%02d:%02d:%02d",
timeinfo.tm_hour,
timeinfo.tm_min,
timeinfo.tm_sec);
// 显示星期
u8g2.setFont(u8g2_font_wqy12_t_gb2312a);
const char* weekDays[] = {"日", "一", "二", "三", "四", "五", "六"};
u8g2.setCursor(45, 60);
u8g2.printf("星期%s", weekDays[timeinfo.tm_wday]);
u8g2.sendBuffer();
delay(1000); // 每秒刷新一次
}
成果

更多推荐



所有评论(0)