Dans ce guide, vous apprendrez à créer un tableau réactif à l’aide de LVGL. Nous afficherons la température, l’humidité et la pression du capteur BME280, ainsi que la luminosité du LDR sur l’écran. Nous afficherons également l’horodatage associé aux lectures (date et heure). L’ESP32 sera programmé à 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
Dans ce projet, nous allons créer un tableau avec les lectures du capteur BME280 et du LDR sur la carte ESP32 CYD. Nous afficherons également la date et l’heure, ainsi que l’adresse IP de votre carte.


Pour obtenir une date et une heure précises pour votre fuseau horaire, nous utiliserons WorldTimeAPI. Pour obtenir l’heure 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.
Si vous ne disposez pas d’une connexion Internet sur laquelle l’ESP32 fonctionnera, vous pouvez omettre la section date et heure ou utiliser un module RTC.
Nous afficherons également un bouton flottant avec l’icône d’actualisation qui, une fois cliqué, mettra à jour les valeurs du tableau.
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 et câblage du circuit
Pour ce projet, vous avez besoin des pièces suivantes :
Nous utiliserons le protocole de communication I2C pour obtenir les données du capteur BME280. Sur la carte ESP32 CYD se trouve une prise IO étendue qui vous permet de connecter des périphériques externes. Nous allons connecter le capteur au connecteur CN1.

Votre carte aurait dû être livrée avec un petit connecteur JST pour accéder à ces GPIO.

Si vous n’êtes pas familier avec le capteur BME280, nous vous recommandons de lire notre guide de démarrage : ESP32 avec capteur BME280 utilisant l’IDE Arduino (Pression, Température, Humidité)
La carte CYD doit avoir une LDR (résistance dépendante de la lumière) intégrée à côté de l’écran et connectée au GPIO 34.

Lecture recommandée : brochage de l’écran jaune bon marché (CYD) ESP32 (ESP32-2432S028R).
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) Installez les bibliothèques ArduinoJson et BME280
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.

Nous utiliserons la bibliothèque Adafruit BME280 pour obtenir les données du BME280. Dans l’IDE Arduino, accédez à Sketch > Inclure la bibliothèque > Gérer les bibliothèques. Recherchez la bibliothèque Adafruit BME280 dans le champ de recherche et installez la bibliothèque. Installez également toutes les dépendances qui ne sont actuellement pas installées (généralement les bibliothèques Adafruit Bus IO et Adafruit Unified Sensor).

