{"id":162157,"date":"2024-09-05T13:51:15","date_gmt":"2024-09-05T13:51:15","guid":{"rendered":"https:\/\/randomnerdtutorials.com\/?p=162157"},"modified":"2024-10-07T14:34:41","modified_gmt":"2024-10-07T14:34:41","slug":"esp32-tft-lvgl-digital-clock","status":"publish","type":"post","link":"https:\/\/randomnerdtutorials.com\/esp32-tft-lvgl-digital-clock\/","title":{"rendered":"ESP32 TFT with LVGL: Digital Clock with Time and Date"},"content":{"rendered":"\n<p>In this guide, you&#8217;ll learn how to turn your ESP32 and a TFT display into a digital clock that displays time and date. We&#8217;ll use the LVGL (Light Versatile Graphics Library) and the WorldTimeAPI to get the current time and date. The ESP32 will be programmed using Arduino IDE.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" fetchpriority=\"high\" decoding=\"async\" width=\"1200\" height=\"675\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/09\/ESP32-TFT-Screen-LVGL-Digital-Clock-with-Time-and-Date.jpg?resize=1200%2C675&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 TFT Screen LVGL Digital Clock with Time and Date\" class=\"wp-image-162138\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/09\/ESP32-TFT-Screen-LVGL-Digital-Clock-with-Time-and-Date.jpg?w=1920&amp;quality=100&amp;strip=all&amp;ssl=1 1920w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/09\/ESP32-TFT-Screen-LVGL-Digital-Clock-with-Time-and-Date.jpg?resize=300%2C169&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/09\/ESP32-TFT-Screen-LVGL-Digital-Clock-with-Time-and-Date.jpg?resize=1024%2C576&amp;quality=100&amp;strip=all&amp;ssl=1 1024w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/09\/ESP32-TFT-Screen-LVGL-Digital-Clock-with-Time-and-Date.jpg?resize=768%2C432&amp;quality=100&amp;strip=all&amp;ssl=1 768w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/09\/ESP32-TFT-Screen-LVGL-Digital-Clock-with-Time-and-Date.jpg?resize=1536%2C864&amp;quality=100&amp;strip=all&amp;ssl=1 1536w\" sizes=\"(max-width: 1200px) 100vw, 1200px\" \/><\/figure><\/div>\n\n\n<p class=\"rntbox rntclblue\">Are you using a CYD board? Read this guide: <a href=\"https:\/\/randomnerdtutorials.com\/esp32-cyd-lvgl-digital-clock\/\">ESP32 CYD with LVGL &#8211; Digital Clock with Time and Date<\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Project Overview<\/h2>\n\n\n\n<p>In this project, we\u2019ll display the time and date from the WorldTimeAPI on a 2.8-inch ILI9341 TFT LCD Touchscreen (240&#215;320). The time and date will be displayed on text labels.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" decoding=\"async\" width=\"750\" height=\"456\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/09\/ESP32-TFT-LVGL-Digital-Clock-Time-and-Date-Demonstration-Screen.png?resize=750%2C456&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 TFT LVGL Digital Clock Time and Date Demonstration Screen\" class=\"wp-image-162145\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/09\/ESP32-TFT-LVGL-Digital-Clock-Time-and-Date-Demonstration-Screen.png?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/09\/ESP32-TFT-LVGL-Digital-Clock-Time-and-Date-Demonstration-Screen.png?resize=300%2C182&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/figure><\/div>\n\n\n<p>To get an accurate date and time for your timezone, we\u2019ll use the <a href=\"https:\/\/worldtimeapi.org\/\" target=\"_blank\" rel=\"noopener\" title=\"\">WorldTimeAPI<\/a>. To get the time from the API, the ESP32 needs to connect to the internet, so you need to have a router in your surroundings so that the ESP32 can connect to it.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Prerequisites<\/h2>\n\n\n\n<p>Before proceeding, make sure you follow the next prerequisites.<strong> You must follow all steps, otherwise, your project will not work.<\/strong><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">1) Parts Required<\/h3>\n\n\n\n<p>For this project, you need the following parts:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/makeradvisor.com\/tools\/2-8-inch-ili9341-tft-240x320\/\" target=\"_blank\" rel=\"noreferrer noopener\">TFT LCD Touchscreen Display \u2013 2.8 inch ILI9341 240\u00d7320<\/a><\/li>\n\n\n\n<li>ESP32 board with enough pins to wire the display (for example an <a href=\"https:\/\/makeradvisor.com\/tools\/esp32-dev-board-wi-fi-bluetooth\/\" target=\"_blank\" rel=\"noopener\" title=\"\">ESP32 DOIT V1 board<\/a>)<\/li>\n\n\n\n<li><a href=\"https:\/\/makeradvisor.com\/tools\/mb-102-solderless-breadboard-830-points\/\" target=\"_blank\" rel=\"noopener\" title=\"\">Breadboard<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/makeradvisor.com\/tools\/jumper-wires-kit-120-pieces\/\" target=\"_blank\" rel=\"noopener\" title=\"\">Jumper wires<\/a><\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">2) Install ESP32 Boards in Arduino IDE<\/h3>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" decoding=\"async\" width=\"204\" height=\"204\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/06\/arduino-ide-2.jpg?resize=204%2C204&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Arduino IDE 2 Logo\" class=\"wp-image-159109\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/06\/arduino-ide-2.jpg?w=204&amp;quality=100&amp;strip=all&amp;ssl=1 204w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/06\/arduino-ide-2.jpg?resize=150%2C150&amp;quality=100&amp;strip=all&amp;ssl=1 150w\" sizes=\"(max-width: 204px) 100vw, 204px\" \/><\/figure><\/div>\n\n\n<p>We&#8217;ll program the ESP32 using Arduino IDE. Make sure you have the ESP32 boards installed. Follow the next tutorial:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/randomnerdtutorials.com\/installing-esp32-arduino-ide-2-0\/\" title=\"\">Installing ESP32 Board in Arduino IDE 2 (Windows, Mac OS X, Linux)<\/a><\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">3) Get familiar with the ILI9341 TFT LCD Touchscreen Display<\/h3>\n\n\n\n<p>The display we\u2019re using in this guide is the 2.8. inch TFT LCD that also comes with a touchscreen. The display communicates via SPI communication protocol and uses the ILI9341 driver. The touchscreen also uses the SPI communication protocol.<\/p>\n\n\n\n<p>The TFT LCD touchscreen also comes with an SD card interface if you need to load files for your specific project. This display is also available with different screen sizes, but we&#8217;ll use the one with 240 x 320 pixels).<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"750\" height=\"421\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/03\/TFT-LCD-Touchscreen-display.jpg?resize=750%2C421&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ILI9341 TFT LCD Touchscreen Display\" class=\"wp-image-150003\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/03\/TFT-LCD-Touchscreen-display.jpg?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/03\/TFT-LCD-Touchscreen-display.jpg?resize=300%2C168&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/figure><\/div>\n\n\n<p>If this is your first time using this display, make sure to follow our getting started guide:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong><a href=\"https:\/\/randomnerdtutorials.com\/lvgl-esp32-tft-touchscreen-display-ili9341-arduino\/\" title=\"\">ESP32 with LVGL: TFT LCD Touchscreen Display \u2013 2.8 inch ILI9341 240\u00d7320 (Arduino IDE)<\/a><\/strong><\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">4) Wire the Display to the ESP32<\/h3>\n\n\n\n<p>Wire the TFT LCD and touchscreen pins to the ESP32 GPIOs according to the next table (you must use these exact pins, otherwise the project will not work).<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"750\" height=\"422\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/03\/ESP32-TFT-Display-Screen-Wiring.jpg?resize=750%2C422&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Wiring TFT LCD Touchscreen display to ESP32\" class=\"wp-image-150007\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/03\/ESP32-TFT-Display-Screen-Wiring.jpg?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/03\/ESP32-TFT-Display-Screen-Wiring.jpg?resize=300%2C169&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/figure><\/div>\n\n\n<figure class=\"wp-block-table\"><table><tbody><tr><td><strong>TFT LCD Touchscreen<\/strong><\/td><td><strong>ESP32<\/strong><\/td><\/tr><tr><td>T_IRQ<\/td><td>GPIO 36<\/td><\/tr><tr><td>T_OUT<\/td><td>GPIO 39<\/td><\/tr><tr><td>T_DIN<\/td><td>GPIO 32<\/td><\/tr><tr><td>T_CS<\/td><td>GPIO 33<\/td><\/tr><tr><td>T_CLK<\/td><td>GPIO 25<\/td><\/tr><tr><td>SDO(MISO)<\/td><td>GPIO 12<\/td><\/tr><tr><td>LED<\/td><td>GPIO 21<\/td><\/tr><tr><td>SCK<\/td><td>GPIO 14<\/td><\/tr><tr><td>SDI(MOSI)<\/td><td>GPIO 13<\/td><\/tr><tr><td>D\/C<\/td><td>GPIO 2<\/td><\/tr><tr><td>RESET<\/td><td>EN\/RESET<\/td><\/tr><tr><td>CS<\/td><td>GPIO 15<\/td><\/tr><tr><td>GND<\/td><td>GND<\/td><\/tr><tr><td>VCC<\/td><td>5V (or 3.3V)*<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>* In the VCC pin, you can either use 5V or 3.3V depending if your <strong>J1<\/strong> connection is open or closed (by default it&#8217;s usually open as you can see in the figure below).<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>VCC = 5V | J1=OPEN\nVCC = 3.3V | J1=CLOSE<\/code><\/pre>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"750\" height=\"422\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/03\/TFT-LCD-touchscreen-J1-connection.jpg?resize=750%2C422&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"TFT LCD Touchscreen display J1 connection\" class=\"wp-image-150009\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/03\/TFT-LCD-touchscreen-J1-connection.jpg?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/03\/TFT-LCD-touchscreen-J1-connection.jpg?resize=300%2C169&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/figure><\/div>\n\n\n<h3 class=\"wp-block-heading\">5) Install TFT and LVGL Libraries<\/h3>\n\n\n\n<p><a href=\"https:\/\/docs.lvgl.io\/master\/\" target=\"_blank\" rel=\"noreferrer noopener\">LVGL<\/a>&nbsp;(Light and Versatile Graphics Library) is a free and open-source graphics library that provides a wide range of easy-to-use graphical elements for your microcontroller projects that require a graphical user interface (GUI).<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full is-resized\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"622\" height=\"194\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/08\/LVGL-new-logo.png?resize=622%2C194&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"LVGL new logo\" class=\"wp-image-161339\" style=\"width:340px\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/08\/LVGL-new-logo.png?w=622&amp;quality=100&amp;strip=all&amp;ssl=1 622w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/08\/LVGL-new-logo.png?resize=300%2C94&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 622px) 100vw, 622px\" \/><\/figure><\/div>\n\n\n<p>Follow the next tutorial to install and configure the required libraries to use LVGL with the 2.8 inch ILI9341 240\u00d7320 TFT LCD Touchscreen using Arduino IDE.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/randomnerdtutorials.com\/lvgl-esp32-tft-touchscreen-display-ili9341-arduino\/\" title=\"\"><strong>LVGL with ESP32 TFT LCD Touchscreen Display \u2013 2.8 inch ILI9341 240\u00d7320 (Arduino IDE)<\/strong><\/a><\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">6) Install ArduinoJson Library<\/h3>\n\n\n\n<p>For this project, you need to install the ArduinoJSON library to handle the JSON response when you make a request to the WorldTimeAPI.<\/p>\n\n\n\n<p>In the Arduino IDE, go to <strong>Sketch <\/strong>&gt; <strong>Include Library<\/strong> &gt; <strong>Manage Libraries<\/strong>. Search for <strong>ArduinoJSON <\/strong>and install the library by <em>Benoit Blanchon<\/em>. We\u2019re using version 7.0.4. We recommend using the same version.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"749\" height=\"514\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/06\/install-arduinojsonlibrary-arduino-ide-2.png?resize=749%2C514&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"\" class=\"wp-image-158855\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/06\/install-arduinojsonlibrary-arduino-ide-2.png?w=749&amp;quality=100&amp;strip=all&amp;ssl=1 749w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/06\/install-arduinojsonlibrary-arduino-ide-2.png?resize=300%2C206&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 749px) 100vw, 749px\" \/><\/figure><\/div>\n\n\n<h2 class=\"wp-block-heading\">ESP32 TFT Digital Clock: Display Date and Time &#8211; Arduino Code<\/h2>\n\n\n\n<p>The following code will create two text labels with the current time and date. Before uploading the code to your board, you need to insert your network credentials so that the ESP32 can connect to the internet to get the time and date. You also need to insert your timezone.<\/p>\n\n\n<pre style=\"max-height: 40em; margin-bottom: 20px;\"><code class=\"language-c\">\/*  Rui Santos &amp; Sara Santos - Random Nerd Tutorials - https:\/\/RandomNerdTutorials.com\/esp32-cyd-lvgl-digital-clock\/  |  https:\/\/RandomNerdTutorials.com\/esp32-tft-lvgl-digital-clock\/\n    THIS EXAMPLE WAS TESTED WITH THE FOLLOWING HARDWARE:\n    1) ESP32-2432S028R 2.8 inch 240\u00d7320 also known as the Cheap Yellow Display (CYD): https:\/\/makeradvisor.com\/tools\/cyd-cheap-yellow-display-esp32-2432s028r\/\n      SET UP INSTRUCTIONS: https:\/\/RandomNerdTutorials.com\/cyd-lvgl\/\n    2) REGULAR ESP32 Dev Board + 2.8 inch 240x320 TFT Display: https:\/\/makeradvisor.com\/tools\/2-8-inch-ili9341-tft-240x320\/ and https:\/\/makeradvisor.com\/tools\/esp32-dev-board-wi-fi-bluetooth\/\n      SET UP INSTRUCTIONS: https:\/\/RandomNerdTutorials.com\/esp32-tft-lvgl\/\n    Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files.\n    The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n*\/\n\n\/*  Install the &quot;lvgl&quot; library version 9.2 by kisvegabor to interface with the TFT Display - https:\/\/lvgl.io\/\n    *** IMPORTANT: lv_conf.h available on the internet will probably NOT work with the examples available at Random Nerd Tutorials ***\n    *** YOU MUST USE THE lv_conf.h FILE PROVIDED IN THE LINK BELOW IN ORDER TO USE THE EXAMPLES FROM RANDOM NERD TUTORIALS ***\n    FULL INSTRUCTIONS AVAILABLE ON HOW CONFIGURE THE LIBRARY: https:\/\/RandomNerdTutorials.com\/cyd-lvgl\/ or https:\/\/RandomNerdTutorials.com\/esp32-tft-lvgl\/   *\/\n#include &lt;lvgl.h&gt;\n\n\/*  Install the &quot;TFT_eSPI&quot; library by Bodmer to interface with the TFT Display - https:\/\/github.com\/Bodmer\/TFT_eSPI\n    *** IMPORTANT: User_Setup.h available on the internet will probably NOT work with the examples available at Random Nerd Tutorials ***\n    *** YOU MUST USE THE User_Setup.h FILE PROVIDED IN THE LINK BELOW IN ORDER TO USE THE EXAMPLES FROM RANDOM NERD TUTORIALS ***\n    FULL INSTRUCTIONS AVAILABLE ON HOW CONFIGURE THE LIBRARY: https:\/\/RandomNerdTutorials.com\/cyd-lvgl\/ or https:\/\/RandomNerdTutorials.com\/esp32-tft-lvgl\/   *\/\n#include &lt;TFT_eSPI.h&gt;\n\n#include &lt;WiFi.h&gt;\n#include &lt;HTTPClient.h&gt;\n#include &lt;ArduinoJson.h&gt;\n\n\/\/ Replace with your network credentials\nconst char* ssid = &quot;REPLACE_WITH_YOUR_SSID&quot;;\nconst char* password = &quot;REPLACE_WITH_YOUR_PASSWORD&quot;;\n\n\/\/ Specify the timezone you want to get the time for: https:\/\/worldtimeapi.org\/api\/timezone\n\/\/ Timezone example for Portugal: &quot;Europe\/Lisbon&quot;\nconst char* timezone = &quot;Europe\/Lisbon&quot;;\n\n\/\/ Store date and time\nString current_date;\nString current_time;\n\n\/\/ Store hour, minute, second\nstatic int32_t hour;\nstatic int32_t minute;\nstatic int32_t second;\nbool sync_time_date = false;\n\n#define SCREEN_WIDTH 240\n#define SCREEN_HEIGHT 320\n\n#define DRAW_BUF_SIZE (SCREEN_WIDTH * SCREEN_HEIGHT \/ 10 * (LV_COLOR_DEPTH \/ 8))\nuint32_t draw_buf[DRAW_BUF_SIZE \/ 4];\n\n\/\/ If logging is enabled, it will inform the user about what is happening in the library\nvoid log_print(lv_log_level_t level, const char * buf) {\n  LV_UNUSED(level);\n  Serial.println(buf);\n  Serial.flush();\n}\n\nString format_time(int time) {\n  return (time &lt; 10) ? &quot;0&quot; + String(time) : String(time);\n}\n\nstatic lv_obj_t * text_label_time;\nstatic lv_obj_t * text_label_date;\n\nstatic void timer_cb(lv_timer_t * timer){\n  LV_UNUSED(timer);\n  second++;\n  if(second &gt; 59) {\n    second = 0;\n    minute++;\n    if(minute &gt; 59) {\n      minute = 0;\n      hour++;\n      sync_time_date = true;\n      Serial.println(sync_time_date);\n      Serial.println(&quot;\\n\\n\\n\\n\\n\\n\\n\\n&quot;);\n      if(hour &gt; 23) {\n        hour = 0;\n      }\n    }\n  }\n\n  String hour_time_f = format_time(hour);\n  String minute_time_f = format_time(minute);\n  String second_time_f = format_time(second);\n\n  String final_time_str = String(hour_time_f) + &quot;:&quot; + String(minute_time_f) + &quot;:&quot;  + String(second_time_f);\n  \/\/Serial.println(final_time_str);\n  lv_label_set_text(text_label_time, final_time_str.c_str());\n  lv_label_set_text(text_label_date, current_date.c_str());\n}\n\nvoid lv_create_main_gui(void) {\n  \/\/ Get the time and date from WorldTimeAPI\n  while(hour==0 &amp;&amp; minute==0 &amp;&amp; second==0) {\n    get_date_and_time();\n  }\n  Serial.println(&quot;Current Time: &quot; + current_time);\n  Serial.println(&quot;Current Date: &quot; + current_date);\n\n  lv_timer_t * timer = lv_timer_create(timer_cb, 1000, NULL);\n  lv_timer_ready(timer);\n\n  \/\/ Create a text label for the time aligned center\n  text_label_time = lv_label_create(lv_screen_active());\n  lv_label_set_text(text_label_time, &quot;&quot;);\n  lv_obj_align(text_label_time, LV_ALIGN_CENTER, 0, -30);\n  \/\/ Set font type and size\n  static lv_style_t style_text_label;\n  lv_style_init(&amp;style_text_label);\n  lv_style_set_text_font(&amp;style_text_label, &amp;lv_font_montserrat_48);\n  lv_obj_add_style(text_label_time, &amp;style_text_label, 0);\n\n  \/\/ Create a text label for the date aligned center\n  text_label_date = lv_label_create(lv_screen_active());\n  lv_label_set_text(text_label_date, current_date.c_str());\n  lv_obj_align(text_label_date, LV_ALIGN_CENTER, 0, 40);\n  \/\/ Set font type and size\n  static lv_style_t style_text_label2;\n  lv_style_init(&amp;style_text_label2);\n  lv_style_set_text_font(&amp;style_text_label2, &amp;lv_font_montserrat_30);\n  lv_obj_add_style(text_label_date, &amp;style_text_label2, 0); \n  lv_obj_set_style_text_color((lv_obj_t*) text_label_date, lv_palette_main(LV_PALETTE_GREY), 0);\n}\n\nvoid get_date_and_time() {\n  if (WiFi.status() == WL_CONNECTED) {\n    HTTPClient http;\n\n    \/\/ Construct the API endpoint\n    String url = String(&quot;http:\/\/worldtimeapi.org\/api\/timezone\/&quot;) + timezone;\n    http.begin(url);\n    int httpCode = http.GET(); \/\/ Make the GET request\n\n    if (httpCode &gt; 0) {\n      \/\/ Check for the response\n      if (httpCode == HTTP_CODE_OK) {\n        String payload = http.getString();\n        \/\/Serial.println(&quot;Time information:&quot;);\n        \/\/Serial.println(payload);\n        \/\/ Parse the JSON to extract the time\n        JsonDocument doc;\n        DeserializationError error = deserializeJson(doc, payload);\n        if (!error) {\n          const char* datetime = doc[&quot;datetime&quot;];          \n          \/\/ Split the datetime into date and time\n          String datetime_str = String(datetime);\n          int splitIndex = datetime_str.indexOf('T');\n          current_date = datetime_str.substring(0, splitIndex);\n          current_time = datetime_str.substring(splitIndex + 1, splitIndex + 9); \/\/ Extract time portion\n          hour = current_time.substring(0, 2).toInt();\n          minute = current_time.substring(3, 5).toInt();\n          second = current_time.substring(6, 8).toInt();\n        } else {\n          Serial.print(&quot;deserializeJson() failed: &quot;);\n          Serial.println(error.c_str());\n        }\n      }\n    } else {\n      Serial.printf(&quot;GET request failed, error: %s\\n&quot;, http.errorToString(httpCode).c_str());\n      sync_time_date = true;\n    }\n    http.end(); \/\/ Close connection\n  } else {\n    Serial.println(&quot;Not connected to Wi-Fi&quot;);\n  }\n}\n\nvoid setup() {\n  String LVGL_Arduino = String(&quot;LVGL Library Version: &quot;) + lv_version_major() + &quot;.&quot; + lv_version_minor() + &quot;.&quot; + lv_version_patch();\n  Serial.begin(115200);\n  Serial.println(LVGL_Arduino);\n\n  \/\/ Connect to Wi-Fi\n  WiFi.begin(ssid, password);\n  Serial.print(&quot;Connecting&quot;);\n  while (WiFi.status() != WL_CONNECTED) {\n    delay(500);\n    Serial.print(&quot;.&quot;);\n  }\n  Serial.print(&quot;\\nConnected to Wi-Fi network with IP Address: &quot;);\n  Serial.println(WiFi.localIP());\n  \n  \/\/ Start LVGL\n  lv_init();\n  \/\/ Register print function for debugging\n  lv_log_register_print_cb(log_print);\n\n  \/\/ Create a display object\n  lv_display_t * disp;\n  \/\/ Initialize the TFT display using the TFT_eSPI library\n  disp = lv_tft_espi_create(SCREEN_WIDTH, SCREEN_HEIGHT, draw_buf, sizeof(draw_buf));\n  lv_display_set_rotation(disp, LV_DISPLAY_ROTATION_270);\n  \n  \/\/ Function to draw the GUI\n  lv_create_main_gui();\n}\n\nvoid loop() {\n  \/\/ Get the time and date from WorldTimeAPI\n  if(sync_time_date) {\n    sync_time_date = false;\n    get_date_and_time();\n    while(hour==0 &amp;&amp; minute==0 &amp;&amp; second==0) {\n      get_date_and_time();\n    }\n  }\n  lv_task_handler();  \/\/ let the GUI do its work\n  lv_tick_inc(5);     \/\/ tell LVGL how much time has passed\n  delay(5);           \/\/ let this time pass\n}\n<\/code><\/pre>\n\t<p style=\"text-align:center\"><a class=\"rntwhite\" href=\"https:\/\/github.com\/RuiSantosdotme\/ESP32-TFT-Touchscreen\/raw\/main\/examples\/ESP32_LVGL_Digital_Clock\/ESP32_LVGL_Digital_Clock.ino\" target=\"_blank\">View raw code<\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">How Does the Code Work?<\/h2>\n\n\n\n<p>Let\u2019s take a look at how to get time and date from the API and update the text labels with the current values. Alternatively, you can skip to the <a href=\"#demonstration\" title=\"\">Demonstration <\/a>section.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Including Libraries<\/h3>\n\n\n\n<p>You need to include the <span class=\"rnthl rntliteral\">lvgl.h<\/span> and the <span class=\"rnthl rntliteral\">TFT_eSPI.h<\/span> libraries to communicate and display text on the screen.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>#include &lt;lvgl.h&gt;\n#include &lt;TFT_eSPI.h&gt;<\/code><\/pre>\n\n\n\n<p>You need to include the <span class=\"rnthl rntliteral\">WiFi<\/span>, <span class=\"rnthl rntliteral\">HTTPClient<\/span>, and the <span class=\"rnthl rntliteral\">ArduinoJson<\/span> libraries to make HTTP requests and handle JSON data.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>#include &lt;WiFi.h&gt;\n#include &lt;HTTPClient.h&gt;\n#include &lt;ArduinoJson.h&gt;<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Insert Your Credentials and Timezone<\/h3>\n\n\n\n<p>In the following lines, you must insert your network credentials so that the ESP32 can connect to your router.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>const char* ssid = \"REPLACE_WITH_YOUR_SSID\";\nconst char* password = \"REPLACE_WITH_YOUR_PASSWORD\";<\/code><\/pre>\n\n\n\n<p>Set your timezone in the <span class=\"rnthl rntliteral\">timezone<\/span> variable at the beginning of the code (list of all available <a href=\"http:\/\/worldtimeapi.org\/api\/timezone\" target=\"_blank\" rel=\"noopener\" title=\"\">timezones<\/a>).<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>const char* timezone = \"Europe\/Lisbon\";<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Declaring Other Variables<\/h3>\n\n\n\n<p>Create some auxiliary variables to hold the date and time values.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/ Store date and time\nString current_date;\nString current_time;\n\n\/\/ Store hour, minute, second\nstatic int32_t hour;\nstatic int32_t minute;\nstatic int32_t second;\nbool sync_time_date = false;<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Global Text Labels<\/h3>\n\n\n\n<p>We create two global LVGL text label objects, so that we can access them inside all functions later on.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>static lv_obj_t * text_label_time;\nstatic lv_obj_t * text_label_date;<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">setup()<\/h3>\n\n\n\n<p>In the <span class=\"rnthl rntliteral\">setup()<\/span>, include the following lines for debugging. These will print the version of LVGL that you\u2019re using. You must be using version 9.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>String LVGL_Arduino = String(\"LVGL Library Version: \") + lv_version_major() + \".\" + lv_version_minor() + \".\" + lv_version_patch();\nSerial.begin(115200);\nSerial.println(LVGL_Arduino);<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Connect to the Internet<\/h4>\n\n\n\n<p>To connect the ESP32 to the internet we use the following code.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/ Connect to Wi-Fi\nWiFi.begin(ssid, password);\nSerial.print(\"Connecting\");\nwhile (WiFi.status() != WL_CONNECTED) {\n  delay(500);\n  Serial.print(\".\");\n}\nSerial.print(\"\\nConnected to Wi-Fi network with IP Address: \");\nSerial.println(WiFi.localIP());<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Initialize the LVGL Library<\/h4>\n\n\n\n<p>Initialize the LVGL Library by calling the <span class=\"rnthl rntliteral\">lv_init()<\/span> function in the <span class=\"rnthl rntliteral\">setup()<\/span>.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/ Start LVGL\nlv_init();<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Register Debugging Function<\/h4>\n\n\n\n<p>Register your <span class=\"rnthl rntliteral\">log_print()<\/span> function declared previously as a function associated with debugging LVGL.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/ Register print function for debugging\nlv_log_register_print_cb(log_print);<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Create a Display Object<\/h4>\n\n\n\n<p>To write to the display, you must create a display object first. You need to do this in all your LVGL sketches. The following lines will create an LVGL display object called <span class=\"rnthl rntliteral\">disp<\/span> with the screen width, screen height, and drawing buffer defined earlier.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/ Create a display object\nlv_display_t * disp;\n\/\/ Initialize the TFT display using the TFT_eSPI library\ndisp = lv_tft_espi_create(SCREEN_WIDTH, SCREEN_HEIGHT, draw_buf, sizeof(draw_buf));\nlv_display_set_rotation(disp, LV_DISPLAY_ROTATION_270);<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Drawing the GUI<\/h4>\n\n\n\n<p>The LVGL library works asynchronously. You must call the function to draw on the display in the <span class=\"rnthl rntliteral\">setup()<\/span>. Then, everything works with events and callbacks. The code will always be listening for events in the background. When something happens, it will run the callback function associated with the event. You don\u2019t need to check for any events in the <span class=\"rnthl rntliteral\">loop()<\/span>.<\/p>\n\n\n\n<p>Throughout most of our examples, the function that will draw to the screen will be called <span class=\"rnthl rntliteral\">lv_create_main_gui()<\/span>. Then, inside that function, we\u2019ll add the instructions to build the interface.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/ Function to draw the GUI\nlv_create_main_gui();<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">get_date_and_time()<\/h3>\n\n\n\n<p>When we initialize the screen, we call the <span class=\"rnthl rntliteral\">get_date_and_time()<\/span> function to get the latest date and time from the WorldTimeAPI. Then, we store the values in some auxiliary variables that will be used to display them on the screen.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>void get_date_and_time() {\n  if (WiFi.status() == WL_CONNECTED) {\n    HTTPClient http;\n\n    \/\/ Construct the API endpoint\n    String url = String(\"http:\/\/worldtimeapi.org\/api\/timezone\/\") + timezone;\n    http.begin(url);\n    int httpCode = http.GET(); \/\/ Make the GET request\n\n    if (httpCode > 0) {\n      \/\/ Check for the response\n      if (httpCode == HTTP_CODE_OK) {\n        String payload = http.getString();\n        \/\/Serial.println(\"Time information:\");\n        \/\/Serial.println(payload);\n        \/\/ Parse the JSON to extract the time\n        JsonDocument doc;\n        DeserializationError error = deserializeJson(doc, payload);\n        if (!error) {\n          const char* datetime = doc&#091;\"datetime\"];          \n          \/\/ Split the datetime into date and time\n          String datetime_str = String(datetime);\n          int splitIndex = datetime_str.indexOf('T');\n          current_date = datetime_str.substring(0, splitIndex);\n          current_time = datetime_str.substring(splitIndex + 1, splitIndex + 9); \/\/ Extract time portion\n          hour = current_time.substring(0, 2).toInt();\n          minute = current_time.substring(3, 5).toInt();\n          second = current_time.substring(6, 8).toInt();\n        } else {\n          Serial.print(\"deserializeJson() failed: \");\n          Serial.println(error.c_str());\n        }\n      }\n    } else {\n      Serial.printf(\"GET request failed, error: %s\\n\", http.errorToString(httpCode).c_str());\n      sync_time_date = true;\n    }\n    http.end(); \/\/ Close connection\n  } else {\n    Serial.println(\"Not connected to Wi-Fi\");\n  }\n}<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Preparing the GUI<\/h3>\n\n\n\n<p>Before drawing the main GUI, we start by calling the API to get the latest time and date.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>void lv_create_main_gui(void) {\n  \/\/ Get the time and date from WorldTimeAPI\n  while(hour==0 &amp;&amp; minute==0 &amp;&amp; second==0) {\n    get_date_and_time();\n  }\n(...)<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Timer<\/h4>\n\n\n\n<p>To update the time and date text labels on the screen, we can create an LVGL timer that will run a specific function periodically. In this case, we\u2019ll update it every 1 second. Create an LVGL timer called <span class=\"rnthl rntliteral\">timer<\/span> and assign the <span class=\"rnthl rntliteral\">timer_cb<\/span> callback function.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>lv_timer_t * timer = lv_timer_create(timer_cb, 1000, NULL);\nlv_timer_ready(timer);<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Time Text Label<\/h4>\n\n\n\n<p>To create a text label, we can call the LVGL function <span class=\"rnthl rntliteral\">lv_label_create()<\/span> and pass as argument where we want to display the text. We want to add it to the current screen (<span class=\"rnthl rntliteral\">lv_screen_active()<\/span>).<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/ Create a text label for the time aligned center\ntext_label_time = lv_label_create(lv_screen_active());<\/code><\/pre>\n\n\n\n<p>After creating the text label, we can set its text by using the <span class=\"rnthl rntliteral\">lv_label_set_text()<\/span> function that accepts as arguments the text label we\u2019re referring to and the text we want to add to that label. In our case, we\u2019re setting it to empty at the beginning.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>lv_label_set_text(text_label_time, \"\");<\/code><\/pre>\n\n\n\n<p>The following lines align the text label. You can use the <span class=\"rnthl rntliteral\">lv_obj_align()<\/span> function. Pass as arguments, the LVGL object, the alignment and x and y offsets in pixels.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>lv_obj_align(text_label_time, LV_ALIGN_CENTER, 0, -30);<\/code><\/pre>\n\n\n\n<p>To style our text label, we\u2019ll start by creating an object of type <span class=\"rnthl rntliteral\">lv_style_t<\/span> called <span class=\"rnthl rntliteral\">style_text_label<\/span>. This kind of object is used to apply styles to LVGL objects.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>static lv_style_t style_text_label;<\/code><\/pre>\n\n\n\n<p>After creating the style, we initialize it using the <span class=\"rnthl rntliteral\">lv_style_init()<\/span> function and pass as argument our text label style (<span class=\"rnthl rntliteral\">style_text_label<\/span>).<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>lv_style_init(&amp;style_text_label);<\/code><\/pre>\n\n\n\n<p>Then, we can set the font type and size using the <span class=\"rnthl rntliteral\">lv_style_set_text_font()<\/span> function. We pass as argument the style object we\u2019re referring to and the font type. Finally, we apply the style.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>lv_style_set_text_font(&amp;style_text_label, &amp;lv_font_montserrat_48);\nlv_obj_add_style(text_label_time, &amp;style_text_label, 0);<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Date Text Label<\/h4>\n\n\n\n<p>A similar procedure is applied to create the <span class=\"rnthl rntliteral\">text_label_date<\/span>.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code> \/\/ Create a text label for the date aligned center\ntext_label_date = lv_label_create(lv_screen_active());\nlv_label_set_text(text_label_date, current_date.c_str());\nlv_obj_align(text_label_date, LV_ALIGN_CENTER, 0, 40);\n\/\/ Set font type and size\nstatic lv_style_t style_text_label2;\nlv_style_init(&amp;style_text_label2);\nlv_style_set_text_font(&amp;style_text_label2, &amp;lv_font_montserrat_30);\nlv_obj_add_style(text_label_date, &amp;style_text_label2, 0); \nlv_obj_set_style_text_color((lv_obj_t*) text_label_date, lv_palette_main(LV_PALETTE_GREY), 0);<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Timer Callback Function<\/h3>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">timer_cb<\/span> function runs every one second. Each time the callback function runs, we increment one second, every 60 seconds one minute and every 60 minutes one hour.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>static void timer_cb(lv_timer_t * timer){\n  LV_UNUSED(timer);\n  second++;\n  if(second &gt; 59) {\n    second = 0;\n    minute++;\n    if(minute &gt; 59) {\n      minute = 0;\n      hour++;\n      sync_time_date = true;\n      Serial.println(sync_time_date);\n      Serial.println(\"\\n\\n\\n\\n\\n\\n\\n\\n\");\n      if(hour &gt; 23) {\n        hour = 0;\n      }\n    }\n  }\n(...)<\/code><\/pre>\n\n\n\n<p>We use these auxiliary variable to prepare the String that will be displayed on the text labels.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>String hour_time_f = format_time(hour);\nString minute_time_f = format_time(minute);\nString second_time_f = format_time(second);\n\nString final_time_str = String(hour_time_f) + \":\" + String(minute_time_f) + \":\"  + String(second_time_f);<\/code><\/pre>\n\n\n\n<p>Set the text labels to the current time and date:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>lv_label_set_text(text_label_time, final_time_str.c_str());\nlv_label_set_text(text_label_date, current_date.c_str());<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">loop()<\/h3>\n\n\n\n<p>In the <span class=\"rnthl rntliteral\">loop()<\/span>, you can add any other tasks that you need your ESP32 to do like in any regular Arduino sketch. In our case, we will check if it&#8217;s necessary to sync the date and time with the WorldTimeAPI every hour.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>void loop() {\n  \/\/ Get the time and date from WorldTimeAPI\n  if(sync_time_date) {\n    sync_time_date = false;\n    get_date_and_time();\n    while(hour==0 &amp;&amp; minute==0 &amp;&amp; second==0) {\n      get_date_and_time();\n    }\n  }\n  lv_task_handler();   \/\/ let the GUI do its work\n  lv_tick_inc(5);         \/\/ tell LVGL how much time has passed\n  delay(5);                 \/\/ let this time pass\n}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"demonstration\">Demonstration<\/h2>\n\n\n\n<p>Upload the code to your board. Go to <strong>Tools <\/strong>&gt; <strong>Board <\/strong>and select <strong>ESP32 <\/strong>&gt; <strong>ESP32 Dev Module<\/strong>. Then, select the right COM port in <strong>Tools <\/strong>&gt; <strong>Port<\/strong>.<\/p>\n\n\n\n<p>If you see an Error like this: &#8220;Sketch too big&#8221; during the uploading process, in Arduino IDE go to <strong>Tools <\/strong>&gt; <strong>Partition scheme<\/strong> &gt; choose anything that has more than 1.4MB APP, for example: &#8220;<strong>Huge APP (3MB No OTA\/1MB SPIFFS<\/strong>&#8220;.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"768\" height=\"817\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/08\/Select-Huge-App-Partion-Scheme-Arduino-IDE-Tools-Menu.png?resize=768%2C817&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Select Huge App Partion Scheme Arduino IDE Tools Menu\" class=\"wp-image-161757\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/08\/Select-Huge-App-Partion-Scheme-Arduino-IDE-Tools-Menu.png?w=768&amp;quality=100&amp;strip=all&amp;ssl=1 768w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/08\/Select-Huge-App-Partion-Scheme-Arduino-IDE-Tools-Menu.png?resize=282%2C300&amp;quality=100&amp;strip=all&amp;ssl=1 282w\" sizes=\"(max-width: 768px) 100vw, 768px\" \/><\/figure><\/div>\n\n\n<p>Finally, click the upload button.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full is-resized\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"36\" height=\"39\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/05\/arduino-ide-2-upload-button.png?resize=36%2C39&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Arduino IDE 2 Upload Button\" class=\"wp-image-146269\" style=\"width:36px;height:auto\"\/><\/figure><\/div>\n\n\n<p>After a few seconds, the time and date will be displayed on the screen as shown in the picture below.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"750\" height=\"422\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/09\/ESP32-TFT-Screen-LVGL-Digital-Clock-Time-Date.jpg?resize=750%2C422&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 TFT Screen LVGL Digital Clock Time Date Project Demonstration\" class=\"wp-image-162139\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/09\/ESP32-TFT-Screen-LVGL-Digital-Clock-Time-Date.jpg?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/09\/ESP32-TFT-Screen-LVGL-Digital-Clock-Time-Date.jpg?resize=300%2C169&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/figure><\/div>\n\n\n<p>The ESP32 will not keep the time perfectly with its internal clock. During our tests, after one hour it usually incurs a 20 to 40 seconds delay. Every hour we make a new HTTP request to the WorldTimeAPI to sync the time and date.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Wrapping Up<\/h2>\n\n\n\n<p>In this tutorial, you learned to display date and time on a TFT with ESP32 board using the LVGL library.<\/p>\n\n\n\n<p>We hope you found this tutorial useful. We&#8217;re preparing more guides about this board, so stay tuned. If you would like to learn more about creating graphical user interfaces using the LVGL library with the ESP32, check out our latest eBook:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong><a href=\"https:\/\/randomnerdtutorials.com\/learn-lvgl-esp32-ebook\/\">Learn LVGL: Build GUIs for ESP32 Projects (eBook)<\/a><\/strong><\/li>\n<\/ul>\n\n\n\n<p>Other guides you might like reading:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/randomnerdtutorials.com\/lvgl-esp32-tft-touchscreen-display-ili9341-arduino\/\">LVGL with ESP32 TFT LCD Touchscreen Display \u2013 2.8 inch ILI9341 240\u00d7320 (Arduino IDE)<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/esp32-lvgl-ds18b20-tempreature-tft-display\/\">ESP32 with LVGL: Display DS18B20 Sensor Readings on TFT LCD (Text and Arc)<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/esp32-tft-display-image-lvgl-arduino\/\">ESP32 with TFT: Display Image using LVGL \u2013 2.8 inch ILI9341 240\u00d7320 (Arduino)<\/a><\/li>\n<\/ul>\n\n\n\n<p>To learn more about the ESP32, make sure to take a look at our resources:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/randomnerdtutorials.com\/learn-esp32-with-arduino-ide\/\">Learn ESP32 with Arduino IDE (eBook)<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/smart-home-ebook\/\" title=\"\">SMART HOME with Raspberry Pi, ESP32, and ESP8266 eBook<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/projects-esp32\/\" title=\"\"><strong>Free ESP32 Guides and Tutorials<\/strong><\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>In this guide, you&#8217;ll learn how to turn your ESP32 and a TFT display into a digital clock that displays time and date. We&#8217;ll use the LVGL (Light Versatile Graphics &#8230; <\/p>\n<p class=\"read-more-container\"><a title=\"ESP32 TFT with LVGL: Digital Clock with Time and Date\" class=\"read-more button\" href=\"https:\/\/randomnerdtutorials.com\/esp32-tft-lvgl-digital-clock\/#more-162157\" aria-label=\"Read more about ESP32 TFT with LVGL: Digital Clock with Time and Date\">CONTINUE READING \u00bb<\/a><\/p>\n","protected":false},"author":1,"featured_media":162138,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[276,281,277,299,264],"tags":[],"class_list":["post-162157","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-esp32","category-esp32-project","category-esp32-arduino-ide","category-0-esp32","category-project"],"aioseo_notices":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/09\/ESP32-TFT-Screen-LVGL-Digital-Clock-with-Time-and-Date.jpg?fit=1920%2C1080&quality=100&strip=all&ssl=1","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts\/162157","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/comments?post=162157"}],"version-history":[{"count":6,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts\/162157\/revisions"}],"predecessor-version":[{"id":162924,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts\/162157\/revisions\/162924"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/media\/162138"}],"wp:attachment":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/media?parent=162157"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/categories?post=162157"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/tags?post=162157"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}