【花雕学编程】Arduino动手做(238)---ESP32 CYD 数字时钟

2024-11-152445
AI 快速预览详细 收起
本文介绍了如何使用ESP32-CYD(2432S028)液晶2.8寸屏开发板制作数字时钟。该开发板主控为ESP32-WROOM-32模块,集成了Wi-Fi和蓝牙功能,支持多种开发环境如Arduino IDE、ESP IDE、MicroPython和Mixly。硬件包括LCD显示器、背光控制电路、触控式屏幕控制电路、扬声器驱动电路、光敏电路和RGB LED控制电路。此外,还支持TF卡界面、序列界面、温湿度感测器界面和保留的IO口界面。这个项目适合零基础新手入门,无需复杂前置技能即可完成。
【花雕学编程】Arduino动手做(238)---ESP32 CYD 数字时钟图1

ESP32-CYD(2432S028)液晶2.8寸屏开发板使用ESP32-WROOM-32模块作为主控,主控是一款双核MCU,集成了Wi-Fi和蓝牙功能,主频可达240MHz,具有520KB的SRAM、448KB的ROM,闪存容量为4MB+4MB,显示分辨率为240x320,采用电阻式触控式屏幕。该模块包括LCD显示器、背光控制电路、触控式屏幕控制电路、扬声器驱动电路、光敏电路和RGB LED控制电路。支持TF卡界面、序列界面、温湿度感测器界面(DHT11界面)和保留的IO口界面,该模块支持在Arduino IDE、ESP IDE、MicroPython和Mixly中进行开发。

【花雕学编程】Arduino动手做(238)---ESP32 CYD 数字时钟图2

创作许可协议

本项目采用 None(不开放任何权利,保留所有权利) 进行许可。

评论(12)
驴友花雕
驴友花雕
作者
实验场景图

驴友花雕
驴友花雕
作者
实验场景图 动态图

驴友花雕
驴友花雕
作者
连接CYD,打开Arduono IDE,实验串口返回情况

驴友花雕
驴友花雕
作者
没想到,过了一天,这个网站又可以正常访问了

驴友花雕
驴友花雕
作者
重新上传代码,可以运行了,实验串口返回情况