ESP32 CYD : afficher les lectures du capteur BME280 sur une table – Code Arduino
Le code suivant créera le tableau et affichera les lectures du capteur. 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. Vous devez également insérer votre fuseau horaire.
/* Rui Santos & Sara Santos - Raspberryme.com - https://Raspberryme.com/esp32-cyd-lvgl-display-bme280-data-table/ | https://Raspberryme.com/esp32-tft-lvgl-display-bme280-data-table/
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
// Install the "XPT2046_Touchscreen" library by Paul Stoffregen to use the Touchscreen - https://github.com/PaulStoffregen/XPT2046_Touchscreen - Note: this library doesn't require further configuration
#include
#include
#include
#include
// Replace with your network credentials
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
// Specify the timezone you want to get the time for
const char* timezone = "Europe/Lisbon";
// Store date and time
String current_date;
String current_time;
// Install Adafruit Unified Sensor and Adafruit BME280 Library
#include
#include
#include
#define I2C_SDA 27
#define I2C_SCL 22
#define SEALEVELPRESSURE_HPA (1013.25)
TwoWire I2CBME = TwoWire(0);
Adafruit_BME280 bme;
// SET VARIABLE TO 0 FOR TEMPERATURE IN FAHRENHEIT DEGREES
#define TEMP_CELSIUS 1
#define LDR_PIN 34
// Touchscreen pins
#define XPT2046_IRQ 36 // T_IRQ
#define XPT2046_MOSI 32 // T_DIN
#define XPT2046_MISO 39 // T_OUT
#define XPT2046_CLK 25 // T_CLK
#define XPT2046_CS 33 // T_CS
SPIClass touchscreenSPI = SPIClass(VSPI);
XPT2046_Touchscreen touchscreen(XPT2046_CS, XPT2046_IRQ);
#define SCREEN_WIDTH 240
#define SCREEN_HEIGHT 320
// Touchscreen coordinates: (x, y) and pressure (z)
int x, y, z;
#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();
}
// Get the Touchscreen data
void touchscreen_read(lv_indev_t * indev, lv_indev_data_t * data) {
// Checks if Touchscreen was touched, and prints X, Y and Pressure (Z)
if(touchscreen.tirqTouched() && touchscreen.touched()) {
// Get Touchscreen points
TS_Point p = touchscreen.getPoint();
// Advanced Touchscreen calibration, LEARN MORE » https://Raspberryme.com/touchscreen-calibration/
float alpha_x, beta_x, alpha_y, beta_y, delta_x, delta_y;
// REPLACE WITH YOUR OWN CALIBRATION VALUES » https://Raspberryme.com/touchscreen-calibration/
alpha_x = -0.000;
beta_x = 0.090;
delta_x = -33.771;
alpha_y = 0.066;
beta_y = 0.000;
delta_y = -14.632;
x = alpha_y * p.x + beta_y * p.y + delta_y;
// clamp x between 0 and SCREEN_WIDTH - 1
x = max(0, x);
x = min(SCREEN_WIDTH - 1, x);
y = alpha_x * p.x + beta_x * p.y + delta_x;
// clamp y between 0 and SCREEN_HEIGHT - 1
y = max(0, y);
y = min(SCREEN_HEIGHT - 1, y);
// Basic Touchscreen calibration points with map function to the correct width and height
//x = map(p.x, 200, 3700, 1, SCREEN_WIDTH);
//y = map(p.y, 240, 3800, 1, SCREEN_HEIGHT);
z = p.z;
data->state = LV_INDEV_STATE_PRESSED;
// Set the coordinates
data->point.x = x;
data->point.y = y;
// Print Touchscreen info about X, Y and Pressure (Z) on the Serial Monitor
Serial.print("X = ");
Serial.print(x);
Serial.print(" | Y = ");
Serial.print(y);
Serial.print(" | Pressure = ");
Serial.print(z);
Serial.println();
}
else {
data->state = LV_INDEV_STATE_RELEASED;
}
}
static void float_button_event_cb(lv_event_t * e) {
update_table_values();
}
static lv_obj_t * table;
static void update_table_values(void) {
// Get the latest temperature reading in Celsius or Fahrenheit
#if TEMP_CELSIUS
float bme_temp = bme.readTemperature();
const char degree_symbol[] = "\u00B0C";
#else
float bme_temp = 1.8 * bme.readTemperature() + 32;
const char degree_symbol[] = "\u00B0F";
#endif
String bme_temp_value = String(bme_temp) + degree_symbol;
String bme_humi_value = String(bme.readHumidity()) + "%";
String bme_press_value = String(bme.readPressure() / 100.0F) + " hPa";
String ldr_value = String(analogRead(LDR_PIN));
// Get the time from WorldTimeAPI
get_date_and_time();
//Serial.println("Current Date: " + current_date);
//Serial.println("Current Time: " + current_time);
// Fill the first column
lv_table_set_cell_value(table, 0, 0, "Data");
lv_table_set_cell_value(table, 1, 0, "Temperature");
lv_table_set_cell_value(table, 2, 0, "Humidity");
lv_table_set_cell_value(table, 3, 0, "Pressure");
lv_table_set_cell_value(table, 4, 0, "Luminosity");
lv_table_set_cell_value(table, 5, 0, "Date");
lv_table_set_cell_value(table, 6, 0, "Time");
lv_table_set_cell_value(table, 7, 0, "IP Address");
// Fill the second column
lv_table_set_cell_value(table, 0, 1, "Value");
lv_table_set_cell_value(table, 1, 1, bme_temp_value.c_str());
lv_table_set_cell_value(table, 2, 1, bme_humi_value.c_str());
lv_table_set_cell_value(table, 3, 1, bme_press_value.c_str());
lv_table_set_cell_value(table, 4, 1, ldr_value.c_str());
lv_table_set_cell_value(table, 5, 1, current_date.c_str());
lv_table_set_cell_value(table, 6, 1, current_time.c_str());
lv_table_set_cell_value(table, 7, 1, WiFi.localIP().toString().c_str());
}
static void draw_event_cb(lv_event_t * e) {
lv_draw_task_t * draw_task = lv_event_get_draw_task(e);
lv_draw_dsc_base_t * base_dsc = (lv_draw_dsc_base_t*) draw_task->draw_dsc;
// If the cells are drawn
if(base_dsc->part == LV_PART_ITEMS) {
uint32_t row = base_dsc->id1;
uint32_t col = base_dsc->id2;
// Make the texts in the first cell center aligned
if(row == 0) {
lv_draw_label_dsc_t * label_draw_dsc = lv_draw_task_get_label_dsc(draw_task);
if(label_draw_dsc) {
label_draw_dsc->align = LV_TEXT_ALIGN_CENTER;
}
lv_draw_fill_dsc_t * fill_draw_dsc = lv_draw_task_get_fill_dsc(draw_task);
if(fill_draw_dsc) {
fill_draw_dsc->color = lv_color_mix(lv_palette_main(LV_PALETTE_BLUE), fill_draw_dsc->color, LV_OPA_20);
fill_draw_dsc->opa = LV_OPA_COVER;
}
}
// In the first column align the texts to the right
else if(col == 0) {
lv_draw_label_dsc_t * label_draw_dsc = lv_draw_task_get_label_dsc(draw_task);
if(label_draw_dsc) {
label_draw_dsc->align = LV_TEXT_ALIGN_RIGHT;
}
}
// Make every 2nd row gray color
if((row != 0 && row % 2) == 0) {
lv_draw_fill_dsc_t * fill_draw_dsc = lv_draw_task_get_fill_dsc(draw_task);
if(fill_draw_dsc) {
fill_draw_dsc->color = lv_color_mix(lv_palette_main(LV_PALETTE_GREY), fill_draw_dsc->color, LV_OPA_10);
fill_draw_dsc->opa = LV_OPA_COVER;
}
}
}
}
void lv_create_main_gui(void) {
table = lv_table_create(lv_screen_active());
// Inserts or updates all table values
update_table_values();
// Set a smaller height to the table. It will make it scrollable
lv_obj_set_height(table, 200);
lv_obj_center(table);
// Add an event callback to apply some custom drawing
lv_obj_add_event_cb(table, draw_event_cb, LV_EVENT_DRAW_TASK_ADDED, NULL);
lv_obj_add_flag(table, LV_OBJ_FLAG_SEND_DRAW_TASK_EVENTS);
// Create floating button
lv_obj_t * float_button = lv_button_create(lv_screen_active());
lv_obj_set_size(float_button, 50, 50);
lv_obj_add_flag(float_button, LV_OBJ_FLAG_FLOATING);
lv_obj_align(float_button, LV_ALIGN_BOTTOM_RIGHT, -15, -15);
lv_obj_add_event_cb(float_button, float_button_event_cb, LV_EVENT_CLICKED, NULL);
lv_obj_set_style_radius(float_button, LV_RADIUS_CIRCLE, 0);
lv_obj_set_style_bg_image_src(float_button, LV_SYMBOL_REFRESH, 0);
lv_obj_set_style_text_font(float_button, lv_theme_get_font_large(float_button), 0);
lv_obj_set_style_bg_color(float_button, lv_palette_main(LV_PALETTE_GREEN), LV_PART_MAIN);
}
void get_date_and_time() {
if (WiFi.status() == WL_CONNECTED) {
HTTPClient http;
// Construct the API endpoint
String url = String("http://worldtimeapi.org/api/timezone/") + timezone;
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("Time information:");
//Serial.println(payload);
// Parse the JSON to extract the time
JsonDocument doc;
DeserializationError error = deserializeJson(doc, payload);
if (!error) {
const char* datetime = doc["datetime"];
//Serial.println("Datetime: " + String(datetime));
// Split the datetime into date and time
String datetimeStr = String(datetime);
int splitIndex = datetimeStr.indexOf('T');
current_date = datetimeStr.substring(0, splitIndex);
current_time = datetimeStr.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);
// Set analog read resolution
analogReadResolution(12);
// 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());
I2CBME.begin(I2C_SDA, I2C_SCL, 100000);
bool status;
// Passing a &Wire2 to set custom I2C ports
status = bme.begin(0x76, &I2CBME);
if (!status) {
Serial.println("Could not find a valid BME280 sensor, check wiring!");
while (1);
}
// Start LVGL
lv_init();
// Register print function for debugging
lv_log_register_print_cb(log_print);
// Start the SPI for the touchscreen and init the touchscreen
touchscreenSPI.begin(XPT2046_CLK, XPT2046_MISO, XPT2046_MOSI, XPT2046_CS);
touchscreen.begin(touchscreenSPI);
// Set the Touchscreen rotation in landscape mode
// Note: in some displays, the touchscreen might be upside down, so you might need to set the rotation to 0: touchscreen.setRotation(0);
touchscreen.setRotation(2);
// 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);
// Initialize an LVGL input device object (Touchscreen)
lv_indev_t * indev = lv_indev_create();
lv_indev_set_type(indev, LV_INDEV_TYPE_POINTER);
// Set the callback function to read Touchscreen input
lv_indev_set_read_cb(indev, touchscreen_read);
// 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 l’heure sur Internet et afficher toutes les données sur un tableau. Vous pouvez également passer directement à la section Démonstration.
Y compris les bibliothèques
Vous devez inclure les bibliothèques lvgl, TFT_eSPI et XPT2046_Touchscreen pour communiquer et afficher du texte à l’écran.
#include
#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
Pour utiliser le BME280, nous devons inclure les bibliothèques suivantes.
#include
#include
#include
Insérez vos informations d’identification et votre fuseau horaire
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 fuseau horaire dans la variable timezone au début du code (liste de tous les fuseaux horaires disponibles).
const char* timezone = "Europe/Lisbon";
Déclaration d’autres variables
Nous devons créer une instance I2C sur des broches I2C personnalisées et un objet Adafruit_BME280 pour faire référence au capteur.
#define I2C_SDA 27
#define I2C_SCL 22
#define SEALEVELPRESSURE_HPA (1013.25)
TwoWire I2CBME = TwoWire(0);
Adafruit_BME280 bme;
Contenu associé : Communication ESP32 I2C : broches définies, interfaces de bus multiples et périphériques (Arduino IDE)
Notre code est prêt à afficher la température en degrés Celsius ou Fahrenheit. Pour choisir l’unité souhaitée, vous pouvez définir la valeur de la variable TEMP_CELSIUS. Il est réglé sur 1 par défaut pour afficher la température en degrés Celsius.
#define TEMP_CELSIUS 1
Si vous souhaitez plutôt afficher en degrés Fahrenheit, réglez-le sur 0.
#define TEMP_CELSIUS 0
Créez un objet table LVGL, afin que nous puissions y accéder ultérieurement dans toutes les fonctions.
static lv_obj_t * table;
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());
Initialisation BME280
Les lignes suivantes initialisent le capteur sur le bus I2C créé :
I2CBME.begin(I2C_SDA, I2C_SCL, 100000);
bool status;
// Passing a &Wire2 to set custom I2C ports
status = bme.begin(0x76, &I2CBME);
if (!status) {
Serial.println("Could not find a valid BME280 sensor, check wiring!");
while (1);
}
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);
Préparation de l’écran tactile
Initialisez l’écran tactile.
// Start the SPI for the touchscreen and init the touchscreen
touchscreenSPI.begin(XPT2046_CLK, XPT2046_MISO, XPT2046_MOSI, XPT2046_CS);
touchscreen.begin(touchscreenSPI);
// Set the Touchscreen rotation in landscape mode
// Note: in some displays, the touchscreen might be upside down
// so you might need to set the rotation to 0: touchscreen.setRotation(0);
touchscreen.setRotation(2);
Calibrage de l’écran tactile
Sur la fonction touchscreen_read(), nous ajustons les points de l’écran tactile pour les calibrer avec l’affichage. Vous devez insérer les valeurs d’étalonnage sur les lignes suivantes. Consultez ce didacticiel pour obtenir les valeurs d’étalonnage de votre écran.
// REPLACE WITH YOUR OWN CALIBRATION VALUES » https://Raspberryme.com/touchscreen-calibration/
alpha_x = -0.000;
beta_x = 0.090;
delta_x = -33.771;
alpha_y = 0.066;
beta_y = 0.000;
delta_y = -14.632;
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 vérifier les é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_date_and_time()
Nous créons deux variables globales current_date et current_time au début du code pour enregistrer la date et l’heure actuelles.
String current_date;
String current_time;
Créez une fonction appelée get_date_and_time() qui envoie une requête à WorldTimeAPI et met à jour les variables current_date et current_time avec la date et l’heure actuelles.
void get_date_and_time() {
if (WiFi.status() == WL_CONNECTED) {
HTTPClient http;
// Construct the API endpoint
String url = String("http://worldtimeapi.org/api/timezone/") + timezone;
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("Time information:");
//Serial.println(payload);
// Parse the JSON to extract the time
JsonDocument doc;
DeserializationError error = deserializeJson(doc, payload);
if (!error) {
const char* datetime = doc["datetime"];
// 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);
current_time = datetime_str.substring(splitIndex + 1, splitIndex + 9); // Extract time portion
hour = current_time.substring(0, 2).toInt();
minute = current_time.substring(3, 5).toInt();
second = current_time.substring(6, 8).toInt();
} else {
Serial.print("deserializeJson() failed: ");
Serial.println(error.c_str());
}
}
} else {
Serial.printf("GET request failed, error: %s\n", http.errorToString(httpCode).c_str());
sync_time_date = true;
}
http.end(); // Close connection
} else {
Serial.println("Not connected to Wi-Fi");
}
}
Nous n’aborderons pas le fonctionnement des requêtes HTTP. Si vous souhaitez en savoir plus, vous pouvez consulter le tutoriel suivant : ESP32 HTTP GET avec Arduino IDE.
Préparation de l’interface graphique
Nous créons la table dans la fonction lv_create_main_gui().
void lv_create_main_gui(void) {
Nous pouvons créer un objet table en utilisant la fonction lv_table_create() comme suit.
table = lv_table_create(lv_screen_active());
Ensuite, nous écrivons une fonction appelée update_table_values() qui remplit le tableau avec les lectures. Nous examinerons cette fonction dans un instant.
update_table_values();
Réglez la hauteur de la table et centrez-la sur l’écran.
// Set a smaller height to the table. It will make it scrollable
lv_obj_set_height(table, 200);
lv_obj_center(table);
Ajoutez un rappel et un indicateur à la table. Ceux-ci nous permettront de dessiner le tableau avec un style spécifique (couleurs différentes pour les en-têtes et rangées grises et blanches alternées).
// Add an event callback to apply some custom drawing
lv_obj_add_event_cb(table, draw_event_cb, LV_EVENT_DRAW_TASK_ADDED, NULL);
lv_obj_add_flag(table, LV_OBJ_FLAG_SEND_DRAW_TASK_EVENTS);
Création du bouton flottant
Pourtant, dans la fonction lv_create_main_gui(), nous créons le bouton flottant. Il s’agit d’un bouton ordinaire, mais il est circulaire et avec un style spécifique.
// Create floating button
lv_obj_t * float_button = lv_button_create(lv_screen_active());
lv_obj_set_size(float_button, 50, 50);
lv_obj_add_flag(float_button, LV_OBJ_FLAG_FLOATING);
lv_obj_align(float_button, LV_ALIGN_BOTTOM_RIGHT, -15, -15);
lv_obj_add_event_cb(float_button, float_button_event_cb, LV_EVENT_CLICKED, NULL);
lv_obj_set_style_radius(float_button, LV_RADIUS_CIRCLE, 0);
lv_obj_set_style_bg_image_src(float_button, LV_SYMBOL_REFRESH, 0);
lv_obj_set_style_text_font(float_button, lv_theme_get_font_large(float_button), 0);
lv_obj_set_style_bg_color(float_button, lv_palette_main(LV_PALETTE_GREEN), LV_PART_MAIN);
Le bouton cliqué déclenchera la fonction float_button_event_cb.
lv_obj_add_event_cb(float_button, float_button_event_cb, LV_EVENT_CLICKED, NULL);
Pour ajouter le symbole d’actualisation au bouton, nous utilisons la fonction lv_obj_set_style_bg_image_src(). Pour ajouter le symbole d’actualisation, nous devons utiliser LV_SYMBOL_REFRESH.
lv_obj_set_style_bg_image_src(float_button, LV_SYMBOL_REFRESH, 0);
Ajout de données au tableau
C’est dans update_table_values() que nous ajouterons des données à la table.
static void update_table_values(void) {
Cette fonction est appelée lorsque nous créons l’interface graphique dans la fonction lv_create_main_gui(), et lorsque vous cliquez sur le bouton de la fonction float_button_event_cb().
Tout d’abord, nous commençons par obtenir les lectures du capteur BME280 ainsi que la luminosité du LDR.
// Get the latest temperature reading in Celsius or Fahrenheit
#if TEMP_CELSIUS
float bme_temp = bme.readTemperature();
const char degree_symbol[] = "\u00B0C";
#else
float bme_temp = 1.8 * bme.readTemperature() + 32;
const char degree_symbol[] = "\u00B0F";
#endif
String bme_temp_value = String(bme_temp) + degree_symbol;
String bme_humi_value = String(bme.readHumidity()) + "%";
String bme_press_value = String(bme.readPressure() / 100.0F) + " hPa";
String ldr_value = String(analogRead(LDR_PIN));
Les lectures sont enregistrées sur les variables bme_temp_value, bme_humi_value, bme_pres_value et ldr_value. Nous mettons à jour les variables temporelles en appelant la fonction get_date_and_time() que nous avons vue précédemment.
// Get the time from WorldTimeAPI
get_date_and_time();
Après avoir récupéré toutes les données, nous pouvons enfin commencer à ajouter des lignes au tableau. Pour cela, nous pouvons utiliser la fonction lv_table_set_cell_value(). Cette fonction accepte comme argument le tableau auquel vous faites référence, le numéro de ligne, le numéro de colonne et les données que vous souhaitez afficher.
Les lignes suivantes remplissent la première colonne.
// Fill the first column
lv_table_set_cell_value(table, 0, 0, "Data");
lv_table_set_cell_value(table, 1, 0, "Temperature");
lv_table_set_cell_value(table, 2, 0, "Humidity");
lv_table_set_cell_value(table, 3, 0, "Pressure");
lv_table_set_cell_value(table, 4, 0, "Luminosity");
lv_table_set_cell_value(table, 5, 0, "Date");
lv_table_set_cell_value(table, 6, 0, "Time");
lv_table_set_cell_value(table, 7, 0, "IP Address");
Enfin, nous remplissons la deuxième colonne avec les valeurs des capteurs, la date et l’heure, ainsi que l’adresse IP de l’ESP32.
// Fill the second column
lv_table_set_cell_value(table, 0, 1, "Value");
lv_table_set_cell_value(table, 1, 1, bme_temp_value.c_str());
lv_table_set_cell_value(table, 2, 1, bme_humi_value.c_str());
lv_table_set_cell_value(table, 3, 1, bme_press_value.c_str());
lv_table_set_cell_value(table, 4, 1, ldr_value.c_str());
lv_table_set_cell_value(table, 5, 1, current_date.c_str());
lv_table_set_cell_value(table, 6, 1, current_time.c_str());
lv_table_set_cell_value(table, 7, 1, WiFi.localIP().toString().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.
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 données actuelles s’afficheront à l’écran, comme indiqué dans l’image ci-dessous.

Pour mettre à jour les données du tableau, il vous suffit de cliquer sur le bouton Actualiser.

Vous pouvez couvrir le LDR avec votre doigt pour voir les valeurs de luminosité changer.
Remarque : sur de nombreuses cartes CYD, le LDR ne fonctionnera pas comme prévu sans modifier le circuit interne. Donc, si vous n’obtenez que 0, c’est « normal ».

Le tableau est déroulant. Vous pouvez faire défiler vers le bas pour vérifier la date et l’heure de la dernière mise à jour.
Dépannage
Si vous rencontrez des problèmes pour ouvrir le site Web WorldTimeAPI ou si votre requête HTTP ne parvient pas à récupérer l’heure, vous pouvez modifier la ligne suivante 252.
String url = String("http://worldtimeapi.org/api/timezone/") + timezone;
De leur nom de domaine (worldtimeapi.org) à leur adresse IP comme suit :
String url = String("http://213.188.196.246/api/timezone/") + timezone;
Conclusion
Dans ce didacticiel, vous avez appris à afficher les données du capteur sur une table réactive sur la 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 :

-
Heltec ESP32 LoRa V4 Kit de capteur en verre trempé avec carte de développement BME280 ESP32 S3 SX1262 LoRa Kit de surveillance environnementale tout-en-un pour nœud Meshtastic IoT sans fil
-
AZDelivery 5 x BME280 Barometric Temperature Humidity Air Pressure Sensor Module compatible avec Arduino et Raspberry Pi incluant un eBook!
