{"id":161726,"date":"2024-09-17T16:45:57","date_gmt":"2024-09-17T16:45:57","guid":{"rendered":"https:\/\/randomnerdtutorials.com\/?p=161726"},"modified":"2024-12-09T11:57:33","modified_gmt":"2024-12-09T11:57:33","slug":"esp32-cyd-lvgl-weather-station","status":"publish","type":"post","link":"https:\/\/randomnerdtutorials.com\/esp32-cyd-lvgl-weather-station\/","title":{"rendered":"ESP32 CYD with LVGL: Weather Station (Description, Temperature, Humidity)"},"content":{"rendered":"\n<p>In this project, you&#8217;ll learn how to turn your ESP32 Cheap Yellow Display (CYD) board into a weather station that displays weather description, temperature, humidity, and date using LVGL (Light Versatile Graphics Library). We&#8217;ll use the Open-Meteo API to get the weather data and the ESP32 chip 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\/08\/ESP32-CYD-Cheap-Yellow-Display-LVGL-Weather-Station-Description-Temperature-Humidity.jpg?resize=1200%2C675&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 CYD Cheap Yellow Display LVGL Weather Station Description Temperature Humidity\" class=\"wp-image-161730\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/08\/ESP32-CYD-Cheap-Yellow-Display-LVGL-Weather-Station-Description-Temperature-Humidity.jpg?w=1920&amp;quality=100&amp;strip=all&amp;ssl=1 1920w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/08\/ESP32-CYD-Cheap-Yellow-Display-LVGL-Weather-Station-Description-Temperature-Humidity.jpg?resize=300%2C169&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/08\/ESP32-CYD-Cheap-Yellow-Display-LVGL-Weather-Station-Description-Temperature-Humidity.jpg?resize=1024%2C576&amp;quality=100&amp;strip=all&amp;ssl=1 1024w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/08\/ESP32-CYD-Cheap-Yellow-Display-LVGL-Weather-Station-Description-Temperature-Humidity.jpg?resize=768%2C432&amp;quality=100&amp;strip=all&amp;ssl=1 768w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/08\/ESP32-CYD-Cheap-Yellow-Display-LVGL-Weather-Station-Description-Temperature-Humidity.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\"><strong>New to the ESP32 Cheap Yellow Display?<\/strong> Start here: <a href=\"https:\/\/randomnerdtutorials.com\/cheap-yellow-display-esp32-2432s028r\/\">Getting Started with ESP32 Cheap Yellow Display Board \u2013 CYD (ESP32-2432S028R)<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Project Overview<\/h2>\n\n\n\n<p>We\u2019ll display the current weather description, temperature, humidity, and date on the ESP32 CYD board. The weather description will also be identified with an image.<\/p>\n\n\n\n<figure class=\"wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-1 is-layout-flex wp-block-gallery-is-layout-flex\">\n<figure class=\"wp-block-image size-large\"><img data-recalc-dims=\"1\" decoding=\"async\" width=\"750\" height=\"453\" data-id=\"161732\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/08\/ESP32-TFT-LVGL-Weather-Station-Description-Demonstration-Touchscreen-Partly-Cloudy.png?resize=750%2C453&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 TFT LVGL Weather Station Description Demonstration Touchscreen Partly Cloudy\" class=\"wp-image-161732\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/08\/ESP32-TFT-LVGL-Weather-Station-Description-Demonstration-Touchscreen-Partly-Cloudy.png?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/08\/ESP32-TFT-LVGL-Weather-Station-Description-Demonstration-Touchscreen-Partly-Cloudy.png?resize=300%2C181&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><img data-recalc-dims=\"1\" decoding=\"async\" width=\"750\" height=\"453\" data-id=\"161733\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/08\/ESP32-TFT-LVGL-Weather-Station-Description-Demonstration-Touchscreen-Clear-Sky.png?resize=750%2C453&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 TFT LVGL Weather Station Description Demonstration Touchscreen Clear Sky\" class=\"wp-image-161733\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/08\/ESP32-TFT-LVGL-Weather-Station-Description-Demonstration-Touchscreen-Clear-Sky.png?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/08\/ESP32-TFT-LVGL-Weather-Station-Description-Demonstration-Touchscreen-Clear-Sky.png?resize=300%2C181&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/figure>\n<\/figure>\n\n\n\n<p>To get an accurate weather description for your location, we\u2019ll use the free <a href=\"https:\/\/open-meteo.com\/en\/docs\" target=\"_blank\" rel=\"noopener\" title=\"\">Open-Meteo<\/a> API. To get the data 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\/cyd-cheap-yellow-display-esp32-2432s028r\/\" target=\"_blank\" rel=\"noreferrer noopener\">ESP32-2432S028R \u2013 2.8 inch 240\u00d7320 Smart Display TFT with Touchscreen<\/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\" loading=\"lazy\" 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 ESP32 Cheap Yellow Display<\/h3>\n\n\n\n<p>The&nbsp;<a href=\"https:\/\/makeradvisor.com\/tools\/cyd-cheap-yellow-display-esp32-2432s028r\/\" target=\"_blank\" rel=\"noreferrer noopener\">ESP32-2432S028R<\/a>&nbsp;development board has become known in the maker community as the \u201c<em>Cheap Yellow Display<\/em>\u201d or CYD for short. This development board, whose main chip is an ESP32-WROOM-32 module, comes with a 2.8-inch TFT touchscreen LCD, a microSD card interface, an RGB LED, and all the required circuitry to program and apply power to the board.<\/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\/ESP32-Cheap-Yellow-Display-CYD-Board-ESP32-2432S028R-front.jpg?resize=750%2C421&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 Cheap Yellow Display CYD Board ESP32-2432S028R front\" class=\"wp-image-149592\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/03\/ESP32-Cheap-Yellow-Display-CYD-Board-ESP32-2432S028R-front.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-Cheap-Yellow-Display-CYD-Board-ESP32-2432S028R-front.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 the ESP32 Cheap Yellow Display, make sure to follow our getting started guide:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/randomnerdtutorials.com\/lvgl-cheap-yellow-display-esp32-2432s028r\/\">Getting Started with ESP32 Cheap Yellow Display Board and LVGL<\/a><\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">4) 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 for the ESP32 Cheap Yellow Display using Arduino IDE.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/randomnerdtutorials.com\/lvgl-cheap-yellow-display-esp32-2432s028r\/\" title=\"\"><strong>Get started with LVGL using the ESP32 Cheap Yellow Display Board (ESP32-2432S028R)<\/strong><\/a><\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">5) 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 open-meteo API.<\/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 CYD Weather Station &#8211; <em>weather_images.h<\/em> file<\/h2>\n\n\n\n<p>To load custom images using LVGL, you need to create an extra file called <em>weather_images.h<\/em> that must be placed inside the sketch folder. We already prepared that file for you. In order to load the custom images for this weather station project, you need to download the next file.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/github.com\/RuiSantosdotme\/ESP32-TFT-Touchscreen\/raw\/refs\/heads\/main\/examples\/ESP32_LVGL_Weather_Station\/weather_images.zip\" target=\"_blank\" rel=\"noopener\" title=\"\"><strong>Click here to download the <em>weather_images.h<\/em> file<\/strong><\/a><\/li>\n<\/ul>\n\n\n\n<p><strong>Important:<\/strong> the <em>weather_images.h<\/em> file should be placed next to the <em>.ino<\/em> file in the sketch folder of your project.<\/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=\"367\" height=\"232\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/08\/LVGL-Load-Image-Arduino-Code-example-folder-weather-images-file.png?resize=367%2C232&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"LVGL Load Image Arduino Code example folder weather images file\" class=\"wp-image-161740\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/08\/LVGL-Load-Image-Arduino-Code-example-folder-weather-images-file.png?w=367&amp;quality=100&amp;strip=all&amp;ssl=1 367w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/08\/LVGL-Load-Image-Arduino-Code-example-folder-weather-images-file.png?resize=300%2C190&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 367px) 100vw, 367px\" \/><\/figure><\/div>\n\n\n<p>Your Arduino IDE should have two tabs:<\/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=\"439\" height=\"134\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/08\/Arduino-IDE-tabs-LVGL-Load-Image-Arduino-Code-example-folder-weather-images-file.png?resize=439%2C134&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Arduino IDE tabs LVGL Load Image Arduino Code example folder weather images file\" class=\"wp-image-161741\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/08\/Arduino-IDE-tabs-LVGL-Load-Image-Arduino-Code-example-folder-weather-images-file.png?w=439&amp;quality=100&amp;strip=all&amp;ssl=1 439w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/08\/Arduino-IDE-tabs-LVGL-Load-Image-Arduino-Code-example-folder-weather-images-file.png?resize=300%2C92&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 439px) 100vw, 439px\" \/><\/figure><\/div>\n\n\n<p>If you want to learn more about loading images using LVGL, we recommend reading our <a href=\"https:\/\/randomnerdtutorials.com\/esp32-cyd-lvgl-display-image\/\">Guide ESP32 CYD with LVGL: Display Image on the Screen<\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">ESP32 CYD Weather Station &#8211; Arduino Code<\/h2>\n\n\n\n<p>The following code will create some text labels with the weather description, temperature, humidity, current date, and last updated time. It will also load an image to illustrate the current weather description.<\/p>\n\n\n\n<p>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 latitude, longitude, location, and 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-weather-station\/   |    https:\/\/RandomNerdTutorials.com\/esp32-tft-lvgl-weather-station\/\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.X 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 &quot;weather_images.h&quot;\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\/\/ Replace with the latitude and longitude to where you want to get the weather\nString latitude = &quot;41.14961&quot;;\nString longitude = &quot;-8.61099&quot;;\n\/\/ Enter your location\nString location = &quot;Porto&quot;;\n\/\/ Type the timezone you want to get the time for\nString timezone = &quot;Europe\/Lisbon&quot;;\n\n\/\/ Store date and time\nString current_date;\nString last_weather_update;\nString temperature;\nString humidity;\nint is_day;\nint weather_code = 0;\nString weather_description;\n\n\/\/ SET VARIABLE TO 0 FOR TEMPERATURE IN FAHRENHEIT DEGREES\n#define TEMP_CELSIUS 1\n\n#if TEMP_CELSIUS\n  String temperature_unit = &quot;&quot;;\n  const char degree_symbol[] = &quot;\\u00B0C&quot;;\n#else\n  String temperature_unit = &quot;&amp;temperature_unit=fahrenheit&quot;;\n  const char degree_symbol[] = &quot;\\u00B0F&quot;;\n#endif\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\nstatic lv_obj_t * weather_image;\nstatic lv_obj_t * text_label_date;\nstatic lv_obj_t * text_label_temperature;\nstatic lv_obj_t * text_label_humidity;\nstatic lv_obj_t * text_label_weather_description;\nstatic lv_obj_t * text_label_time_location;\n\nstatic void timer_cb(lv_timer_t * timer){\n  LV_UNUSED(timer);\n  get_weather_data();\n  get_weather_description(weather_code);\n  lv_label_set_text(text_label_date, current_date.c_str());\n  lv_label_set_text(text_label_temperature, String(&quot;      &quot; + temperature + degree_symbol).c_str());\n  lv_label_set_text(text_label_humidity, String(&quot;   &quot; + humidity + &quot;%&quot;).c_str());\n  lv_label_set_text(text_label_weather_description, weather_description.c_str());\n  lv_label_set_text(text_label_time_location, String(&quot;Last Update: &quot; + last_weather_update + &quot;  |  &quot; + location).c_str());\n}\n\nvoid lv_create_main_gui(void) {\n  LV_IMAGE_DECLARE(image_weather_sun);\n  LV_IMAGE_DECLARE(image_weather_cloud);\n  LV_IMAGE_DECLARE(image_weather_rain);\n  LV_IMAGE_DECLARE(image_weather_thunder);\n  LV_IMAGE_DECLARE(image_weather_snow);\n  LV_IMAGE_DECLARE(image_weather_night);\n  LV_IMAGE_DECLARE(image_weather_temperature);\n  LV_IMAGE_DECLARE(image_weather_humidity);\n\n  \/\/ Get the weather data from open-meteo.com API\n  get_weather_data();\n\n  weather_image = lv_image_create(lv_screen_active());\n  lv_obj_align(weather_image, LV_ALIGN_CENTER, -80, -20);\n  \n  get_weather_description(weather_code);\n\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, 70, -70);\n  lv_obj_set_style_text_font((lv_obj_t*) text_label_date, &amp;lv_font_montserrat_26, 0);\n  lv_obj_set_style_text_color((lv_obj_t*) text_label_date, lv_palette_main(LV_PALETTE_TEAL), 0);\n\n  lv_obj_t * weather_image_temperature = lv_image_create(lv_screen_active());\n  lv_image_set_src(weather_image_temperature, &amp;image_weather_temperature);\n  lv_obj_align(weather_image_temperature, LV_ALIGN_CENTER, 30, -25);\n  text_label_temperature = lv_label_create(lv_screen_active());\n  lv_label_set_text(text_label_temperature, String(&quot;      &quot; + temperature + degree_symbol).c_str());\n  lv_obj_align(text_label_temperature, LV_ALIGN_CENTER, 70, -25);\n  lv_obj_set_style_text_font((lv_obj_t*) text_label_temperature, &amp;lv_font_montserrat_22, 0);\n\n  lv_obj_t * weather_image_humidity = lv_image_create(lv_screen_active());\n  lv_image_set_src(weather_image_humidity, &amp;image_weather_humidity);\n  lv_obj_align(weather_image_humidity, LV_ALIGN_CENTER, 30, 20);\n  text_label_humidity = lv_label_create(lv_screen_active());\n  lv_label_set_text(text_label_humidity, String(&quot;   &quot; + humidity + &quot;%&quot;).c_str());\n  lv_obj_align(text_label_humidity, LV_ALIGN_CENTER, 70, 20);\n  lv_obj_set_style_text_font((lv_obj_t*) text_label_humidity, &amp;lv_font_montserrat_22, 0);\n\n  text_label_weather_description = lv_label_create(lv_screen_active());\n  lv_label_set_text(text_label_weather_description, weather_description.c_str());\n  lv_obj_align(text_label_weather_description, LV_ALIGN_BOTTOM_MID, 0, -40);\n  lv_obj_set_style_text_font((lv_obj_t*) text_label_weather_description, &amp;lv_font_montserrat_18, 0);\n\n  \/\/ Create a text label for the time and timezone aligned center in the bottom of the screen\n  text_label_time_location = lv_label_create(lv_screen_active());\n  lv_label_set_text(text_label_time_location, String(&quot;Last Update: &quot; + last_weather_update + &quot;  |  &quot; + location).c_str());\n  lv_obj_align(text_label_time_location, LV_ALIGN_BOTTOM_MID, 0, -10);\n  lv_obj_set_style_text_font((lv_obj_t*) text_label_time_location, &amp;lv_font_montserrat_12, 0);\n  lv_obj_set_style_text_color((lv_obj_t*) text_label_time_location, lv_palette_main(LV_PALETTE_GREY), 0);\n\n  lv_timer_t * timer = lv_timer_create(timer_cb, 600000, NULL);\n  lv_timer_ready(timer);\n}\n\n\/*\n  WMO Weather interpretation codes (WW)- Code\tDescription\n  0\tClear sky\n  1, 2, 3\tMainly clear, partly cloudy, and overcast\n  45, 48\tFog and depositing rime fog\n  51, 53, 55\tDrizzle: Light, moderate, and dense intensity\n  56, 57\tFreezing Drizzle: Light and dense intensity\n  61, 63, 65\tRain: Slight, moderate and heavy intensity\n  66, 67\tFreezing Rain: Light and heavy intensity\n  71, 73, 75\tSnow fall: Slight, moderate, and heavy intensity\n  77\tSnow grains\n  80, 81, 82\tRain showers: Slight, moderate, and violent\n  85, 86\tSnow showers slight and heavy\n  95 *\tThunderstorm: Slight or moderate\n  96, 99 *\tThunderstorm with slight and heavy hail\n*\/\nvoid get_weather_description(int code) {\n  switch (code) {\n    case 0:\n      if(is_day==1) { lv_image_set_src(weather_image, &amp;image_weather_sun); }\n      else { lv_image_set_src(weather_image, &amp;image_weather_night); }\n      weather_description = &quot;CLEAR SKY&quot;;\n      break;\n    case 1: \n      if(is_day==1) { lv_image_set_src(weather_image, &amp;image_weather_sun); }\n      else { lv_image_set_src(weather_image, &amp;image_weather_night); }\n      weather_description = &quot;MAINLY CLEAR&quot;;\n      break;\n    case 2: \n      lv_image_set_src(weather_image, &amp;image_weather_cloud);\n      weather_description = &quot;PARTLY CLOUDY&quot;;\n      break;\n    case 3:\n      lv_image_set_src(weather_image, &amp;image_weather_cloud);\n      weather_description = &quot;OVERCAST&quot;;\n      break;\n    case 45:\n      lv_image_set_src(weather_image, &amp;image_weather_cloud);\n      weather_description = &quot;FOG&quot;;\n      break;\n    case 48:\n      lv_image_set_src(weather_image, &amp;image_weather_cloud);\n      weather_description = &quot;DEPOSITING RIME FOG&quot;;\n      break;\n    case 51:\n      lv_image_set_src(weather_image, &amp;image_weather_rain);\n      weather_description = &quot;DRIZZLE LIGHT INTENSITY&quot;;\n      break;\n    case 53:\n      lv_image_set_src(weather_image, &amp;image_weather_rain);\n      weather_description = &quot;DRIZZLE MODERATE INTENSITY&quot;;\n      break;\n    case 55:\n      lv_image_set_src(weather_image, &amp;image_weather_rain); \n      weather_description = &quot;DRIZZLE DENSE INTENSITY&quot;;\n      break;\n    case 56:\n      lv_image_set_src(weather_image, &amp;image_weather_rain);\n      weather_description = &quot;FREEZING DRIZZLE LIGHT&quot;;\n      break;\n    case 57:\n      lv_image_set_src(weather_image, &amp;image_weather_rain);\n      weather_description = &quot;FREEZING DRIZZLE DENSE&quot;;\n      break;\n    case 61:\n      lv_image_set_src(weather_image, &amp;image_weather_rain);\n      weather_description = &quot;RAIN SLIGHT INTENSITY&quot;;\n      break;\n    case 63:\n      lv_image_set_src(weather_image, &amp;image_weather_rain);\n      weather_description = &quot;RAIN MODERATE INTENSITY&quot;;\n      break;\n    case 65:\n      lv_image_set_src(weather_image, &amp;image_weather_rain);\n      weather_description = &quot;RAIN HEAVY INTENSITY&quot;;\n      break;\n    case 66:\n      lv_image_set_src(weather_image, &amp;image_weather_rain);\n      weather_description = &quot;FREEZING RAIN LIGHT INTENSITY&quot;;\n      break;\n    case 67:\n      lv_image_set_src(weather_image, &amp;image_weather_rain);\n      weather_description = &quot;FREEZING RAIN HEAVY INTENSITY&quot;;\n      break;\n    case 71:\n      lv_image_set_src(weather_image, &amp;image_weather_snow);\n      weather_description = &quot;SNOW FALL SLIGHT INTENSITY&quot;;\n      break;\n    case 73:\n      lv_image_set_src(weather_image, &amp;image_weather_snow);\n      weather_description = &quot;SNOW FALL MODERATE INTENSITY&quot;;\n      break;\n    case 75:\n      lv_image_set_src(weather_image, &amp;image_weather_snow);\n      weather_description = &quot;SNOW FALL HEAVY INTENSITY&quot;;\n      break;\n    case 77:\n      lv_image_set_src(weather_image, &amp;image_weather_snow);\n      weather_description = &quot;SNOW GRAINS&quot;;\n      break;\n    case 80:\n      lv_image_set_src(weather_image, &amp;image_weather_rain);\n      weather_description = &quot;RAIN SHOWERS SLIGHT&quot;;\n      break;\n    case 81:\n      lv_image_set_src(weather_image, &amp;image_weather_rain);\n      weather_description = &quot;RAIN SHOWERS MODERATE&quot;;\n      break;\n    case 82:\n      lv_image_set_src(weather_image, &amp;image_weather_rain);\n      weather_description = &quot;RAIN SHOWERS VIOLENT&quot;;\n      break;\n    case 85:\n      lv_image_set_src(weather_image, &amp;image_weather_snow);\n      weather_description = &quot;SNOW SHOWERS SLIGHT&quot;;\n      break;\n    case 86:\n      lv_image_set_src(weather_image, &amp;image_weather_snow);\n      weather_description = &quot;SNOW SHOWERS HEAVY&quot;;\n      break;\n    case 95:\n      lv_image_set_src(weather_image, &amp;image_weather_thunder);\n      weather_description = &quot;THUNDERSTORM&quot;;\n      break;\n    case 96:\n      lv_image_set_src(weather_image, &amp;image_weather_thunder);\n      weather_description = &quot;THUNDERSTORM SLIGHT HAIL&quot;;\n      break;\n    case 99:\n      lv_image_set_src(weather_image, &amp;image_weather_thunder);\n      weather_description = &quot;THUNDERSTORM HEAVY HAIL&quot;;\n      break;\n    default: \n      weather_description = &quot;UNKNOWN WEATHER CODE&quot;;\n      break;\n  }\n}\n\nvoid get_weather_data() {\n  if (WiFi.status() == WL_CONNECTED) {\n    HTTPClient http;\n    \/\/ Construct the API endpoint\n    String url = String(&quot;http:\/\/api.open-meteo.com\/v1\/forecast?latitude=&quot; + latitude + &quot;&amp;longitude=&quot; + longitude + &quot;&amp;current=temperature_2m,relative_humidity_2m,is_day,precipitation,rain,weather_code&quot; + temperature_unit + &quot;&amp;timezone=&quot; + timezone + &quot;&amp;forecast_days=1&quot;);\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;Request 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;current&quot;][&quot;time&quot;];\n          temperature = String(doc[&quot;current&quot;][&quot;temperature_2m&quot;]);\n          humidity = String(doc[&quot;current&quot;][&quot;relative_humidity_2m&quot;]);\n          is_day = String(doc[&quot;current&quot;][&quot;is_day&quot;]).toInt();\n          weather_code = String(doc[&quot;current&quot;][&quot;weather_code&quot;]).toInt();\n          \/*Serial.println(temperature);\n          Serial.println(humidity);\n          Serial.println(is_day);\n          Serial.println(weather_code);\n          Serial.println(String(timezone));*\/\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          last_weather_update = datetime_str.substring(splitIndex + 1, splitIndex + 9); \/\/ Extract time portion\n        } else {\n          Serial.print(&quot;deserializeJson() failed: &quot;);\n          Serial.println(error.c_str());\n        }\n      }\n      else {\n        Serial.println(&quot;Failed&quot;);\n      }\n    } else {\n      Serial.printf(&quot;GET request failed, error: %s\\n&quot;, http.errorToString(httpCode).c_str());\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  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_Weather_Station\/ESP32_LVGL_Weather_Station.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 current weather data from the API and update the screen 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 and Images<\/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 draw the GUI 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<p>Include the <span class=\"rnthl rntliteral\">weather_images.h<\/span> file that contains all the data to draw the weather images.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>#include \"weather_images.h\"<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Insert Your Details<\/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 <span class=\"rnthl rntliteral\">latitude<\/span>, <span class=\"rnthl rntliteral\">longitude<\/span> and <span class=\"rnthl rntliteral\">location<\/span> in these three variables:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>String latitude = \"\";\nString longitude = \"\";\nString location = \"\";    \/\/ Example: Porto<\/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=\"https:\/\/en.wikipedia.org\/wiki\/List_of_tz_database_time_zones\" target=\"_blank\" rel=\"noopener\" title=\"\">timezones<\/a>).<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>const char* timezone = \"REPLACE_WITH_YOUR_TIMEZONE\";    \/\/ Example: 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 weather data and other values.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>String current_date;\nString last_weather_update;\nString temperature;\nString humidity;\nint is_day;\nint weather_code = 0;\nString weather_description;<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Temperature in Celsius or Fahrenheit<\/h3>\n\n\n\n<p>By default, we\u2019ll display the temperature values in Celsius degrees. If you want to display the temperature readings in Fahrenheit degrees, change <span class=\"rnthl rntliteral\">TEMP_CELSIUS<\/span> variable to <span class=\"rnthl rntliteral\">0<\/span>.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/ SET VARIABLE TO 0 FOR TEMPERATURE IN FAHRENHEIT DEGREES\n#define TEMP_CELSIUS 1\n\n#if TEMP_CELSIUS\n  String temperature_unit = \"\";\n  const char degree_symbol&#091;] = \"\\u00B0C\";\n#else\n  String temperature_unit = \"&amp;temperature_unit=fahrenheit\";\n  const char degree_symbol&#091;] = \"\\u00B0F\";\n#endif<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Global LVGL Objects<\/h3>\n\n\n\n<p>We create some global LVGL 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 * weather_image;\nstatic lv_obj_t * text_label_date;\nstatic lv_obj_t * text_label_temperature;\nstatic lv_obj_t * text_label_humidity;\nstatic lv_obj_t * text_label_weather_description;\nstatic lv_obj_t * text_label_time_location;<\/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_weather_data()<\/h3>\n\n\n\n<p>When we initialize the screen, we call the <span class=\"rnthl rntliteral\">get_weather_data()<\/span> function to get the latest weather data from the Open-Meteo API. 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_weather_data() {\n  if (WiFi.status() == WL_CONNECTED) {\n    HTTPClient http;\n    \/\/ Construct the API endpoint\n    String url = String(\"http:\/\/api.open-meteo.com\/v1\/forecast?latitude=\" + latitude + \"&amp;longitude=\" + longitude + \"&amp;current=temperature_2m,relative_humidity_2m,is_day,precipitation,rain,weather_code\" + temperature_unit + \"&amp;timezone=\" + timezone + \"&amp;forecast_days=1\");\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(\"Request 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;\"current\"]&#091;\"time\"];\n          temperature = String(doc&#091;\"current\"]&#091;\"temperature_2m\"]);\n          humidity = String(doc&#091;\"current\"]&#091;\"relative_humidity_2m\"]);\n          is_day = String(doc&#091;\"current\"]&#091;\"is_day\"]).toInt();\n          weather_code = String(doc&#091;\"current\"]&#091;\"weather_code\"]).toInt();\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          last_weather_update = datetime_str.substring(splitIndex + 1, splitIndex + 9); \/\/ Extract time portion\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    }\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\">get_weather_description(int code)<\/h3>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">get_weather_description()<\/span> function receives the weather code from the Open-Meteo API and it assigns the correct weather description and corresponding image to illustrate the current weather.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>void get_weather_description(int code) {\n  switch (code) {\n    case 0:\n      if(is_day==1) { lv_image_set_src(weather_image, &amp;image_weather_sun); }\n      else { lv_image_set_src(weather_image, &amp;image_weather_night); }\n      weather_description = \"CLEAR SKY\";\n      break;\n    case 1: \n      if(is_day==1) { lv_image_set_src(weather_image, &amp;image_weather_sun); }\n      else { lv_image_set_src(weather_image, &amp;image_weather_night); }\n      weather_description = \"MAINLY CLEAR\";\n      break;\n    case 2: \n      lv_image_set_src(weather_image, &amp;image_weather_cloud);\n      weather_description = \"PARTLY CLOUDY\";\n      break;\n    case 3:\n      lv_image_set_src(weather_image, &amp;image_weather_cloud);\n      weather_description = \"OVERCAST\";\n      break;\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 declaring all the images to illustrate the weather description.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>void lv_create_main_gui(void) {\n  LV_IMAGE_DECLARE(image_weather_sun);\n  LV_IMAGE_DECLARE(image_weather_cloud);\n  LV_IMAGE_DECLARE(image_weather_rain);\n  LV_IMAGE_DECLARE(image_weather_thunder);\n  LV_IMAGE_DECLARE(image_weather_snow);\n  LV_IMAGE_DECLARE(image_weather_night);\n  LV_IMAGE_DECLARE(image_weather_temperature);\n  LV_IMAGE_DECLARE(image_weather_humidity);\n(...)<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Get the latest weather data<\/h4>\n\n\n\n<p>Then, we call the weather API to get the latest data and store the values in the auxiliary variables.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>get_weather_data();<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Load the weather image<\/h4>\n\n\n\n<p>We create an image and set it to the left side of the display.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>weather_image = lv_image_create(lv_screen_active());\nlv_obj_align(weather_image, LV_ALIGN_CENTER, -80, -20);\n  \nget_weather_description(weather_code);<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Text Labels<\/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>text_label_date = 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 the current date.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>lv_label_set_text(text_label_date, current_date.c_str());<\/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_date, LV_ALIGN_CENTER, 70, -70);<\/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.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>lv_obj_set_style_text_font((lv_obj_t*) text_label_date, &amp;lv_font_montserrat_26, 0);<\/code><\/pre>\n\n\n\n<p>For the <span class=\"rnthl rntliteral\">text_label_date<\/span> we&#8217;re also setting a custom text teal color:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>lv_obj_set_style_text_color((lv_obj_t*) text_label_date, lv_palette_main(LV_PALETTE_TEAL), 0);<\/code><\/pre>\n\n\n\n<p>A similar procedure is applied to all other labels (temperature, humidity, description, time, and location).<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>lv_obj_t * weather_image_temperature = lv_image_create(lv_screen_active());\nlv_image_set_src(weather_image_temperature, &amp;image_weather_temperature);\nlv_obj_align(weather_image_temperature, LV_ALIGN_CENTER, 30, -25);\ntext_label_temperature = lv_label_create(lv_screen_active());\nlv_label_set_text(text_label_temperature, String(\"      \" + temperature + degree_symbol).c_str());\nlv_obj_align(text_label_temperature, LV_ALIGN_CENTER, 70, -25);\nlv_obj_set_style_text_font((lv_obj_t*) text_label_temperature, &amp;lv_font_montserrat_22, 0);\n\nlv_obj_t * weather_image_humidity = lv_image_create(lv_screen_active());\nlv_image_set_src(weather_image_humidity, &amp;image_weather_humidity);\nlv_obj_align(weather_image_humidity, LV_ALIGN_CENTER, 30, 20);\ntext_label_humidity = lv_label_create(lv_screen_active());\nlv_label_set_text(text_label_humidity, String(\"   \" + humidity + \"%\").c_str());\nlv_obj_align(text_label_humidity, LV_ALIGN_CENTER, 70, 20);\nlv_obj_set_style_text_font((lv_obj_t*) text_label_humidity, &amp;lv_font_montserrat_22, 0);\n\ntext_label_weather_description = lv_label_create(lv_screen_active());\nlv_label_set_text(text_label_weather_description, weather_description.c_str());\nlv_obj_align(text_label_weather_description, LV_ALIGN_BOTTOM_MID, 0, -40);\nlv_obj_set_style_text_font((lv_obj_t*) text_label_weather_description, &amp;lv_font_montserrat_18, 0);\n\n\/\/ Create a text label for the time and timezone aligned center in the bottom of the screen\ntext_label_time_location = lv_label_create(lv_screen_active());\nlv_label_set_text(text_label_time_location, String(\"Last Update: \" + last_weather_update + \"  |  \" + location).c_str());\nlv_obj_align(text_label_time_location, LV_ALIGN_BOTTOM_MID, 0, -10);\nlv_obj_set_style_text_font((lv_obj_t*) text_label_time_location, &amp;lv_font_montserrat_12, 0);\nlv_obj_set_style_text_color((lv_obj_t*) text_label_time_location, lv_palette_main(LV_PALETTE_GREY), 0);<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Timer<\/h4>\n\n\n\n<p>To update the data on the screen, we can create an LVGL timer that will run a specific function periodically. In this case, we\u2019ll update it every 10 minutes. 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, 600000, NULL);\nlv_timer_ready(timer);;<\/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 10 minutes. Each time the callback function runs, we get the latest weather data from the API and update the GUI.<\/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  get_weather_data();\n  get_weather_description(weather_code);\n  \n(...)<\/code><\/pre>\n\n\n\n<p>Finally, we set all the text labels to the current data returned from the API:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>lv_label_set_text(text_label_date, current_date.c_str());\nlv_label_set_text(text_label_temperature, String(\"      \" + temperature + degree_symbol).c_str());\nlv_label_set_text(text_label_humidity, String(\"   \" + humidity + \"%\").c_str());\nlv_label_set_text(text_label_weather_description, weather_description.c_str());\nlv_label_set_text(text_label_time_location, String(\"Last Update: \" + last_weather_update + \"  |  \" + location).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 won\u2019t add any tasks to the <span class=\"rnthl rntliteral\">loop()<\/span>, but to keep LVGL running and detecting events, you always need to add the following lines to your <span class=\"rnthl rntliteral\">loop()<\/span>.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>void loop() {\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 weather info 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=\"424\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/08\/ESP32-CYD-Cheap-Yellow-Display-LVGL-Weather-Station-Description-Temperature-Humidity-Demonstration-Screen.jpg?resize=750%2C424&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 CYD Cheap Yellow Display LVGL Weather Station Description Temperature Humidity Demonstration Screen\" class=\"wp-image-161731\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/08\/ESP32-CYD-Cheap-Yellow-Display-LVGL-Weather-Station-Description-Temperature-Humidity-Demonstration-Screen.jpg?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/08\/ESP32-CYD-Cheap-Yellow-Display-LVGL-Weather-Station-Description-Temperature-Humidity-Demonstration-Screen.jpg?resize=300%2C170&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/figure><\/div>\n\n\n<h2 class=\"wp-block-heading\">Wrapping Up<\/h2>\n\n\n\n<p>In this tutorial, you&#8217;ve created a simple weather station with your Cheap Yellow Display (CYD) 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\/cheap-yellow-display-esp32-2432s028r\/\">Getting Started with ESP32 Cheap Yellow Display Board \u2013 CYD (ESP32-2432S028R)<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/touchscreen-on-off-button-cheap-yellow-display-esp32-2432s028r\/\">ESP32 Touchscreen On\/Off Button \u2013 Cheap Yellow Display (ESP32-2432S028R)<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/esp32-cheap-yellow-display-cyd-pinout-esp32-2432s028r\/\">ESP32 Cheap Yellow Display (CYD) Pinout (ESP32-2432S028R)<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/lvgl-cheap-yellow-display-esp32-2432s028r\/\">LVGL with ESP32 Cheap Yellow Display Board (ESP32-2432S028R)<\/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 project, you&#8217;ll learn how to turn your ESP32 Cheap Yellow Display (CYD) board into a weather station that displays weather description, temperature, humidity, and date using LVGL (Light &#8230; <\/p>\n<p class=\"read-more-container\"><a title=\"ESP32 CYD with LVGL: Weather Station (Description, Temperature, Humidity)\" class=\"read-more button\" href=\"https:\/\/randomnerdtutorials.com\/esp32-cyd-lvgl-weather-station\/#more-161726\" aria-label=\"Read more about ESP32 CYD with LVGL: Weather Station (Description, Temperature, Humidity)\">CONTINUE READING \u00bb<\/a><\/p>\n","protected":false},"author":1,"featured_media":161730,"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":[281,276,277,299,264],"tags":[],"class_list":["post-161726","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-esp32-project","category-esp32","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\/08\/ESP32-CYD-Cheap-Yellow-Display-LVGL-Weather-Station-Description-Temperature-Humidity.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\/161726","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=161726"}],"version-history":[{"count":19,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts\/161726\/revisions"}],"predecessor-version":[{"id":164478,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts\/161726\/revisions\/164478"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/media\/161730"}],"wp:attachment":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/media?parent=161726"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/categories?post=161726"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/tags?post=161726"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}