In this project, you’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’ll use the Open-Meteo API to get the weather data and the ESP32 chip will be programmed using Arduino IDE.

New to the ESP32 Cheap Yellow Display? Start here: Getting Started with ESP32 Cheap Yellow Display Board – CYD (ESP32-2432S028R).
Project Overview
We’ll display the current weather description, temperature, humidity, and date on the ESP32 CYD board. The weather description will also be identified with an image.


To get an accurate weather description for your location, we’ll use the free Open-Meteo 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.
Prerequisites
Before proceeding, make sure you follow the next prerequisites. You must follow all steps, otherwise, your project will not work.
1) Parts Required
For this project, you need the following parts
2) Install ESP32 Boards in Arduino IDE

We’ll program the ESP32 using Arduino IDE. Make sure you have the ESP32 boards installed. Follow the next tutorial:
3) Get familiar with the ESP32 Cheap Yellow Display
The ESP32-2432S028R development board has become known in the maker community as the “Cheap Yellow Display” 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.

If this is your first time using the ESP32 Cheap Yellow Display, make sure to follow our getting started guide:
4) Install TFT and LVGL Libraries
LVGL (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).

Follow the next tutorial to install and configure the required libraries to use LVGL for the ESP32 Cheap Yellow Display using Arduino IDE.
5) Install ArduinoJson Library
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.
In the Arduino IDE, go to Sketch > Include Library > Manage Libraries. Search for ArduinoJSON and install the library by Benoit Blanchon. We’re using version 7.0.4. We recommend using the same version.

ESP32 CYD Weather Station – weather_images.h file
To load custom images using LVGL, you need to create an extra file called weather_images.h 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.
Important: the weather_images.h file should be placed next to the .ino file in the sketch folder of your project.

Your Arduino IDE should have two tabs:

