Dans ce projet, vous apprendrez comment transformer votre carte ESP32 Cheap Yellow Display (CYD) en une station météo qui affiche la description météo, la température, l’humidité et la date à l’aide de LVGL (Light Versatile Graphics Library). Nous utiliserons l’API Open-Meteo pour obtenir les données météorologiques et la puce ESP32 sera programmée à l’aide de l’IDE Arduino.

Nouveau sur l’écran jaune bon marché ESP32 ? Commencez ici : Premiers pas avec le tableau d’affichage jaune bon marché ESP32 – CYD (ESP32-2432S028R).
Aperçu du projet
Nous afficherons la description météo actuelle, la température, l’humidité et la date sur la carte ESP32 CYD. La description météo sera également identifiée par une image.


Pour obtenir une description météo précise de votre emplacement, nous utiliserons l’API gratuite Open-Meteo. Pour obtenir les données de l’API, l’ESP32 doit se connecter à Internet, vous devez donc disposer d’un routeur à proximité pour que l’ESP32 puisse s’y connecter.
Conditions préalables
Avant de continuer, assurez-vous de suivre les conditions préalables suivantes. Vous devez suivre toutes les étapes, sinon votre projet ne fonctionnera pas.
1) Pièces requises
Pour ce projet, vous avez besoin des pièces suivantes
2) Installez les cartes ESP32 dans l’IDE Arduino

Nous allons programmer l’ESP32 à l’aide de l’IDE Arduino. Assurez-vous que les cartes ESP32 sont installées. Suivez le tutoriel suivant :
3) Familiarisez-vous avec l’écran jaune bon marché ESP32
La carte de développement ESP32-2432S028R est connue dans la communauté des fabricants sous le nom de « Cheap Yellow Display » ou CYD en abrégé. Cette carte de développement, dont la puce principale est un module ESP32-WROOM-32, est livrée avec un écran tactile LCD TFT de 2,8 pouces, une interface de carte microSD, une LED RVB et tous les circuits nécessaires pour programmer et alimenter la carte.

Si c’est la première fois que vous utilisez l’écran jaune bon marché ESP32, assurez-vous de suivre notre guide de démarrage :
4) Installez les bibliothèques TFT et LVGL
LVGL (Light and Versatile Graphics Library) est une bibliothèque graphique gratuite et open source qui fournit une large gamme d’éléments graphiques faciles à utiliser pour vos projets de microcontrôleurs nécessitant une interface utilisateur graphique (GUI).

Suivez le didacticiel suivant pour installer et configurer les bibliothèques requises pour utiliser LVGL pour l’écran jaune bon marché ESP32 à l’aide de l’IDE Arduino.
5) Installer la bibliothèque ArduinoJson
Pour ce projet, vous devez installer la bibliothèque ArduinoJSON pour gérer la réponse JSON lorsque vous effectuez une requête auprès de WorldTimeAPI.
Dans l’IDE Arduino, accédez à Sketch > Inclure la bibliothèque > Gérer les bibliothèques. Recherchez ArduinoJSON et installez la bibliothèque de Benoit Blanchon. Nous utilisons la version 7.0.4. Nous vous recommandons d’utiliser la même version.

Station météo ESP32 CYD – fichier Weather_images.h
Pour charger des images personnalisées à l’aide de LVGL, vous devez créer un fichier supplémentaire appelé Weather_images.h qui doit être placé dans le dossier Sketch. Nous avons déjà préparé ce dossier pour vous. Afin de charger les images personnalisées pour ce projet de station météo, vous devez télécharger le fichier suivant.
Important : le fichier Weather_images.h doit être placé à côté du fichier .ino dans le dossier sketch de votre projet.

Votre IDE Arduino devrait avoir deux onglets :