检查API的服务状态
访问WorldTimeAPI网站(https://worldtimeapi.org/),才发现API服务不能正常运行。
驴友花雕
驴友花雕
作者
后来采取扩大存储,在 Arduino IDE 中转到工具 > 分区方案>选择任何超过 1.4MB APP 的内容,例如:“Huge APP (3MB No OTA/1MB SPIFFS”)。

驴友花雕
驴友花雕
作者
代码的简要说明:
1、引入库:
lvgl.h:用于图形界面的LVGL库。
TFT_eSPI.h:用于驱动TFT显示屏的TFT_eSPI库。
WiFi.h:用于WiFi连接的库。
HTTPClient.h:用于发起HTTP请求的库。
ArduinoJson.h:用于处理JSON数据的库。
2、WiFi设置:
ssid和password:用于连接到WiFi网络的凭据。
3、时区设置:
timezone:设置为葡萄牙的时区"Europe/Lisbon"。
4、日期和时间变量:
current_date和current_time:存储当前日期和时间的字符串。
hour、minute、second:存储小时、分钟、秒的整数变量。
sync_time_date:标志变量,用于指示是否需要同步日期和时间。
5、屏幕参数:
SCREEN_WIDTH和SCREEN_HEIGHT:屏幕的宽度和高度。
DRAW_BUF_SIZE和draw_buf:绘图缓冲区的大小和数组。
6、日志打印函数:
log_print:用于打印LVGL日志的函数。
7、时间格式化函数:
format_time:将时间格式化为两位数的字符串。
8、定时器回调函数:
timer_cb:每秒更新时间显示,并在需要时同步日期和时间。
9、主GUI创建函数:
lv_create_main_gui:初始化GUI界面,包括创建时间标签和日期标签,并设置它们的样式和位置。
10、日期和时间获取函数:
get_date_and_time:从WorldTimeAPI获取当前的日期和时间,并解析JSON数据。
11、setup函数:
初始化串口通信,连接到WiFi网络,初始化LVGL和显示屏,并创建主GUI。
12、loop函数:
周期性地检查是否需要更新时间,并处理LVGL的GUI任务,以及更新屏幕显示。
驴友花雕
驴友花雕
作者
代码编译时,出现错误

错误信息
Sketch uses 1448233 bytes (110%) of program storage space. Maximum is 1310720 bytes.
Global variables use 63176 bytes (19%) of dynamic memory, leaving 264504 bytes for local variables. Maximum is 327680 bytes.
Sketch too big; see https://support.arduino.cc/hc/en-us/articles/360013825179 for tips on reducing it.
text section exceeds available space in board
Compilation error: text section exceeds available space in board
Sketch使用1448233字节(110%)的程序存储空间。最大值为1310720字节。
全局变量使用63176字节(19%)的动态内存,留下264504字节用于局部变量。最大为327680字节。
草图太大;看https://support.arduino.cc/hc/en-us/articles/360013825179以获取减少它的提示。
文本部分超出板上的可用空间
编译错误:文本部分超出板上的可用空间
没有想到,ESP32也会遇到程序存储空间不够的情况。
驴友花雕
驴友花雕
作者
【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
实验二百三十八:ESP32开发板WiFi蓝牙2.8寸240*320智能液晶显示屏带触摸屏TFT模块
项目实验之二十四:带 LVGL 的 ESP32 CYD:显示时间和日期的数字时钟
实验开源代码
[code]/*
【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
实验二百三十八:ESP32开发板WiFi蓝牙2.8寸240*320智能液晶显示屏带触摸屏TFT模块
项目实验之二十四:带 LVGL 的 ESP32 CYD:显示时间和日期的数字时钟
*/
#include // 引入LVGL图形库
#include // 引入TFT_eSPI库,用于驱动TFT显示屏
#include // 引入WiFi库,用于WiFi连接
#include // 引入HTTPClient库,用于发起HTTP请求
#include // 引入ArduinoJson库,用于处理JSON数据
// 替换为您的网络凭据
const char* ssid = "zhz3";// WiFi名称
const char* password = "z156721";// WiFi密码
// 指定您想要获取时间的时区:https://worldtimeapi.org/api/timezone
// 葡萄牙时区示例:"Europe/Lisbon"
const char* timezone = "Europe/Lisbon"; // 设置时区
// 存储日期和时间
String current_date; // 当前日期
String current_time; // 当前时间
// 存储小时、分钟、秒
static int32_t hour; // 小时
static int32_t minute; // 分钟
static int32_t second; // 秒
bool sync_time_date = false; // 是否同步日期和时间
#define SCREEN_WIDTH 240 // 屏幕宽度
#define SCREEN_HEIGHT 320 // 屏幕高度
#define DRAW_BUF_SIZE (SCREEN_WIDTH * SCREEN_HEIGHT / 10 * (LV_COLOR_DEPTH / 8)) // 绘图缓冲区大小
uint32_t draw_buf[DRAW_BUF_SIZE / 4]; // 绘图缓冲区
// 如果启用了日志记录,它将告知用户库中发生了什么
void log_print(lv_log_level_t level, const char * buf) {
LV_UNUSED(level); // 未使用的参数
Serial.println(buf); // 打印日志
Serial.flush(); // 清空串口缓冲区
}
String format_time(int time) { // 格式化时间为两位数
return (time < 10) ? "0" + String(time) : String(time);
}
static lv_obj_t * text_label_time; // 时间标签
static lv_obj_t * text_label_date; // 日期标签
static void timer_cb(lv_timer_t * timer){ // 定时器回调函数
LV_UNUSED(timer);
second++;
if(second > 59) { // 秒数超过59则进位
second = 0;
minute++;
if(minute > 59) { // 分钟超过59则进位
minute = 0;
hour++;
sync_time_date = true; // 设置同步日期和时间标志
Serial.println(sync_time_date);
Serial.println("\n\n\n\n\n\n\n\n");
if(hour > 23) { // 小时超过23则归零
hour = 0;
}
}
}
String hour_time_f = format_time(hour); // 格式化小时
String minute_time_f = format_time(minute); // 格式化分钟
String second_time_f = format_time(second); // 格式化秒
String final_time_str = String(hour_time_f) + ":" + String(minute_time_f) + ":" + String(second_time_f); // 组合成最终时间字符串
//Serial.println(final_time_str);
lv_label_set_text(text_label_time, final_time_str.c_str()); // 设置时间标签文本
lv_label_set_text(text_label_date, current_date.c_str()); // 设置日期标签文本
}
void lv_create_main_gui(void) { // 创建主GUI界面
// 从WorldTimeAPI获取时间和日期
while(hour==0 && minute==0 && second==0) {
get_date_and_time();
}
Serial.println("Current Time: " + current_time); // 打印当前时间
Serial.println("Current Date: " + current_date); // 打印当前日期
lv_timer_t * timer = lv_timer_create(timer_cb, 1000, NULL); // 创建定时器
lv_timer_ready(timer); // 定时器立即执行
// 创建居中对齐的时间文本标签
text_label_time = lv_label_create(lv_screen_active()); // 创建标签
lv_label_set_text(text_label_time, ""); // 设置标签文本为空
lv_obj_align(text_label_time, LV_ALIGN_CENTER, 0, -30); // 设置标签位置
// 设置字体类型和大小
static lv_style_t style_text_label;
lv_style_init(&style_text_label); // 初始化样式
lv_style_set_text_font(&style_text_label, &lv_font_montserrat_48); // 设置字体为48号
lv_obj_add_style(text_label_time, &style_text_label, 0); // 应用样式
// 创建居中对齐的日期文本标签
text_label_date = lv_label_create(lv_screen_active()); // 创建标签
lv_label_set_text(text_label_date, current_date.c_str()); // 设置标签文本
lv_obj_align(text_label_date, LV_ALIGN_CENTER, 0, 40); // 设置标签位置
// 设置字体类型和大小
static lv_style_t style_text_label2;
lv_style_init(&style_text_label2); // 初始化样式
lv_style_set_text_font(&style_text_label2, &lv_font_montserrat_30); // 设置字体为30号
lv_obj_add_style(text_label_date, &style_text_label2, 0); // 应用样式
lv_obj_set_style_text_color((lv_obj_t*) text_label_date, lv_palette_main(LV_PALETTE_GREY), 0); // 设置文本颜色为灰色
}
void get_date_and_time() { // 获取日期和时间
if (WiFi.status() == WL_CONNECTED) { // 如果WiFi已连接
HTTPClient http; // 创建HTTPClient对象
// 构造API端点
String url = String("http://worldtimeapi.org/api/timezone/") + timezone;
http.begin(url); // 初始化HTTP请求
int httpCode = http.GET(); // 发起GET请求
if (httpCode > 0) { // 如果请求成功
// 检查响应
if (httpCode == HTTP_CODE_OK) { // 如果响应码为OK
String payload = http.getString(); // 获取响应内容
//Serial.println("Time information:");
//Serial.println(payload);
// 解析JSON以提取时间
JsonDocument doc; // 创建JSON文档
DeserializationError error = deserializeJson(doc, payload); // 反序列化JSON
if (!error) { // 如果没有错误
const char* datetime = doc["datetime"]; // 获取datetime字段
// 将datetime分割为日期和时间
String datetime_str = String(datetime);
int splitIndex = datetime_str.indexOf('T');
current_date = datetime_str.substring(0, splitIndex); // 提取日期部分
current_time = datetime_str.substring(splitIndex + 1, splitIndex + 9); // 提取时间部分
hour = current_time.substring(0, 2).toInt(); // 提取小时
minute = current_time.substring(3, 5).toInt(); // 提取分钟
second = current_time.substring(6, 8).toInt(); // 提取秒
} else { // 如果反序列化失败
Serial.print("deserializeJson() failed: ");
Serial.println(error.c_str()); // 打印错误信息
}
}
} else { // 如果请求失败
Serial.printf("GET request failed, error: %s\n", http.errorToString(httpCode).c_str()); // 打印错误信息
sync_time_date = true; // 设置同步日期和时间标志
}
http.end(); // 关闭连接
} else { // 如果WiFi未连接
Serial.println("Not connected to Wi-Fi"); // 打印未连接信息
}
}
void setup() {
String LVGL_Arduino = String("LVGL Library Version: ") + lv_version_major() + "." + lv_version_minor() + "." + lv_version_patch(); // LVGL库版本
Serial.begin(115200); // 初始化串口通信
Serial.println(LVGL_Arduino); // 打印LVGL库版本
// 连接到WiFi
WiFi.begin(ssid, password); // 初始化WiFi连接
Serial.print("Connecting"); // 打印连接信息
while (WiFi.status() != WL_CONNECTED) { // 等待WiFi连接
delay(500); // 延时
Serial.print("."); // 打印点以显示进度
}
Serial.print("\nConnected to Wi-Fi network with IP Address: "); // 打印连接成功的信息
Serial.println(WiFi.localIP()); // 打印IP地址
// 开始LVGL图形库的初始化
lv_init();
// 注册打印函数,用于调试
lv_log_register_print_cb(log_print);
// 创建一个显示对象
lv_display_t * disp;
// 使用TFT_eSPI库初始化TFT显示屏
disp = lv_tft_espi_create(SCREEN_WIDTH, SCREEN_HEIGHT, draw_buf, sizeof(draw_buf)); // 创建显示对象,设置屏幕宽高和绘图缓冲区
lv_display_set_rotation(disp, LV_DISPLAY_ROTATION_270); // 设置屏幕旋转方向为270度
// 函数用于绘制GUI
lv_create_main_gui();
}
void loop() {
// 从WorldTimeAPI获取日期和时间
if(sync_time_date) { // 如果需要同步日期和时间
sync_time_date = false; // 重置同步标志
get_date_and_time(); // 获取日期和时间
while(hour==0 && minute==0 && second==0) { // 如果获取的时间无效(即小时、分钟、秒都为0)
get_date_and_time(); // 再次尝试获取日期和时间
}
}
lv_task_handler(); // 让LVGL执行GUI任务
lv_tick_inc(5); // 告诉LVGL已经过去了5毫秒
delay(5); // 等待5毫秒
}[/code]
驴友花雕
驴友花雕
作者
要获取您所在时区的准确日期和时间,我们将使用 WorldTimeAPI。要从 API 获取时间,ESP32 需要连接到互联网,因此您需要在周围环境中安装路由器,以便 ESP32 可以连接到它。
安装 ArduinoJson 库
对于此项目,您需要安装 ArduinoJSON 库,以便在向 WorldTimeAPI 发出请求时处理 JSON 响应。
在 Arduino IDE 中,转到 Sketch > Include Library > Manage Libraries。搜索 ArduinoJSON 并安装 Benoit Blanchon 提供的库。我们使用的是 7.0.4 版本。我们建议使用相同的版本。

驴友花雕
驴友花雕
作者


驴友花雕
驴友花雕
作者
安装TFT_eSPI、XPT2046_Touchscreen、BasicLinearAlgebra和LVGL库
网址:
TFT_eSPI库的网址:https://github.com/Bodmer/TFT_eSPI
XPT2046_Touchscreen库的网址: https://github.com/PaulStoffregen/XPT2046_Touchscreen
BasicLinearAlgebra库:https://github.com/tomstewart89/BasicLinearAlgebra
要正确使用 TFT_eSPI 库,需要根据不同开发板与TFT屏幕正确配置User_Setup.h和lv_conf.h文件。
LVGL中文开发手册:https://lvgl.100ask.net/master/


- 没有更多了 -