If you want to learn more about loading images using LVGL, we recommend reading our Guide ESP32 CYD with LVGL: Display Image on the Screen
ESP32 CYD Weather Station – Arduino Code
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.
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.
/* Rui Santos & Sara Santos - Random Nerd Tutorials - https://RandomNerdTutorials.com/esp32-cyd-lvgl-weather-station/ | https://RandomNerdTutorials.com/esp32-tft-lvgl-weather-station/
THIS EXAMPLE WAS TESTED WITH THE FOLLOWING HARDWARE:
1) ESP32-2432S028R 2.8 inch 240Ă—320 also known as the Cheap Yellow Display (CYD): https://makeradvisor.com/tools/cyd-cheap-yellow-display-esp32-2432s028r/
SET UP INSTRUCTIONS: https://RandomNerdTutorials.com/cyd-lvgl/
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/
SET UP INSTRUCTIONS: https://RandomNerdTutorials.com/esp32-tft-lvgl/
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files.
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*/
/* Install the "lvgl" library version 9.X by kisvegabor to interface with the TFT Display - https://lvgl.io/
*** IMPORTANT: lv_conf.h available on the internet will probably NOT work with the examples available at Random Nerd Tutorials ***
*** YOU MUST USE THE lv_conf.h FILE PROVIDED IN THE LINK BELOW IN ORDER TO USE THE EXAMPLES FROM RANDOM NERD TUTORIALS ***
FULL INSTRUCTIONS AVAILABLE ON HOW CONFIGURE THE LIBRARY: https://RandomNerdTutorials.com/cyd-lvgl/ or https://RandomNerdTutorials.com/esp32-tft-lvgl/ */
#include <lvgl.h>
/* Install the "TFT_eSPI" library by Bodmer to interface with the TFT Display - https://github.com/Bodmer/TFT_eSPI
*** IMPORTANT: User_Setup.h available on the internet will probably NOT work with the examples available at Random Nerd Tutorials ***
*** YOU MUST USE THE User_Setup.h FILE PROVIDED IN THE LINK BELOW IN ORDER TO USE THE EXAMPLES FROM RANDOM NERD TUTORIALS ***
FULL INSTRUCTIONS AVAILABLE ON HOW CONFIGURE THE LIBRARY: https://RandomNerdTutorials.com/cyd-lvgl/ or https://RandomNerdTutorials.com/esp32-tft-lvgl/ */
#include <TFT_eSPI.h>
#include "weather_images.h"
#include <WiFi.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>
// Replace with your network credentials
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
// Replace with the latitude and longitude to where you want to get the weather
String latitude = "41.14961";
String longitude = "-8.61099";
// Enter your location
String location = "Porto";
// Type the timezone you want to get the time for
String timezone = "Europe/Lisbon";
// Store date and time
String current_date;
String last_weather_update;
String temperature;
String humidity;
int is_day;
int weather_code = 0;
String weather_description;
// SET VARIABLE TO 0 FOR TEMPERATURE IN FAHRENHEIT DEGREES
#define TEMP_CELSIUS 1
#if TEMP_CELSIUS
String temperature_unit = "";
const char degree_symbol[] = "\u00B0C";
#else
String temperature_unit = "&temperature_unit=fahrenheit";
const char degree_symbol[] = "\u00B0F";
#endif
#define SCREEN_WIDTH 240
#define SCREEN_HEIGHT 320
#define DRAW_BUF_SIZE (SCREEN_WIDTH * SCREEN_HEIGHT / 10 * (LV_COLOR_DEPTH / 8))
uint32_t draw_buf[DRAW_BUF_SIZE / 4];
// If logging is enabled, it will inform the user about what is happening in the library
void log_print(lv_log_level_t level, const char * buf) {
LV_UNUSED(level);
Serial.println(buf);
Serial.flush();
}
static lv_obj_t * weather_image;
static lv_obj_t * text_label_date;
static lv_obj_t * text_label_temperature;
static lv_obj_t * text_label_humidity;
static lv_obj_t * text_label_weather_description;
static lv_obj_t * text_label_time_location;
static void timer_cb(lv_timer_t * timer){
LV_UNUSED(timer);
get_weather_data();
get_weather_description(weather_code);
lv_label_set_text(text_label_date, current_date.c_str());
lv_label_set_text(text_label_temperature, String(" " + temperature + degree_symbol).c_str());
lv_label_set_text(text_label_humidity, String(" " + humidity + "%").c_str());
lv_label_set_text(text_label_weather_description, weather_description.c_str());
lv_label_set_text(text_label_time_location, String("Last Update: " + last_weather_update + " | " + location).c_str());
}
void lv_create_main_gui(void) {
LV_IMAGE_DECLARE(image_weather_sun);
LV_IMAGE_DECLARE(image_weather_cloud);
LV_IMAGE_DECLARE(image_weather_rain);
LV_IMAGE_DECLARE(image_weather_thunder);
LV_IMAGE_DECLARE(image_weather_snow);
LV_IMAGE_DECLARE(image_weather_night);
LV_IMAGE_DECLARE(image_weather_temperature);
LV_IMAGE_DECLARE(image_weather_humidity);
// Get the weather data from open-meteo.com API
get_weather_data();
weather_image = lv_image_create(lv_screen_active());
lv_obj_align(weather_image, LV_ALIGN_CENTER, -80, -20);
get_weather_description(weather_code);
text_label_date = lv_label_create(lv_screen_active());
lv_label_set_text(text_label_date, current_date.c_str());
lv_obj_align(text_label_date, LV_ALIGN_CENTER, 70, -70);
lv_obj_set_style_text_font((lv_obj_t*) text_label_date, &lv_font_montserrat_26, 0);
lv_obj_set_style_text_color((lv_obj_t*) text_label_date, lv_palette_main(LV_PALETTE_TEAL), 0);
lv_obj_t * weather_image_temperature = lv_image_create(lv_screen_active());
lv_image_set_src(weather_image_temperature, &image_weather_temperature);
lv_obj_align(weather_image_temperature, LV_ALIGN_CENTER, 30, -25);
text_label_temperature = lv_label_create(lv_screen_active());
lv_label_set_text(text_label_temperature, String(" " + temperature + degree_symbol).c_str());
lv_obj_align(text_label_temperature, LV_ALIGN_CENTER, 70, -25);
lv_obj_set_style_text_font((lv_obj_t*) text_label_temperature, &lv_font_montserrat_22, 0);
lv_obj_t * weather_image_humidity = lv_image_create(lv_screen_active());
lv_image_set_src(weather_image_humidity, &image_weather_humidity);
lv_obj_align(weather_image_humidity, LV_ALIGN_CENTER, 30, 20);
text_label_humidity = lv_label_create(lv_screen_active());
lv_label_set_text(text_label_humidity, String(" " + humidity + "%").c_str());
lv_obj_align(text_label_humidity, LV_ALIGN_CENTER, 70, 20);
lv_obj_set_style_text_font((lv_obj_t*) text_label_humidity, &lv_font_montserrat_22, 0);
text_label_weather_description = lv_label_create(lv_screen_active());
lv_label_set_text(text_label_weather_description, weather_description.c_str());
lv_obj_align(text_label_weather_description, LV_ALIGN_BOTTOM_MID, 0, -40);
lv_obj_set_style_text_font((lv_obj_t*) text_label_weather_description, &lv_font_montserrat_18, 0);
// Create a text label for the time and timezone aligned center in the bottom of the screen
text_label_time_location = lv_label_create(lv_screen_active());
lv_label_set_text(text_label_time_location, String("Last Update: " + last_weather_update + " | " + location).c_str());
lv_obj_align(text_label_time_location, LV_ALIGN_BOTTOM_MID, 0, -10);
lv_obj_set_style_text_font((lv_obj_t*) text_label_time_location, &lv_font_montserrat_12, 0);
lv_obj_set_style_text_color((lv_obj_t*) text_label_time_location, lv_palette_main(LV_PALETTE_GREY), 0);
lv_timer_t * timer = lv_timer_create(timer_cb, 600000, NULL);
lv_timer_ready(timer);
}
/*
WMO Weather interpretation codes (WW)- Code Description
0 Clear sky
1, 2, 3 Mainly clear, partly cloudy, and overcast
45, 48 Fog and depositing rime fog
51, 53, 55 Drizzle: Light, moderate, and dense intensity
56, 57 Freezing Drizzle: Light and dense intensity
61, 63, 65 Rain: Slight, moderate and heavy intensity
66, 67 Freezing Rain: Light and heavy intensity
71, 73, 75 Snow fall: Slight, moderate, and heavy intensity
77 Snow grains
80, 81, 82 Rain showers: Slight, moderate, and violent
85, 86 Snow showers slight and heavy
95 * Thunderstorm: Slight or moderate
96, 99 * Thunderstorm with slight and heavy hail
*/
void get_weather_description(int code) {
switch (code) {
case 0:
if(is_day==1) { lv_image_set_src(weather_image, &image_weather_sun); }
else { lv_image_set_src(weather_image, &image_weather_night); }
weather_description = "CLEAR SKY";
break;
case 1:
if(is_day==1) { lv_image_set_src(weather_image, &image_weather_sun); }
else { lv_image_set_src(weather_image, &image_weather_night); }
weather_description = "MAINLY CLEAR";
break;
case 2:
lv_image_set_src(weather_image, &image_weather_cloud);
weather_description = "PARTLY CLOUDY";
break;
case 3:
lv_image_set_src(weather_image, &image_weather_cloud);
weather_description = "OVERCAST";
break;
case 45:
lv_image_set_src(weather_image, &image_weather_cloud);
weather_description = "FOG";
break;
case 48:
lv_image_set_src(weather_image, &image_weather_cloud);
weather_description = "DEPOSITING RIME FOG";
break;
case 51:
lv_image_set_src(weather_image, &image_weather_rain);
weather_description = "DRIZZLE LIGHT INTENSITY";
break;
case 53:
lv_image_set_src(weather_image, &image_weather_rain);
weather_description = "DRIZZLE MODERATE INTENSITY";
break;
case 55:
lv_image_set_src(weather_image, &image_weather_rain);
weather_description = "DRIZZLE DENSE INTENSITY";
break;
case 56:
lv_image_set_src(weather_image, &image_weather_rain);
weather_description = "FREEZING DRIZZLE LIGHT";
break;
case 57:
lv_image_set_src(weather_image, &image_weather_rain);
weather_description = "FREEZING DRIZZLE DENSE";
break;
case 61:
lv_image_set_src(weather_image, &image_weather_rain);
weather_description = "RAIN SLIGHT INTENSITY";
break;
case 63:
lv_image_set_src(weather_image, &image_weather_rain);
weather_description = "RAIN MODERATE INTENSITY";
break;
case 65:
lv_image_set_src(weather_image, &image_weather_rain);
weather_description = "RAIN HEAVY INTENSITY";
break;
case 66:
lv_image_set_src(weather_image, &image_weather_rain);
weather_description = "FREEZING RAIN LIGHT INTENSITY";
break;
case 67:
lv_image_set_src(weather_image, &image_weather_rain);
weather_description = "FREEZING RAIN HEAVY INTENSITY";
break;
case 71:
lv_image_set_src(weather_image, &image_weather_snow);
weather_description = "SNOW FALL SLIGHT INTENSITY";
break;
case 73:
lv_image_set_src(weather_image, &image_weather_snow);
weather_description = "SNOW FALL MODERATE INTENSITY";
break;
case 75:
lv_image_set_src(weather_image, &image_weather_snow);
weather_description = "SNOW FALL HEAVY INTENSITY";
break;
case 77:
lv_image_set_src(weather_image, &image_weather_snow);
weather_description = "SNOW GRAINS";
break;
case 80:
lv_image_set_src(weather_image, &image_weather_rain);
weather_description = "RAIN SHOWERS SLIGHT";
break;
case 81:
lv_image_set_src(weather_image, &image_weather_rain);
weather_description = "RAIN SHOWERS MODERATE";
break;
case 82:
lv_image_set_src(weather_image, &image_weather_rain);
weather_description = "RAIN SHOWERS VIOLENT";
break;
case 85:
lv_image_set_src(weather_image, &image_weather_snow);
weather_description = "SNOW SHOWERS SLIGHT";
break;
case 86:
lv_image_set_src(weather_image, &image_weather_snow);
weather_description = "SNOW SHOWERS HEAVY";
break;
case 95:
lv_image_set_src(weather_image, &image_weather_thunder);
weather_description = "THUNDERSTORM";
break;
case 96:
lv_image_set_src(weather_image, &image_weather_thunder);
weather_description = "THUNDERSTORM SLIGHT HAIL";
break;
case 99:
lv_image_set_src(weather_image, &image_weather_thunder);
weather_description = "THUNDERSTORM HEAVY HAIL";
break;
default:
weather_description = "UNKNOWN WEATHER CODE";
break;
}
}
void get_weather_data() {
if (WiFi.status() == WL_CONNECTED) {
HTTPClient http;
// Construct the API endpoint
String url = String("http://api.open-meteo.com/v1/forecast?latitude=" + latitude + "&longitude=" + longitude + "¤t=temperature_2m,relative_humidity_2m,is_day,precipitation,rain,weather_code" + temperature_unit + "&timezone=" + timezone + "&forecast_days=1");
http.begin(url);
int httpCode = http.GET(); // Make the GET request
if (httpCode > 0) {
// Check for the response
if (httpCode == HTTP_CODE_OK) {
String payload = http.getString();
//Serial.println("Request information:");
//Serial.println(payload);
// Parse the JSON to extract the time
JsonDocument doc;
DeserializationError error = deserializeJson(doc, payload);
if (!error) {
const char* datetime = doc["current"]["time"];
temperature = String(doc["current"]["temperature_2m"]);
humidity = String(doc["current"]["relative_humidity_2m"]);
is_day = String(doc["current"]["is_day"]).toInt();
weather_code = String(doc["current"]["weather_code"]).toInt();
/*Serial.println(temperature);
Serial.println(humidity);
Serial.println(is_day);
Serial.println(weather_code);
Serial.println(String(timezone));*/
// Split the datetime into date and time
String datetime_str = String(datetime);
int splitIndex = datetime_str.indexOf('T');
current_date = datetime_str.substring(0, splitIndex);
last_weather_update = datetime_str.substring(splitIndex + 1, splitIndex + 9); // Extract time portion
} else {
Serial.print("deserializeJson() failed: ");
Serial.println(error.c_str());
}
}
else {
Serial.println("Failed");
}
} else {
Serial.printf("GET request failed, error: %s\n", http.errorToString(httpCode).c_str());
}
http.end(); // Close connection
} else {
Serial.println("Not connected to Wi-Fi");
}
}
void setup() {
String LVGL_Arduino = String("LVGL Library Version: ") + lv_version_major() + "." + lv_version_minor() + "." + lv_version_patch();
Serial.begin(115200);
Serial.println(LVGL_Arduino);
// Connect to Wi-Fi
WiFi.begin(ssid, password);
Serial.print("Connecting");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.print("\nConnected to Wi-Fi network with IP Address: ");
Serial.println(WiFi.localIP());
// Start LVGL
lv_init();
// Register print function for debugging
lv_log_register_print_cb(log_print);
// Create a display object
lv_display_t * disp;
// Initialize the TFT display using the TFT_eSPI library
disp = lv_tft_espi_create(SCREEN_WIDTH, SCREEN_HEIGHT, draw_buf, sizeof(draw_buf));
lv_display_set_rotation(disp, LV_DISPLAY_ROTATION_270);
// Function to draw the GUI
lv_create_main_gui();
}
void loop() {
lv_task_handler(); // let the GUI do its work
lv_tick_inc(5); // tell LVGL how much time has passed
delay(5); // let this time pass
}
How Does the Code Work?
Let’s 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 Demonstration section.
Including Libraries and Images
You need to include the lvgl.h and the TFT_eSPI.h libraries to draw the GUI on the screen.
#include <lvgl.h>
#include <TFT_eSPI.h>
You need to include the WiFi, HTTPClient, and the ArduinoJson libraries to make HTTP requests and handle JSON data.
#include <WiFi.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>
Include the weather_images.h file that contains all the data to draw the weather images.
#include "weather_images.h"
Insert Your Details
In the following lines, you must insert your network credentials so that the ESP32 can connect to your router.
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
Set your latitude, longitude and location in these three variables:
String latitude = "";
String longitude = "";
String location = ""; // Example: Porto
Set your timezone in the timezone variable at the beginning of the code (list of all available timezones).
const char* timezone = "REPLACE_WITH_YOUR_TIMEZONE"; // Example: Europe/Lisbon
Declaring Other Variables
Create some auxiliary variables to hold the weather data and other values.
String current_date;
String last_weather_update;
String temperature;
String humidity;
int is_day;
int weather_code = 0;
String weather_description;
Temperature in Celsius or Fahrenheit
By default, we’ll display the temperature values in Celsius degrees. If you want to display the temperature readings in Fahrenheit degrees, change TEMP_CELSIUS variable to 0.
// SET VARIABLE TO 0 FOR TEMPERATURE IN FAHRENHEIT DEGREES
#define TEMP_CELSIUS 1
#if TEMP_CELSIUS
String temperature_unit = "";
const char degree_symbol[] = "\u00B0C";
#else
String temperature_unit = "&temperature_unit=fahrenheit";
const char degree_symbol[] = "\u00B0F";
#endif
Global LVGL Objects
We create some global LVGL objects, so that we can access them inside all functions later on.
static lv_obj_t * weather_image;
static lv_obj_t * text_label_date;
static lv_obj_t * text_label_temperature;
static lv_obj_t * text_label_humidity;
static lv_obj_t * text_label_weather_description;
static lv_obj_t * text_label_time_location;
setup()
In the setup(), include the following lines for debugging. These will print the version of LVGL that you’re using. You must be using version 9.
String LVGL_Arduino = String("LVGL Library Version: ") + lv_version_major() + "." + lv_version_minor() + "." + lv_version_patch();
Serial.begin(115200);
Serial.println(LVGL_Arduino);
Connect to the Internet
To connect the ESP32 to the internet we use the following code.
// Connect to Wi-Fi
WiFi.begin(ssid, password);
Serial.print("Connecting");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.print("\nConnected to Wi-Fi network with IP Address: ");
Serial.println(WiFi.localIP());
Initialize the LVGL Library
Initialize the LVGL Library by calling the lv_init() function in the setup().
// Start LVGL
lv_init();
Register Debugging Function
Register your log_print() function declared previously as a function associated with debugging LVGL.
// Register print function for debugging
lv_log_register_print_cb(log_print);
Create a Display Object
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 disp with the screen width, screen height, and drawing buffer defined earlier.
// Create a display object
lv_display_t * disp;
// Initialize the TFT display using the TFT_eSPI library
disp = lv_tft_espi_create(SCREEN_WIDTH, SCREEN_HEIGHT, draw_buf, sizeof(draw_buf));
lv_display_set_rotation(disp, LV_DISPLAY_ROTATION_270);
Drawing the GUI
The LVGL library works asynchronously. You must call the function to draw on the display in the setup(). 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’t need to check for any events in the loop().
Throughout most of our examples, the function that will draw to the screen will be called lv_create_main_gui(). Then, inside that function, we’ll add the instructions to build the interface.
// Function to draw the GUI
lv_create_main_gui();
get_weather_data()
When we initialize the screen, we call the get_weather_data() 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.
void get_weather_data() {
if (WiFi.status() == WL_CONNECTED) {
HTTPClient http;
// Construct the API endpoint
String url = String("http://api.open-meteo.com/v1/forecast?latitude=" + latitude + "&longitude=" + longitude + "¤t=temperature_2m,relative_humidity_2m,is_day,precipitation,rain,weather_code" + temperature_unit + "&timezone=" + timezone + "&forecast_days=1");
http.begin(url);
int httpCode = http.GET(); // Make the GET request
if (httpCode > 0) {
// Check for the response
if (httpCode == HTTP_CODE_OK) {
String payload = http.getString();
//Serial.println("Request information:");
//Serial.println(payload);
// Parse the JSON to extract the time
JsonDocument doc;
DeserializationError error = deserializeJson(doc, payload);
if (!error) {
const char* datetime = doc["current"]["time"];
temperature = String(doc["current"]["temperature_2m"]);
humidity = String(doc["current"]["relative_humidity_2m"]);
is_day = String(doc["current"]["is_day"]).toInt();
weather_code = String(doc["current"]["weather_code"]).toInt();
// Split the datetime into date and time
String datetime_str = String(datetime);
int splitIndex = datetime_str.indexOf('T');
current_date = datetime_str.substring(0, splitIndex);
last_weather_update = datetime_str.substring(splitIndex + 1, splitIndex + 9); // Extract time portion
} else {
Serial.print("deserializeJson() failed: ");
Serial.println(error.c_str());
}
}
} else {
Serial.printf("GET request failed, error: %s\n", http.errorToString(httpCode).c_str());
}
http.end(); // Close connection
} else {
Serial.println("Not connected to Wi-Fi");
}
}
get_weather_description(int code)
The get_weather_description() 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.
void get_weather_description(int code) {
switch (code) {
case 0:
if(is_day==1) { lv_image_set_src(weather_image, &image_weather_sun); }
else { lv_image_set_src(weather_image, &image_weather_night); }
weather_description = "CLEAR SKY";
break;
case 1:
if(is_day==1) { lv_image_set_src(weather_image, &image_weather_sun); }
else { lv_image_set_src(weather_image, &image_weather_night); }
weather_description = "MAINLY CLEAR";
break;
case 2:
lv_image_set_src(weather_image, &image_weather_cloud);
weather_description = "PARTLY CLOUDY";
break;
case 3:
lv_image_set_src(weather_image, &image_weather_cloud);
weather_description = "OVERCAST";
break;
(...)
Preparing the GUI
Before drawing the main GUI, we start by declaring all the images to illustrate the weather description.
void lv_create_main_gui(void) {
LV_IMAGE_DECLARE(image_weather_sun);
LV_IMAGE_DECLARE(image_weather_cloud);
LV_IMAGE_DECLARE(image_weather_rain);
LV_IMAGE_DECLARE(image_weather_thunder);
LV_IMAGE_DECLARE(image_weather_snow);
LV_IMAGE_DECLARE(image_weather_night);
LV_IMAGE_DECLARE(image_weather_temperature);
LV_IMAGE_DECLARE(image_weather_humidity);
(...)
Get the latest weather data
Then, we call the weather API to get the latest data and store the values in the auxiliary variables.
get_weather_data();
Load the weather image
We create an image and set it to the left side of the display.
weather_image = lv_image_create(lv_screen_active());
lv_obj_align(weather_image, LV_ALIGN_CENTER, -80, -20);
get_weather_description(weather_code);
Text Labels
To create a text label, we can call the LVGL function lv_label_create() and pass as argument where we want to display the text. We want to add it to the current screen (lv_screen_active()).
text_label_date = lv_label_create(lv_screen_active());
After creating the text label, we can set its text by using the lv_label_set_text() function that accepts as arguments the text label we’re referring to and the text we want to add to that label. In our case, we’re setting it to the current date.
lv_label_set_text(text_label_date, current_date.c_str());
The following lines align the text label. You can use the lv_obj_align() function. Pass as arguments, the LVGL object, the alignment and x and y offsets in pixels.
lv_obj_align(text_label_date, LV_ALIGN_CENTER, 70, -70);
Then, we can set the font type and size using the lv_style_set_text_font() function. We pass as argument the style object we’re referring to and the font type.
lv_obj_set_style_text_font((lv_obj_t*) text_label_date, &lv_font_montserrat_26, 0);
For the text_label_date we’re also setting a custom text teal color:
lv_obj_set_style_text_color((lv_obj_t*) text_label_date, lv_palette_main(LV_PALETTE_TEAL), 0);
A similar procedure is applied to all other labels (temperature, humidity, description, time, and location).
lv_obj_t * weather_image_temperature = lv_image_create(lv_screen_active());
lv_image_set_src(weather_image_temperature, &image_weather_temperature);
lv_obj_align(weather_image_temperature, LV_ALIGN_CENTER, 30, -25);
text_label_temperature = lv_label_create(lv_screen_active());
lv_label_set_text(text_label_temperature, String(" " + temperature + degree_symbol).c_str());
lv_obj_align(text_label_temperature, LV_ALIGN_CENTER, 70, -25);
lv_obj_set_style_text_font((lv_obj_t*) text_label_temperature, &lv_font_montserrat_22, 0);
lv_obj_t * weather_image_humidity = lv_image_create(lv_screen_active());
lv_image_set_src(weather_image_humidity, &image_weather_humidity);
lv_obj_align(weather_image_humidity, LV_ALIGN_CENTER, 30, 20);
text_label_humidity = lv_label_create(lv_screen_active());
lv_label_set_text(text_label_humidity, String(" " + humidity + "%").c_str());
lv_obj_align(text_label_humidity, LV_ALIGN_CENTER, 70, 20);
lv_obj_set_style_text_font((lv_obj_t*) text_label_humidity, &lv_font_montserrat_22, 0);
text_label_weather_description = lv_label_create(lv_screen_active());
lv_label_set_text(text_label_weather_description, weather_description.c_str());
lv_obj_align(text_label_weather_description, LV_ALIGN_BOTTOM_MID, 0, -40);
lv_obj_set_style_text_font((lv_obj_t*) text_label_weather_description, &lv_font_montserrat_18, 0);
// Create a text label for the time and timezone aligned center in the bottom of the screen
text_label_time_location = lv_label_create(lv_screen_active());
lv_label_set_text(text_label_time_location, String("Last Update: " + last_weather_update + " | " + location).c_str());
lv_obj_align(text_label_time_location, LV_ALIGN_BOTTOM_MID, 0, -10);
lv_obj_set_style_text_font((lv_obj_t*) text_label_time_location, &lv_font_montserrat_12, 0);
lv_obj_set_style_text_color((lv_obj_t*) text_label_time_location, lv_palette_main(LV_PALETTE_GREY), 0);
Timer
To update the data on the screen, we can create an LVGL timer that will run a specific function periodically. In this case, we’ll update it every 10 minutes. Create an LVGL timer called timer and assign the timer_cb callback function.
lv_timer_t * timer = lv_timer_create(timer_cb, 600000, NULL);
lv_timer_ready(timer);;
Timer Callback Function
The timer_cb function runs every 10 minutes. Each time the callback function runs, we get the latest weather data from the API and update the GUI.
static void timer_cb(lv_timer_t * timer){
LV_UNUSED(timer);
get_weather_data();
get_weather_description(weather_code);
(...)
Finally, we set all the text labels to the current data returned from the API:
lv_label_set_text(text_label_date, current_date.c_str());
lv_label_set_text(text_label_temperature, String(" " + temperature + degree_symbol).c_str());
lv_label_set_text(text_label_humidity, String(" " + humidity + "%").c_str());
lv_label_set_text(text_label_weather_description, weather_description.c_str());
lv_label_set_text(text_label_time_location, String("Last Update: " + last_weather_update + " | " + location).c_str());
loop()
In the loop(), you can add any other tasks that you need your ESP32 to do like in any regular Arduino sketch. In our case, we won’t add any tasks to the loop(), but to keep LVGL running and detecting events, you always need to add the following lines to your loop().
void loop() {
lv_task_handler(); // let the GUI do its work
lv_tick_inc(5); // tell LVGL how much time has passed
delay(5); // let this time pass
}
Demonstration
Upload the code to your board. Go to Tools > Board and select ESP32 > ESP32 Dev Module. Then, select the right COM port in Tools > Port.
If you see an Error like this: “Sketch too big” during the uploading process, in Arduino IDE go to Tools > Partition scheme > choose anything that has more than 1.4MB APP, for example: “Huge APP (3MB No OTA/1MB SPIFFS“.

Finally, click the upload button.

After a few seconds, the weather info will be displayed on the screen as shown in the picture below.

Wrapping Up
In this tutorial, you’ve created a simple weather station with your Cheap Yellow Display (CYD) board using the LVGL library.
We hope you found this tutorial useful. We’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:
Other guides you might like reading:
- Getting Started with ESP32 Cheap Yellow Display Board – CYD (ESP32-2432S028R)
- ESP32 Touchscreen On/Off Button – Cheap Yellow Display (ESP32-2432S028R)
- ESP32 Cheap Yellow Display (CYD) Pinout (ESP32-2432S028R)
- LVGL with ESP32 Cheap Yellow Display Board (ESP32-2432S028R)
To learn more about the ESP32, make sure to take a look at our resources:
weather_images.h: No such file or directory
its killinge me ( lol)
its in the direction
I had this problem and had still selected an Arduino Nano as part of a different project. It worked once I changed the board to ESP32 Dev Module
do not use the angle brackets < > for local files try
#include “weather_images.h”
You need to load these files to the folder where the ino. File is. Find show sketch file in the IDE. Then copy the missing file to that location. Then try again
The xxxxx.h is there. I have it with all sketches of this series. I don’t understand anything of this anymore.
Same error
weather_images.h: No such file or directory
Change to #include “weather_images.h”
Thank you for letting me know! I never had this issue with the <>, but I’ve changed it now to “”. I hope it works for everyone.
I am currently set up for my CYD to work with Rui and Sarah’s CYD LVGL course. It works for all the examples from the ebook, using the most updated versions. This project, though, just puts up a black screen after uploading (which is otherwise successful). Has anyone had this issue? Thanks.
Yes. Me also.
have you tried to edit User_Setup.h and uncommenting #define TFT_INVERSION_ON
Bonsoir
J’ai exactement le mĂŞme problème Ă©cran noir après tĂ©lĂ©chargement rĂ©ussi l’avez vous rĂ©solu si oui pouvez vous svp me dire comment vous avez solutionnĂ© ce souci.
merci
I get this error
C:\Users\John\Documents\Arduino\Sketches\Weather\CYD_Weather\CYD_Weather.ino: In function ‘void get_weather_data()’:
CYD_Weather:304:64: error: call of overloaded ‘String(ArduinoJson::V704PB2::detail::enable_if<true, ArduinoJson::V704PB2::detail::MemberProxy<ArduinoJson::V704PB2::detail::MemberProxy<ArduinoJson::V704PB2::JsonDocument&, const char>, const char> >::type)’ is ambiguous
temperature = String(doc[“current”][“temperature_2m”]);
I have the same error. Did you solve the problem?
Thanks for a short answer
torsten
I fix it with the help of ChatGPT:
if (!error) {
const char* datetime = doc[“current”][“time”];
// Explicitly extract values as strings
temperature = String(doc[“current”][“temperature_2m”].as());
humidity = String(doc[“current”][“relative_humidity_2m”].as());
// Convert Boolean or numeric values with .as<T>()
is_day = doc["current"]["is_day"].as<int>();
weather_code = doc["current"]["weather_code"].as<int>();
Thanks for your help. I will try it within the next week and come back to you.
Hello Eric,
i tested your solution, but without success.
Can you please send me to complete function?
if (httpCode > 0) {
Thanks for your help :’)
Torsten
There’s no explicit conversion from the JasonDocument::operator[] return type to a String, so the compile has to guess, and there are too many choices.
We can help it out with a cast:
temperature = String((const char *)doc["current"]["temperature_2m"]);
Hello Sara and Rui
My error message with both sketches where xxxxx.h should be in the directory of the program always gives the same error message.
The xxxx.h cannot be found. This while IDE does show them, top left in the bar. Other LGVL programs work fine.
I do not know a solution for this.
What can I do. ?
If you click on the weather…h file in IDE on top bar next to ino. File what happens?
then I can read the xxxx.h file
Sorry bert,
it is difficult to understand what you have done incorrectly as your descriptions are alittle vague and difficult to follow. I had not tried the sketch until about 10 minutes ago and it works perfectly.
Without seeing screen shots from your screen it is difficult to know how to help you and understand what you have not done.
Do you know how to take screen shots and maybe send them on a discord server?
Change #include
To
#include “weather_images.h”
Dear Rui and Sara,
Once again thanks for your great sketch and tutorial which runs ok for me, although I have not seen it update yet after 20Mins?(but going to leave it on test).
The sketch ran ok as per instructions, but I am still not convinced that, LVGL is for the novice coder.( A friend of mine purchased your book and he is a fairly experienced Coder, but found LVGL to be quite complex and not intuitive).
But thanks so much for your stuff and the effort that you put in for free.
Regards
Mark D
When I download the xxx.h file as in the descriptions I thought I was downloading a file to the PC. But I get the entire (lane) file as text in the picture. Is this correct? (Thanks for your patience I am old and learn very slowly)
Hello Mark, did you run it for a bit more time? It should definitely update after a few minutes. However that delay is based on a limit of the free API.
Hi Sara,
yes I did and it update correctly, Many thanks once again.
regards
Mark
I’m having a similar issue. The graphics appear on the display, but none of the data.
Curious, I added additional Serial.println() statements to verify that the get_weather_data() method was called and to check the value of httpCode.
I’m getting an HTTP code 502, and am working on how to get around it. Checking the longitude and latitude values provided by Google Maps, there’s a chance they may be too precise (13 digits after the decimal point).
I’ll reduce the number of digits to the right and see if that fixes the problem.
A little help please if you can?
When I click on the link for the “weather_images.h” file I am presented with a page of code. My question is how do I turn this in to the “.h” file to be inserted alongside the main program file? I am at a bit of a loss.
Many thanks for your help
Regards
Bryan
If you right click it and save as link into your PC. You can then copy it into you sketch folder.
Kind Regards
Mark D
Thank you Mark, very helpful, I now have the .h file in the correct place. However when I run through the VERIFY process I get an error that says ” ‘const lv_image_dsc_t’ has no non-static data member named ‘reserved’ “, and the last line (line 1011) of the .h file is highlighted. I have tried inserting commas, “//”‘s, removing “;”, but to no avail. Any suggestions please, I am at a loss once again!
Many thanks
Bryan
Hi.
Are you using the same display?
Some displays come with the colors ivnerted:https://rntlab.com/question/colors-inverted-on-cyb-esp32-display/
Regards,
Sara
I am currently set up for my CYD to work with Rui and Sarah’s CYD LVGL course. It works for all the examples from the ebook, using the most updated library versions, files, etc. This project, though, just puts up a black screen after uploading (which is otherwise successful). Has anyone had this issue? Thanks.
Not really sure what can it be… This example was tested and works under LVGL 9.2… Do you have any issue or info print on the Arduino IDE serial monitor?
Regards,
Sara
That’s a good question. Based on the serial monitor, it was hanging on “Connecting” WiFi. I went back to a Rolling Clock sketch with WiFi that has worked in the past and all seemed OK. Then I realized that I put in my SSID incorrectly in the Weather sketch. What a simple mistake … Thanks for the help, Sara, as always.
I got this erreor anny idea ??
F:\arduino-ide_2.0.0_Projecten\Projects\ESP32_Weather_Station_RNT\ESP32_Weather_Station_RNT.ino: In function ‘void get_weather_data()’:
F:\arduino-ide_2.0.0_Projecten\Projects\ESP32_Weather_Station_RNT\ESP32_Weather_Station_RNT.ino:304:64: error: call of overloaded ‘String(ArduinoJson::V720PB22::detail::enable_if_t<true, ArduinoJson::V720PB22::detail::MemberProxy<ArduinoJson::V720PB22::detail::MemberProxy<ArduinoJson::V720PB22::JsonDocument&, const char>, const char> >)’ is ambiguous
temperature = String(doc[“current”][“temperature_2m”]);
^
Marc
Marc, I have sent a few days ago a reply describing what I had to change to get the sketch working. This reply is still waiting to be moderated …
The error you show is exactly what I got.
Essentially you have to store json variables first into a c string, int, or float first and then convert then to a String as required.
Hope this helps.
Eric
As this is a nice example how to deal with lvgl and the CYD I was eager to get it run.
Here a few changes I had to make the sketch compile.
As I am not an expert I made these changes based on “trial and error” .
1- First problem: weather_images.h couldn’t be found. I changed the include into:
#include “weather_images.h”
2- Next was the complaint during compilation that the use of “StaticJsonDocument” is deprecated. I used instead of:
StaticJsonDocument doc;
the statement:
JsonDocument doc;
3- Third issue were all sorts of compile errors originating from the ArduinoJason library, having to do with the Strings in which the values are saved.
I replaced the original code with:
if (httpCode == HTTP_CODE_OK) {
String payload = http.getString();
//Parse the JSON to extract the time etc.
//StaticJsonDocument doc; // deprecated!!
JsonDocument doc;
DeserializationError error = deserializeJson(doc, payload);
if (!error) {
const char* str_timezone = doc[“timezone”];
const char* datetime = doc[“current”][“time”];
float fl_temperature = doc["current"]["temperature_2m"];
temperature = String(fl_temperature,1);
float fl_humidity = doc["current"]["relative_humidity_2m"];
humidity = String(fl_humidity,0);
is_day = doc["current"]["is_day"];
weather_code = doc["current"]["weather_code"];
//Serial.println(str_timezone);
//Serial.println(fl_temperature);
//Serial.println(fl_humidity);
//Serial.println(is_day);
//Serial.println(weather_code);
// Split the datetime into date and time
… etc. Below this the code is unchanged.
I hope this helps.
Eric
Wow, worked at first try.
Updated at 22:30 and 22:45.
Thank you very much.
That’s great!
Regards,
Sara
Sara,
I am currently set up for my CYD to work with Rui and Sarah’s CYD LVGL course. It works for all the examples from the ebook, using the most updated library versions, files, etc. On this project I get this error: c:\Users\jones\Documents\Arduino\libraries\lvgl\src\examples\styles\lv_example_style_14.c:1:10: fatal error: ../../src/themes/lv_theme_private.h: No such file or directory
1 | #include “../../src/themes/lv_theme_private.h”
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
compilation terminated.
exit status 1
Compilation error: exit status 1
Hi.
Unninstall the LVGL library and install again according to these new instrutions: https://randomnerdtutorials.com/lvgl-cheap-yellow-display-esp32-2432s028r/
Don’t move the demos and examples folders.
Regards,
Sara
Dear Sara,
Have they now altered LVGL so that the examples and Demos folders now longer need to moved in LVGL 9.2? A s i have not installed 9.2 yet?
Regards
Mark D
Hello, Rui and Sara. I am allways trying your projects and buying your books. This is my first issue. The colors of the pictures on the display are strange. The clouds are brown and the sun is blue. How can I change it?
Your work is great.
Greetings from Brazil.
Hi.
Please check this discussion.
Regards,
Sara
Rui and Sara –
These ‘mini’ eBooks you’ve been publishing are simply wonderful! They are the modern equivalent of the traditional “Hello World” starter application, that is, they provide a simple, working example as a starting point for newcomers to the various technologies. Given this working example, we neophytes can then begin experimenting with changes and additions, knowing that if we get into trouble, as most of us will, we can always return to the initial code.
And this particular example, showing as it does the use of a CYD to display data drawn from the internet, is not only an impressive “Hello World” but it, itself suggests all manner of directions for future exploration and experimentation.
Thank you ever so much for all the support and encouragement.
Thanks.
You’re welcome.
Regards,
Sara
Hello!
I get this error message.
Can anyone help me?
Thanks
Sketch uses 1796361 bytes (137%) of program storage space. Maximum is 1310720 bytes.
Global variables use 63112 bytes (19%) of dynamic memory, leaving 264568 bytes for local variables. Maximum is 327680 bytes.
Please read the instructions in the blog post under the section “Demonstration”:
If you see an Error like this: “Sketch too big” during the uploading process, in Arduino IDE go to Tools > Partition scheme > choose anything that has more than 1.4MB APP, for example: “Huge APP (3MB No OTA/1MB SPIFFS“.
I got this message when I tried to upload the sketch !
Sketch uses 1766045 bytes (134%) of program storage space. Maximum is 1310720 bytes.
Global variables use 63096 bytes (19%) of dynamic memory, leaving 264584 bytes for local variables. Maximum is 327680 bytes.
Sketch too big; see support.arduino.cc/hc/en-us/articles/360013825179 for tips on reducing it.
text section exceeds available space in board
Compilation error: text section exceeds available space in board
Please read the instructions in the blog post under the section “Demonstration”:
If you see an Error like this: “Sketch too big” during the uploading process, in Arduino IDE go to Tools > Partition scheme > choose anything that has more than 1.4MB APP, for example: “Huge APP (3MB No OTA/1MB SPIFFS“.
For VSCode and platformio.ini, add this line:
board_build.partitions = huge_app.csv
I had the same issue. Choosing the correct partition scheme fixed the “sketch too big” problem, but not the “Text section exceeds available space in board”. To overcome this I deleted all of the text at the beginning of the sketch.
Complation worked OK with Arduino 1_8_19 but connection to weather server failed (error code 400). -> I got that because I entered another timezone than “Europe/Lisbon” …
The sketch worked with -> String timezone =”auto” : then the time zone is automatically set from the coordinates of the location you entered.
PS. Working through the examples in your book with Platformio : Compilation time for the scetches is reduced to 120 sec instead of 10+ minutes !! Your weather CYD still gets many errors probably due to String incompability between c and c++ compilers of the arduino json framework. Have to check if erics’ changes work with platformio.
What a great project! Everything seems good; get the graphics on the display. But it seems that the timer never fires off get_weather_data(). Only seeing WiFi info in the Serial monitor. I uncommented some of the serial output breakpoints to troubleshoot, nothing showing. Might be related to the lv_timer? So close.
Ciao, lo sketch funziona benissimo solo mi viene il sole azzurro!.
Hi, the sketch works great, only I get a blue sun!
Pierpaolo
Hi Sara,
The weather station project compiles OK, but I get this error message when I use the ESP32 Dev Module:
Sketch uses 1800857 bytes (137%) of program storage space. Maximum is 1310720 bytes.
Global variables use 63292 bytes (19%) of dynamic memory, leaving 264388 bytes for local variables. Maximum is 327680 bytes.
Sketch too big; see https://support.arduino.cc/hc/en-us/articles/360013825179 for tips on reducing it.
text section exceeds available space in board
Compilation error: text section exceeds available space in board
I’m using the Cheap Yellow Display. Did I select the wrong board?
Hi.
In Arduino IDE go to Tools > Partition scheme > choose anything that has more than 1.4MB APP, for example: “Huge APP (3MB No OTA/1MB SPIFFS“.
This is emntioned in the tutorial.
Regards,
Sara
That fixed it. Thanks and sorry I missed the tutorial mention.
Very nice project and write-up.
It’s working very well for me except for the humidity, which is off. I have another project that uses an API from openweathermap.org, and that returns a humidity reading (74%), which is consistent with Accuweather app (72%) and Weatherbug (71%). But the call to open-meteo.com is returning 55%. I provided an accurate Lat/Lon, and America/New_York for the timezone. I’m actually in NJ, but typically use NY as the timezone. So I’m wondering what might account for the difference. Could the API call have a time issue and it’s returning a historical weather report from a few hours ago?
Thanks.
How do I change The date format to DD-MM-YY?
anybody know?
How do I change The date format to DD-MM-YY?
Nice piece of work this. I got it running almost straight away. I only had the program too big error which shows I did not read the instructions well enough LOL. My only gripe is that although the display shows everything it should, it has a very annoying flicker too it. This regardless of which USB port I plug it into. Any solutions would be appreciated.
Hi, as usual very good tutorial.
This time it didn’t work for me and I had to make some changes because I received an error:
Compilation error: call of overloaded ‘String(ArduinoJson::V710PB22::detail::enable_if_t<true, ArduinoJson::V710PB22::detail::MemberProxy<ArduinoJson::V710PB22::detail::MemberProxy<ArduinoJson::V710PB22::JsonDocument&, const char>, const char> >)’ is ambiguous
Then below is my code in case it helps someone else:
void get_weather_data() {
if (WiFi.status() == WL_CONNECTED) {
HTTPClient http;
// Construct the API endpoint
String url = “http://api.open-meteo.com/v1/forecast?latitude=” + latitude + “&longitude=” + longitude + “¤t=temperature_2m,relative_humidity_2m,is_day,precipitation,rain,weather_code” + temperature_unit + “&timezone=” + timezone + “&forecast_days=1”;
Serial.println(url);
http.begin(url);
int httpCode = http.GET(); // Make the GET request
Serial.println(httpCode);
if (httpCode > 0) {
// Check for the response
if (httpCode == HTTP_CODE_OK) {
String payload = http.getString();
Serial.println(“Request information:”);
Serial.println(payload);
StaticJsonDocument doc;
DeserializationError error = deserializeJson(doc, payload);
if (!error) {
// Parse JSON values
const char* datetime = doc["current"]["time"];
temperature = doc["current"]["temperature_2m"].as<String>();
humidity = doc["current"]["relative_humidity_2m"].as<String>();
is_day = doc["current"]["is_day"].as<int>();
weather_code = doc["current"]["weather_code"].as<int>();
Serial.println(temperature);
Serial.println(humidity);
Serial.println(is_day);
Serial.println(weather_code);
Serial.println(String(timezone));
// Split the datetime into date and time
String datetime_str = String(datetime);
int splitIndex = datetime_str.indexOf('T');
current_date = datetime_str.substring(0, splitIndex);
last_weather_update = datetime_str.substring(splitIndex + 1, splitIndex + 9); // Extract time portion
} else {
Serial.print("deserializeJson() failed: ");
Serial.println(error.c_str());
}
}
} else {
Serial.printf("GET request failed, error: %s\n", http.errorToString(httpCode).c_str());
}
http.end(); // Close connection
}
}
It has a couple of Serial print for debugging and it is not 100% tested but at least compilation worked and I can see weather results on display.
If you like me have a CYD with 2 USB ports (ST7789) you also need to make some modification on TFT_eSPI library.
Hello,
How do I display accented characters on the CYD ?
Example: Montréal
Regards
Hi Rui,
Maybe you should mention, that you need the Arduino IDE 2, othervise you will get a huge text with compilation errors.
But even after I installed the Arduino IDE 2 I still have:
Sketch uses 1801529 bytes (137%) of program storage space. Maximum is 1310720 bytes.
Global variables use 63292 bytes (19%) of dynamic memory, leaving 264388 bytes for local variables. Maximum is 327680 bytes.
Sketch too big; see https://support.arduino.cc/hc/en-us/articles/360013825179 for tips on reducing it.
text section exceeds available space in board
Can you help me with this.
Than you
Compilation error: text section exceeds available space in board
Hi.
Please read carefully all the instructions.
In the demonstration section we mention the upload details so that you don’t have the sketch too big issue.
If you see an Error like this: “Sketch too big” during the uploading process, in Arduino IDE go to Tools > Partition scheme > choose anything that has more than 1.4MB APP, for example: “Huge APP (3MB No OTA/1MB SPIFFS“.
In the prerequisites section, we also mention that you need to use arduino IDE and we provide a link with instructions to install Arduino 2.
Let me know if you need further help.
Regards,
Sara
I had the same “Text section …” error. I fixed it by deleting all of the unnecessary text at the beginning of the sketch. The “sketch too big” error is fixed using Sara’s instructions.
Amazing how many people want to code but DONT READ instructions correctly.
The DETAILS really do matter…
The other comments which I find alittle annoying are using a different board, Why doesn’t this work?. Its like buying a Mac Book and reading the instructions for a Windows laptop. Both computers but totally different
True. However, to be fair, I didn’t see anything in the instructions that addressed the issue of the text section exceeding available space. The partition change only fixed the “sketch too big” error, at least for me. As for people using the incorrect board, it’s very easy to end up with the one that has two USB ports when ordering from AliExpress, and this version is different to the original CYD.
Sorry,
that seems to be a great project, but I`m not able to compile it.
I always get a ping timeout error. after 3 minutes compile time.
I use the newest Arduino IDE 2.3.3 on MACOS.
Other project with this display are compiling and working.
do you have any idea?
Thanks,
Torsten
Hi.
What is exactly the error?
Regards,
Sara
Hi,
The temperature displayed is wrong or miscalculated. It appears like so: 9.400001. The least significant digit is always a 1. I’ve had similar number displayed on 4 occasions. I have photos I could send if you provide a mean to do so.
Regards,
Serge
Thanks for this tutorial. I also got the compile error at line 304, the compiler reporting the line was “ambiguous”. The solutions from Eric and Sergio in the comments above do work thankfully. Obviously some people are not getting this compile error and it would be nice to know what the difference is.
Hello, Great project.
I had several issues to make it work:
Using LVGL 9.2.1 lead to an DRAM overflow.
I have to select 9.2.0 to have a correct compilation.
I used ArduinoJson 7.0.4, TFT_eSPI 2.5.43, Arduino IDE 2.3.2, esp32 2.0.17
I think it would be a good practice to give the version of libraries used in projects, as many problems are encountered with evolutions that are not backward compatible.
The deserializer functions had to be modified as explain in previous comments:
const char* datetime = doc[“current”][“time”];
// Explicitly extract values as strings
temperature = String(doc[“current”][“temperature_2m”].as());
humidity = String(doc[“current”][“relative_humidity_2m”].as());
//Convert Boolean or numeric values with .as()
is_day = doc[“current”][“is_day”].as();
weather_code = doc[“current”][“weather_code”].as();
Thank you for this great tutorial. With a little bit of effort, including some reorganization of the screen layout, I’ve managed to add Pressure (MSL) to the display. I’ve always been very keen on meteorology and computing and this new display now gives me the three key elements, temperature, humidity and pressure.
By the way, I have also seen on various occasions the strange temperature display referred to by Serge MĂ©nard above.
i want to display the time on the screen above the date.
I am getting a major error while compiling the ESP32_CYD_WeathwereStation.ino. There as so many line in the error that I am going to break it dow and send just a sample ot the include statements in the error message buy use a slightly different iline item,
The last line of the error is as follows:
Compilation error: #include nested depth 200 exceeds maximum of 200 (use -fmax-include-depth=DEPTH to increase the maximum)
The error message starts with 200 lines that all look alike and say the same thing. The following is a small sample of the 200 lines,
In file included from :\Users\ledby\Arduino\Sketchbook\ESP32_CYD_WeatherStatiom/weather_images.h:23,
Following those 200 lines are
15 | #include <lvgl.h>
| ^
C:\Users\ledby\Arduino\Sketchbook\ESP32_CYD_WeatherStatiom/weather_images.h:21:22: error: #include nested depth 200 exceeds maximum of 200 (use -fmax-include-depth=DEPTH to increase the maximum)
21 | #include <TFT_eSPI.h>
| ^
C:\Users\ledby\Arduino\Sketchbook\ESP32_CYD_WeatherStatiom/weather_images.h:23:28: error: #include nested depth 200 exceeds maximum of 200 (use -fmax-include-depth=DEPTH to increase the maximum)
23 | #include “weather_images.h”
Following those lines are 24 additional statenebts that are simuler but refering to different Include statements.
The last line in the error is shown below:
In file included from C:\Users\ledby\Arduino\Sketchbook\ESP32_CYD_WeatherStatiom/weather_images.h:26:
c:\Users\ledby\Arduino\Sketchbook\libraries\ArduinoJson\src/ArduinoJson.h:9:29: error: #include nested depth 200 exceeds maximum of 200 (use -fmax-include-depth=DEPTH to increase the maximum)
I have sent print screens of the complete error to Rui but have not heard back from him. IOn surching the inter net to find a clue to solve this problem, On searching for a answer to fixing this problem, I found on Cplusplus.com something simular to my problem. They said that you need to use Include guards I do not know how to do that. I’m not sure if that is a Include statement and how to apply it. Anyone have any ideas.
Lowell
Hi.
If you send an email directly to Rui, it will response within a few hours or a couple of days (maximum)
Regards,
Sara
Welll I did send a email with 4 screen shots of the errors that I get when compiling the ESP32 CYD with LVGL: Weather Station. the four screen shots contain the error code that I get when compiing the sketch. Maybe it didn’t get to Rui. Guess I can try it again.
Lowell
Hi.
Yes. Do try again.
Regards,
Sara
Hello,
i would like to add a clock to this project.
ESP32 CYD with LVGL: Weather Station (Description, Temperature, Humidity)
thank you
fred warden
Hi.
You can try to combine it with this one: https://randomnerdtutorials.com/esp32-cyd-lvgl-digital-clock/
Regards,
Sara
I will try that
Thank you
Bonjour, c’est un très bon projet et bien expliquĂ©, moi aussi je trouve qu’il manque un petit affichage de l’heure et ce serait parfait pour moi. Je vais essayer le conseil de Sara
Bravo!
Great project, TU! I, as other commenters have noted, initially experienced the “compiled file too large…” error. After adjusting the partition size to HUGE, it failed with the same error. Finally, just closing and relaunching the IDE (2.3.3) solved that problem and the weather app worked perfectly. As an aside, I’ve had a number of IDE
issues that automagically disappear following an Arduino relaunch. If desperate, try that…
Hi.
In the demonstration section, we explain what to do to avoid that error.
”
If you see an Error like this: “Sketch too big” during the uploading process, in Arduino IDE go to Tools > Partition scheme > choose anything that has more than 1.4MB APP, for example: “Huge APP (3MB No OTA/1MB SPIFFS“.
”
Regards,
Sara
Hello Rui and Sara,
I have a newer version of the CYD with a USB-C connection, after uploading the sketch without errors the display remains dark. I read somewhere that this version CYD uses a ili9342 instead of a ili9341. Any help appreciated!
It uses an other GPIO for the Backlight: GPIO27 instead of GPIO21. Everything works after I changed it in the User_Setup.h file line 142 in the TFT_eSPI directory.
Hope this is useflul for other users of the USB-C 2.4 CYD resistive touch.
Hi. again.
Thanks for sharing the solution.
Regards,
Sara
Hi.
Go to the User_setup file and see if you need to uncomment any definitions for that specific driver.
It may also be helpful taking a look at this discussion: https://rntlab.com/question/colors-inverted-on-cyb-esp32-display/
Regards,
Sara
It uses ST 7789…type in Google cyd 2usb user set up
Hello Mark,
My CYD is the smaller 2.4 inch with only one USB-C connector.
It uses the same ili9341 as the original CYD.
Hi Sara,
Program now compiles. but only shows ‘Clear Sky’, & no date, rainfall % or temperature.
Why?
Alan
Bonjour
J’ai le mĂŞme problème. Avez vous trouvĂ© la solution? Merci pour votre rĂ©ponse.
Cordialement
DH
Hi DH,
Can you translate tha to English, please.
Hello,
I am new to LVGL. How can I make it display letters like Č, Ć, Š, etc.?
I believe it is not a UTF8 issue, as line 456 in lv_conf.h enables the UTF8.
#define LV_TXT_ENC LV_TXT_ENC_UTF8
Hello,
I had the same problem with French accented characters. No reply since October !
Tried to mess up with setlocale() but nothing. Tried to add UTF8 characters, but still nothing.
forum.lvgl.io/t/how-to-use-latin-characters-a-o-c-in-text-labels-v-7-10-0/4803
The LVGL lib is a pain in the a$$. It can not come even close to the Adafruit GFX in terms of easy of use. When you read the example here, it is too complicated to follow up.
The link you provided is for converting a font to a LGVL readable format. Let’s say I use a built-in font, but want to use some extra letters. Huh?
@dekip I think you are missing this is a free example made by two guys that just want to help others to learn.
If you feel you can improve the code just share it here but, criticism doesn’t help anyone.
Or maybe better you can build your own page with your content and make a bigger contribution.
Lets try to keep this comments gently and useful.
Thanks for the hint.
However after reading the url I have decided to skip the pain proposed !
I’ll wait for RNT and/or LVGL to come up with a solution for this hole in the library.
Hi.
Because we create all our examples in English, we haven’t come across the issue of trying to write special characters.
Unfortunately, we haven’t looked into that issue yet.
I think the only way is to create your own font as explained in this link shared previously: https://forum.lvgl.io/t/how-to-use-latin-characters-a-o-c-in-text-labels-v-7-10-0/4803
Regards.
Sara
Thanks Sara, the LVGL library is not ready for prime time ! I’ll go on and do other things while they catch up with the world ! Serge
Bonjour
AprĂ©s avoir bien hĂ©sitĂ© j’ai dĂ©cidĂ© de me lancer dans ce projet bien qu’Ă©tant novice j’ai lu et relu tous les articles le rĂ©sultat est que le tĂ©lĂ©versement s’est bien passĂ© mais je n’ai aucun affichage sur l’Ă©cran qui reste noir.
Quelqu’un peut il m’aider et m’expliquer ce que j’ai manquĂ©.
merci infiniment à celui ou celle qui prendra de son temps pour répondre.
Hi.
Please double-check that you’re using the right User_setup.h file and it is located on the right place.
Additionally, which board are you using? Is it exactly like ours? Or does yours have two USB ports?
Regards
Sara
Bonjour
J’ai rĂ©pondu hier par le biais de ma messagerie n’Ă©tant pas sur que vous ayez reçu la rĂ©ponse je rĂ©ponds ici.
La carte que j’ ai reçu a 2 ports usb. Je pense avoir suivi la procĂ©dure Ă la lettre mais Ă©tant complètement bĂ©otien dans ce domaine j’ai certainement fait une erreur quelque part. J’ai fait les 2 tests dĂ©crits dans les explications et le resultat Ă©tait positif.
Merci pour votre réponse et votre aide.
Which setup do I need? The one I download at Rui and Sara is in the right place (?) I also get no image anymore but an empty screen. Unfortunately I no longer understand how to do it despite the clear explanation. Who can help me because I have no idea how to do it. Ask which setup file is good and which is not how do I see the difference. It is in the right place.
What CYD board do you have?
Does it have two USB ports?
I understand that these CYD boards have quite a few problems regarding settings
My boards have 1 USB connection and according to the description the ILI9488 driver is required, the model number is ESP32-2432So28, there is no R behind that number.
From the first start article of yours the boards worked fine. But without changing my settings (I will not do that) everything suddenly went wrong. I have had a lot of work on it and stopped for a while. Now the sketches are loaded again, but with this driver activated the screen remains black. Other drivers ditto.
I do not know how to proceed with this.
I have redone the settings and lbs several times.
Question: How do I find out which driver is required. There is no text on the PCB other than the above.
Please respond.
So, it seems you’re using a different CYD board.
In that case, I think you need to change the following settings in the User_setup
User_Setup.h:
#define ST7789_DRIVER
#define TFT_RGB_ORDER TFT_BGR
#define TFT_INVERSION_OFF
Let me know if this solves the issue.
Regards,
Sara
Bonjour
J’ai ouvert le fichier user_setup dans le dossier TFT_eSPI et j’ai supprimĂ© les lignes 67 define ST7789 2_ driver
87 define TFT_RGB _order TFT RGB
126 define TFT_inversion_on
J’ai reteleverser le programme et l’Ă©cran est toujours noir.
Je n’ai surement pas fait la bonne manip.
It’s hard to tell what might be wrong.
I suggestion deleting the libraries and trying to follow the libraries’ installation process from the start.
Bert I have spoken to you before. There never ever has been a mention of il9488. They cyd you have which you have used before should never had to change the user_setup of tft_espi once you had any of the older sketches that worked. I suggest you back to older tutorials and start again. If you have a 2.8 inch CYD with one USB then the earlier tft_espi user setup will work perfectly. Do not change it once it works. The lvgl setup requires totally different library changes. Not the tft espi user setup. That stays the sMe
Merci beaucoup pour cette rĂ©ponse. Comme je vous l’ai dit dans mon message je suis ignorant sur ce sujet et je m’en excuse mais pouvez vous svp me dire comment accĂ©der au fichier User_setup et comment faire les modifications?
Encore merci pour votre patience mĂŞme si je n’y connais rien j’aimerais finaliser le projet.
Cordialement
DH
Thanks for your patience. That an il9488 Driver would be needed for my CYD was in the description of that board. That’s why I mentioned it. I have no idea which ones from the long setup list it should be. I never changed anything. That’s why. Okay, which driver do you think I need. Thanks again
Confusing, certainly for me. But I got the CYD working again. Not with the ILI9341_DRIVER-2 but strangely enough with the ILI9341_DRIVER. Don’t ask me how that’s possible, I’m just glad it’s working again. A question right away. Which location should be specified for the Netherlands? With Amsterdam it really stays too warm on the screen. Because it’s freezing here minus 5Gr.c. The screen shows 9.1 Gr.c.
The time zone is set to Europe/Berlin.
Thanks for all the help and patience.
Hi.
You should set your latitude, longitude and location on the following variables to get info about the weather:
Set your latitude, longitude and location in these three variables:
String latitude = “”;
String longitude = “”;
String location = “”; // Example: Porto
Regards,
Sara
For example:
// Replace with the latitude and longitude to where you want to get the weather
String latitude = “41.14961”;
String longitude = “-8.61099”;
// Enter your location
String location = “Porto”;
Yes I did that for my location. This morning I saw that the info on the CYD was correct. So it took some time. I see now that an update has no fixed time but the info is correct. (still no bikini weather) – 2Gr/c 🙂 Thank you Sara and Rui
Great.
I’m glad it’s working as expected now.
Regards,
Sara
Bonjour
AprĂ©s plusieurs jours de galère avec Ă©cran noir ou un affichage sans tempĂ©rature et sans humiditĂ© j’ai rĂ©ussi Ă avoir un Ă©cran avec toutes les informations. Pour moi il semble que ça ne fonctionne que sur un rĂ©seau wifi 2.4GHz et pas sur 5GHz. Il reste un souci la tempĂ©rature et le % d’humiditĂ© ne sont pas bons. J’ai pris les coordonnĂ©es de ma ville sur le site d’open mĂ©tĂ©o j’ai choisi le fuseau europe Berlin. J’habite dans le nord de la france si quelqu’un a une solution je suis preneur.
Merci Ă tous
Use “Europe/Paris” Amsterdam has the same timezone.
So “Europe/Amsterdam” will also work.
Utilisez ” Europe/Paris ” Amsterdam a le mĂŞme fuseau horaire.
Donc ” Europe/Amsterdam ” est Ă©galement possible.
For the weather, set your latitude, longitude and location in these three variables:
String latitude = “”;
String longitude = “”;
String location = “”;
For example:
String latitude = “41.14961”;
String longitude = “-8.61099”;
// Enter your location
String location = “Porto”;
Regards,
Sara
Bonjour
merci pour votre rĂ©ponse j’ai mis les coordonnĂ©es donnĂ©es par open weather dans les lignes que vous m’indiquez. j’ai l’impression qu’il n’y a pas de mise Ă jour de la tempĂ©rature toutes les 10 mn comme indiquĂ© dans le programme.
Hi.
We make a request every 10 minutes. But the information on the API might take longer to update.
Regards,
Sara
Merci pour votre réponse
J’ai mis europe/amsterdam dans le programme. J’ai li’mpression que la mise Ă jour ne se fait pas tous les 10mn comme dans le programme? Y a t’il une solution pour cela?
Cordialement
DH
L’information est demandĂ©e toutes les dix minutes, mais elle peut arriver plus tard.
Cela m’arrive aussi. Je pense mĂŞme que dix minutes, c’est un peu trop.
It is requested every ten minutes but the information can come later.
That happens to me too. I even find ten minutes a bit too often.
Hello Sara and Rui. My CYD are now working well and stable. I was really lost in that.
I understand that there are CYD versions with two USB ports.
Am I right that they also use a different display driver?
Perhaps it would be useful to publish an article about this if necessary.
Or is that already there?
It seems to me that it is not useful to work with two setups.
You make beautiful work. I am old and unfortunately have been very slow in thinking and understanding for years. This hobby has kept me going since 2017
Thank you
Hi.
Yes, that board has a different display driver.
So, it is necessary to change the configuration file.
Unfortunately, I wasn’t able to buy one of those models to test. That’s why we don’t have a guide for that yet.
Regards,
Sara
Dear Burt
I think the subject of the two different displays of the Cyd s has been comprehensively covered by many of them comments. If you have only one USB then the user setup provided will work. If you have the 2 USB version the set up is slightly different.
It’s a shame because there are some display libraries out there that use a simple 1 line macro to tell the display library exactly which display you are using. So simple. bb_spi_lcd is one such library which is so much easier to use than Tft espi.
Thank you. I am also waiting for a possible response from Sara or Rui.
Hi Sara,
Received this msg on the serial monitor:
GET request failed, error: read Timeout
LVGL Library Version: 9.2.0
Connecting…
Connected to Wi-Fi network with IP Address: 192.168.4.61
Display only shows ‘Clear Sky’, 2 stars, crescent moon, C & %, but no data.
Make sure the time zone identification is exactly what the TZ table calls out. I accidentally imbedded a space in my code the first time and got the same result you describe.
Hi Jay,
I live in uk & entered “Europe/London” for my time zone, is this correct?
Thanks
Alan
Hi Jay,
Have now corrected longitude & latitude. The display now works as it should.
Thanks for your help.
Alan
Sara:
I added a debug to the GET():
Serial.print(“HTTP Code = “); // debug
Serial.println(httpCode);
it returns code 502 and “Failed” after each subsequent attempt.
Jay
Sara:
OK, problem solved. I entered the time zone data improperly. Corrected that and now everything is working. I should not have taken 10 hours to find this, but such is life.
Thanks for the project.
I had the same result. It was because d entered the time zone improperly. It has to be exactly as shown in the tine zone app.