Si vous souhaitez en savoir plus sur le chargement d’images à l’aide de LVGL, nous vous recommandons de lire notre Guide ESP32 CYD avec LVGL : Afficher l’image à l’écran
Station météo ESP32 CYD – Code Arduino
Le code suivant créera des étiquettes de texte avec la description de la météo, la température, l’humidité, la date actuelle et l’heure de la dernière mise à jour. Il chargera également une image pour illustrer la description météo actuelle.
Avant de télécharger le code sur votre carte, vous devez insérer vos informations d’identification réseau afin que l’ESP32 puisse se connecter à Internet pour obtenir l’heure et la date. Vous devez également insérer votre latitude, longitude, emplacement et fuseau horaire.
/* Rui Santos & Sara Santos - Raspberryme.com - https://Raspberryme.com/esp32-cyd-lvgl-weather-station/ | https://Raspberryme.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://Raspberryme.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://Raspberryme.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 Raspberryme.com ***
*** 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://Raspberryme.com/cyd-lvgl/ or https://Raspberryme.com/esp32-tft-lvgl/ */
#include
/* 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 Raspberryme.com ***
*** 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://Raspberryme.com/cyd-lvgl/ or https://Raspberryme.com/esp32-tft-lvgl/ */
#include
#include "weather_images.h"
#include
#include
#include
// 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.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
}
Afficher le code brut
Comment fonctionne le code ?
Voyons comment obtenir les données météorologiques actuelles à partir de l’API et mettre à jour l’écran avec les valeurs actuelles. Vous pouvez également passer directement à la section Démonstration.
Y compris les bibliothèques et les images
Vous devez inclure les bibliothèques lvgl.h et TFT_eSPI.h pour dessiner l’interface graphique à l’écran.
#include
#include
Vous devez inclure les bibliothèques WiFi, HTTPClient et ArduinoJson pour effectuer des requêtes HTTP et gérer les données JSON.
#include
#include
#include
Incluez le fichier Weather_images.h qui contient toutes les données pour dessiner les images météo.
#include "weather_images.h"
Insérez vos coordonnées
Dans les lignes suivantes, vous devez insérer vos identifiants réseau afin que l’ESP32 puisse se connecter à votre routeur.
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
Définissez votre latitude, longitude et emplacement dans ces trois variables :
String latitude = "";
String longitude = "";
String location = ""; // Example: Porto
Définissez votre fuseau horaire dans la variable timezone au début du code (liste de tous les fuseaux horaires disponibles).
const char* timezone = "REPLACE_WITH_YOUR_TIMEZONE"; // Example: Europe/Lisbon
Déclaration d’autres variables
Créez des variables auxiliaires pour contenir les données météorologiques et d’autres valeurs.
String current_date;
String last_weather_update;
String temperature;
String humidity;
int is_day;
int weather_code = 0;
String weather_description;
Température en Celsius ou Fahrenheit
Par défaut, nous afficherons les valeurs de température en degrés Celsius. Si vous souhaitez afficher les relevés de température en degrés Fahrenheit, modifiez la variable TEMP_CELSIUS sur 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
Objets LVGL globaux
Nous créons des objets LVGL globaux, afin de pouvoir y accéder ultérieurement dans toutes les fonctions.
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;
installation()
Dans setup(), incluez les lignes suivantes pour le débogage. Ceux-ci imprimeront la version de LVGL que vous utilisez. Vous devez utiliser la 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);
Connectez-vous à Internet
Pour connecter l’ESP32 à Internet, nous utilisons le code suivant.
// 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());
Initialiser la bibliothèque LVGL
Initialisez la bibliothèque LVGL en appelant la fonction lv_init() dans setup().
// Start LVGL
lv_init();
Fonction de débogage d’enregistrement
Enregistrez votre fonction log_print() déclarée précédemment comme fonction associée au débogage LVGL.
// Register print function for debugging
lv_log_register_print_cb(log_print);
Créer un objet d’affichage
Pour écrire sur l’affichage, vous devez d’abord créer un objet d’affichage. Vous devez le faire dans tous vos croquis LVGL. Les lignes suivantes créeront un objet d’affichage LVGL appelé disp avec la largeur d’écran, la hauteur d’écran et le tampon de dessin définis précédemment.
// 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);
Dessiner l’interface graphique
La bibliothèque LVGL fonctionne de manière asynchrone. Vous devez appeler la fonction pour dessiner sur l’écran dans setup(). Ensuite, tout fonctionne avec les événements et les rappels. Le code sera toujours à l’écoute des événements en arrière-plan. Lorsque quelque chose se produit, il exécutera la fonction de rappel associée à l’événement. Vous n’avez pas besoin de rechercher des événements dans la boucle().
Dans la plupart de nos exemples, la fonction qui dessinera à l’écran sera appelée lv_create_main_gui(). Ensuite, à l’intérieur de cette fonction, nous ajouterons les instructions pour construire l’interface.
// Function to draw the GUI
lv_create_main_gui();
get_weather_data()
Lorsque nous initialisons l’écran, nous appelons la fonction get_weather_data() pour obtenir les dernières données météorologiques de l’API Open-Meteo. Ensuite, nous stockons les valeurs dans quelques variables auxiliaires qui serviront à les afficher à l’écran.
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 (code int)
La fonction get_weather_description() reçoit le code météo de l’API Open-Meteo et attribue la description météo correcte et l’image correspondante pour illustrer la météo actuelle.
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;
(...)
Préparation de l’interface graphique
Avant de dessiner l’interface graphique principale, nous commençons par déclarer toutes les images pour illustrer la description météo.
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);
(...)
Obtenez les dernières données météorologiques
Ensuite, nous appelons l’API météo pour obtenir les dernières données et stocker les valeurs dans les variables auxiliaires.
get_weather_data();
Charger l’image météo
Nous créons une image et la plaçons sur le côté gauche de l’écran.
weather_image = lv_image_create(lv_screen_active());
lv_obj_align(weather_image, LV_ALIGN_CENTER, -80, -20);
get_weather_description(weather_code);
Étiquettes de texte
Pour créer une étiquette de texte, nous pouvons appeler la fonction LVGL lv_label_create() et passer en argument l’endroit où nous voulons afficher le texte. Nous voulons l’ajouter à l’écran actuel (lv_screen_active()).
text_label_date = lv_label_create(lv_screen_active());
Après avoir créé l’étiquette de texte, nous pouvons définir son texte en utilisant la fonction lv_label_set_text() qui accepte comme arguments l’étiquette de texte à laquelle nous faisons référence et le texte que nous voulons ajouter à cette étiquette. Dans notre cas, nous le fixons à la date actuelle.
lv_label_set_text(text_label_date, current_date.c_str());
Les lignes suivantes alignent l’étiquette de texte. Vous pouvez utiliser la fonction lv_obj_align(). Passez en arguments, l’objet LVGL, l’alignement et les décalages x et y en pixels.
lv_obj_align(text_label_date, LV_ALIGN_CENTER, 70, -70);
Ensuite, nous pouvons définir le type et la taille de la police à l’aide de la fonction lv_style_set_text_font(). Nous passons en argument l’objet de style auquel nous faisons référence et le type de police.
lv_obj_set_style_text_font((lv_obj_t*) text_label_date, &lv_font_montserrat_26, 0);
Pour text_label_date, nous définissons également une couleur turquoise de texte personnalisée :
lv_obj_set_style_text_color((lv_obj_t*) text_label_date, lv_palette_main(LV_PALETTE_TEAL), 0);
Une procédure similaire est appliquée à toutes les autres étiquettes (température, humidité, description, heure et lieu).
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);
Minuteur
Pour mettre à jour les données à l’écran, nous pouvons créer une minuterie LVGL qui exécutera périodiquement une fonction spécifique. Dans ce cas, nous le mettrons à jour toutes les 10 minutes. Créez un minuteur LVGL appelé timer et attribuez la fonction de rappel timer_cb.
lv_timer_t * timer = lv_timer_create(timer_cb, 600000, NULL);
lv_timer_ready(timer);;
Fonction de rappel de minuterie
La fonction timer_cb s’exécute toutes les 10 minutes. Chaque fois que la fonction de rappel s’exécute, nous obtenons les dernières données météorologiques de l’API et mettons à jour l’interface graphique.
static void timer_cb(lv_timer_t * timer){
LV_UNUSED(timer);
get_weather_data();
get_weather_description(weather_code);
(...)
Enfin, nous définissons toutes les étiquettes de texte sur les données actuelles renvoyées par l’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());
boucle()
Dans la boucle (), vous pouvez ajouter toutes les autres tâches que votre ESP32 doit effectuer, comme dans n’importe quel croquis Arduino classique. Dans notre cas, nous n’ajouterons aucune tâche à la boucle(), mais pour que LVGL continue de fonctionner et de détecter les événements, vous devez toujours ajouter les lignes suivantes à votre boucle().
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
}
Démonstration
Téléchargez le code sur votre tableau. Accédez à Outils > Carte et sélectionnez ESP32 > Module de développement ESP32. Ensuite, sélectionnez le bon port COM dans Outils > Port.
Si vous voyez une erreur comme celle-ci : « Esquisse trop grande » pendant le processus de téléchargement, dans l’IDE Arduino, accédez à Outils > Schéma de partition > choisissez tout ce qui contient plus de 1,4 Mo d’application, par exemple : « Énorme application (3 Mo sans OTA/1 Mo). SPIFF ».

Enfin, cliquez sur le bouton de téléchargement.

Après quelques secondes, les informations météo s’afficheront sur l’écran comme le montre l’image ci-dessous.

Conclusion
Dans ce didacticiel, vous avez créé une station météo simple avec votre carte Cheap Yellow Display (CYD) à l’aide de la bibliothèque LVGL.
Nous espérons que vous avez trouvé ce tutoriel utile. Nous préparons d’autres guides sur ce forum, alors restez à l’écoute. Si vous souhaitez en savoir plus sur la création d’interfaces utilisateur graphiques à l’aide de la bibliothèque LVGL avec l’ESP32, consultez notre dernier eBook :
Autres guides que vous aimeriez lire :
Pour en savoir plus sur l’ESP32, assurez-vous de consulter nos ressources :
Cette vidéo vous emmène dans l’histoire de Raspberry Pi :

-
VEVOR Station Météo Wifi 7 en 1 Station Météo Sans Fil Intérieur Extérieur Solaire Grand Écran Couleur 7,5 po Station Météo Numérique Capteur pour Température Humidité Vitesse Direction de Vent Pluie
-
Station Météo WiFi Professionnelle 7 en 1 Avec Capteur Extérieur Sans Fil, 4 Rétroéclairages Réglables, Pluviomètre, Anémomètre, Girouette, Baromètre et Prévision Météo
