Serveur Web ESP32 : graphiques avec données historiques (fichier CSV)

Serveur Web ESP32 : graphiques avec données historiques (fichier CSV)

Découvrez comment créer un serveur Web ESP32 qui affiche des graphiques avec des données chargées à partir d’un fichier .csv enregistré sur une carte microSD.

Dans ce projet, nous allons construire un enregistreur de données ESP32 utilisant un capteur BME280. Il prend des mesures de température, d’humidité et de pression et enregistre ces valeurs avec un horodatage dans un fichier .cvs sur une carte microSD. L’ESP32 héberge également un serveur Web avec des graphiques en temps réel qui charge les données stockées dans le fichier .csv. La carte ESP32 sera programmée à l’aide de l’IDE Arduino.

Serveur Web ESP32 : graphiques avec données historiques (charger le fichier .csv)

Vous aimerez peut-être lire : Construire un serveur Web ESP32 : le guide complet pour les débutants (Arduino IDE).

Aperçu du projet

L’image suivante montre la page Web que vous allez créer pour ce projet.

Graphique ESP32 Serveur Web Arduino IDE Graphique historique Démonstration du fichier de données de journal CSV

Voici les principales caractéristiques de ce projet :

  • L’ESP32 est équipé d’un capteur BME280 qui prend des mesures toutes les 60 secondes et les stocke sur une carte microSD dans un fichier .csv ;
  • L’ESP32 héberge une page Web qui affiche 3 graphiques en temps réel : température, humidité et pression ;
  • Sur la page Web, vous pouvez télécharger ou supprimer le fichier .csv sur votre appareil ;
  • Les graphiques peuvent être zoomés et mettre en évidence chaque valeur ;
  • La page Web est entièrement réactive pour le Web, elle s’exécute donc sur n’importe quelle taille d’écran.

Pour plus de simplicité, nous stockerons le HTML et le CSS de la page Web dans une variable du croquis Arduino, mais vous pouvez utiliser le système de fichiers LittleFS si vous souhaitez des fichiers séparés.

Conditions préalables

Avant de poursuivre ce tutoriel, vous devez avoir installé le module complémentaire ESP32 dans votre IDE Arduino :

La lecture de ces autres guides pourrait également vous être utile :

Pièces requises

Pour ce tutoriel, vous avez besoin des pièces suivantes :

Vous pouvez utiliser les liens précédents ou vous rendre directement sur MakerAdvisor.com/tools pour trouver toutes les pièces pour vos projets au meilleur prix !

1779372009 796 Serveur Web ESP32 graphiques avec donnees historiques fichier CSV

Diagramme schématique – ESP32 avec BME280 et carte MicroSD

Nous allons utiliser la communication I2C avec le module capteur BME280 et SPI pour la carte microSD.

Câblez le capteur et le module de carte microSD à l’aide du schéma suivant (ou utilisez les tableaux ci-dessous pour vérifier l’affectation des broches).

Diagramme ESP32 du serveur Web Arduino IDE Schéma de circuit de câblage Carte MicroSD BME280

Connectez le capteur BME280 aux broches I2C par défaut de l’ESP32 :

BME280 ESP32
SCK (broche SCL) GPIO22
SDI (broche SDA) GPIO21

Le module de carte microSD communique à l’aide du protocole de communication SPI. Vous pouvez le connecter à l’ESP32 en utilisant les broches SPI par défaut.

Module de carte MicroSD ESP32
3V3 3,3 V
CS GPIO5
MOSI GPIO23
CLK GPIO18
MISO GPIO19
GND GND

Le circuit final devrait ressembler à ceci :

Graphique ESP32 Serveur Web Arduino IDE Graphique historique CSV Log Data File Circuit

Avant de poursuivre le didacticiel, assurez-vous de formater votre carte microSD en FAT32 (en savoir plus sur notre guide de la carte microSD). Ensuite, insérez la carte microSD dans le module.

Installer les bibliothèques requises dans l’IDE Arduino

Pour ce projet, vous devez installer les bibliothèques suivantes :

Vous pouvez installer ces bibliothèques dans Arduino Library Manager. Ouvrez le gestionnaire de bibliothèque en cliquant sur l’icône Bibliothèque dans la barre latérale gauche.

Recherchez ESPAsyncWebServer et installez ESPAsyncWebServer par ESP32Async.

Installation de l'IDE Arduino ESPAsyncWebServer ESP32

Recherchez AsyncTCP et installez AsyncTCP par ESP32Async.

Installation de l'IDE Arduino AsyncTCP ESP32

Recherchez Adafruit BME280 et installez la bibliothèque :

Installation de la bibliothèque de capteurs Adafruit BME280 Arduino IDE

Enfin, recherchez Adafruit Unified Sensor et installez cette bibliothèque.

Installation de l'IDE Arduino de la bibliothèque de capteurs unifiées Adafruit

Arduino Sketch – Graphiques du serveur Web ESP32 avec données historiques (charger le fichier .csv)

Le code suivant crée un serveur Web qui dessert une page Web qui charge les données du capteur stockées dans le fichier .csv de la carte microSD dans des graphiques en temps réel.

/*
  Rui Santos & Sara Santos - Raspberryme.com
  Complete project details at https://Raspberryme.com/esp32-web-server-charts-historical-data/
  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.
*/
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

// REPLACE WITH YOUR NETWORK CREDENTIALS
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

// BME280 GPIOs
#define SDA_PIN 21
#define SCL_PIN 22

// MicroSD Card Module GPIOs
#define SD_CS   5
#define SD_MOSI 23
#define SD_MISO 19
#define SD_SCK  18

// NTP server
const char* ntpServer = "pool.ntp.org";
const long gmtOffset_sec = 3600;      // Change to your timezone
const int daylightOffset_sec = 0;

// Timer to take new readings
unsigned long previousMillis = 0;
const long interval = 60000;  // 60 seconds

// CSV filename
const char* dataFile = "/bme280_log.csv";

// AsyncWebServer Web Server
AsyncWebServer server(80);
// BME280
Adafruit_BME280 bme;

// Get Time
String getTimeStr() {
  struct tm timeinfo;
  if (!getLocalTime(&timeinfo)) return "00:00:00";
  char buf[9]; sprintf(buf, "%02d:%02d:%02d", timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec);
  return String(buf);
}

// Get Date
String getDateStr() {
  struct tm timeinfo;
  if (!getLocalTime(&timeinfo)) return "1970-01-01";
  char buf[11]; sprintf(buf, "%04d-%02d-%02d", timeinfo.tm_year+1900, timeinfo.tm_mon+1, timeinfo.tm_mday);
  return String(buf);
}

// Initialize MicroSD Card and create the .csv file
void initSD() {
  SPI.begin(SD_SCK, SD_MISO, SD_MOSI, SD_CS);
  if (!SD.begin(SD_CS)) { Serial.println("SD Card Failed"); return; }
  
  if (!SD.exists(dataFile)) {
    File f = SD.open(dataFile, FILE_WRITE);
    if (f) { f.println("temp_c,temp_f,humidity,pressure,time,day"); f.close(); }
  }
}

// Log BME280 data on the MicroSD Card
void logData() {
  float tempC = bme.readTemperature();
  float tempF = tempC * 9.0 / 5.0 + 32.0;
  float hum = bme.readHumidity();
  float press = bme.readPressure() / 100.0F;

  File file = SD.open(dataFile, FILE_APPEND);
  if (file) {
    file.printf("%.2f,%.2f,%.2f,%.2f,%s,%s\n", 
                tempC, tempF, hum, press, getTimeStr().c_str(), getDateStr().c_str());
    file.close();
  }
}

void setup() {
  Serial.begin(115200);
  
  // Initialize BME280 Sensor
  Wire.begin(SDA_PIN, SCL_PIN);
  if (!bme.begin(0x76)) { 
    Serial.println("BME280 not found!");
    while(1); 
  }

  // Start the Wi-Fi connection
  WiFi.begin(ssid, password);
  Serial.print("Connecting to Wi-Fi");
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("\nWi-Fi Connected!");
  // Print the ESP32 IP Address
  Serial.print("Access ESP32 IP Address: http://");
  Serial.println(WiFi.localIP());

  // Configure NTP time
  configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
  delay(2000);

  // Initialize MicroSD Card
  initSD();

  // Root URL handler for the mains HTML web page
  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
  String html = R"rawliteral(



  ESP32 Charts with Data Logger
  
  
  
  
  
  


  
    
    

New readings are added to your chart automatically, you don't need to refresh the web page.

Refresh Charts Download CSV Delete All Data Reset All Zoom

Humidity

Pressure

Latest Reading

  
  


)rawliteral";
    request->send(200, "text/html; charset=UTF-8", html);
  });

  // Download .csv file stored on MicroSD Card
  server.on("/download", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(SD, dataFile, "text/csv", true);
  });

  // Delete .csv file stored on MicroSD Card
  server.on("/delete", HTTP_POST, [](AsyncWebServerRequest *request){
    if (SD.exists(dataFile)) SD.remove(dataFile);
    File f = SD.open(dataFile, FILE_WRITE);
    if (f) { f.println("temp_c,temp_f,humidity,pressure,time,day"); f.close(); }
    request->send(200);
  });

  server.begin();
  Serial.println("ESP32 Web Server: Charts with Historical Data Ready!");
}

void loop() {
  // Timer
  if (millis() - previousMillis >= interval) {
    previousMillis = millis();
    logData();
  }
  delay(10);
}

Afficher le code brut

Avec les bibliothèques mentionnées précédemment installées dans votre IDE Arduino, il vous suffit d'insérer vos informations d'identification réseau dans les lignes suivantes du code, et cela fonctionnera immédiatement.

const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_SSID";

Comment fonctionne le code

Continuez à lire pour découvrir comment fonctionne le code ou passez à la section Démonstration.

Y compris les bibliothèques

Tout d'abord, incluez les bibliothèques requises pour vous connecter au Wi-Fi, créer le serveur Web, lire le capteur BME280 et communiquer avec la carte SD.

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

Informations d'identification réseau

Insérez vos informations d'identification réseau dans les variables suivantes afin que l'ESP32 se connecte à votre réseau.

// REPLACE WITH YOUR NETWORK CREDENTIALS
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_SSID";

GPIO

Définissez les GPIO qui seront utilisés pour la communication I2C avec le capteur BME280 et la communication SPI avec le module de carte microSD.

// BME280 GPIOs
#define SDA_PIN 21
#define SCL_PIN 22

// MicroSD Card Module GPIOs
#define SD_CS   5
#define SD_MOSI 23
#define SD_MISO 19
#define SD_SCK  18

Serveur NTP

Nous demanderons l'heure à pool.ntp.org, qui est un cluster de serveurs de temps que tout le monde peut utiliser pour demander l'heure (lisez notre guide Client-Serveur NTP ESP32 : Obtenir la date et l'heure).

const char* ntpServer = "pool.ntp.org";
const long gmtOffset_sec = 3600;      // Change to your timezone
const int daylightOffset_sec = 0;

Minuteur

Cette minuterie prendra de nouvelles lectures toutes les 60 secondes ; vous pouvez augmenter ce nombre pour une application réelle. À des fins de test et pour collecter plus de valeurs dans un court laps de temps, cette durée est définie sur 60 secondes.

unsigned long previousMillis = 0;
const long interval = 60000;  // 60 seconds

Fichier CSV

Le fichier stocké sur la carte microSD porte le nom suivant : bme280_log.csv.

const char* dataFile = "/bme280_log.csv";

Création d'un objet serveur

Créez un objet AsyncWebServer appelé serveur sur le port 80.

AsyncWebServer server(80);

Création d'un objet BME280

Le BME280 lira les valeurs à l'aide du protocole de communication I2C. Il vous suffit de créer un objet Adafruit_BME280 appelé bme comme suit.

Adafruit_BME280 bme;

installation()

Dans le setup(), nous commençons par initialiser le moniteur série et initialiser le capteur BME280.

Serial.begin(115200);
  
// Initialize BME280 Sensor
Wire.begin(SDA_PIN, SCL_PIN);
if (!bme.begin(0x76)) { 
  Serial.println("BME280 not found!");
  while(1); 
}

Démarrez la connexion Wi-Fi et imprimez l'adresse IP ESP32 dans le moniteur série. Vous en aurez besoin plus tard pour accéder au serveur Web.

WiFi.begin(ssid, password);
Serial.print("Connecting to Wi-Fi");
while (WiFi.status() != WL_CONNECTED) {
  delay(500);
  Serial.print(".");
}
Serial.println("\nWi-Fi Connected!");
// Print the ESP32 IP Address
Serial.print("Access ESP32 IP Address: http://");
Serial.println(WiFi.localIP());

Configurez l'heure avec les paramètres que vous avez définis précédemment :

configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);

Appelez la fonction pour initialiser la carte microSD.

initSD();

Voici la fonction initSD() :

void initSD() {
  SPI.begin(SD_SCK, SD_MISO, SD_MOSI, SD_CS);
  if (!SD.begin(SD_CS)) { Serial.println("SD Card Failed"); return; }
  
  if (!SD.exists(dataFile)) {
    File f = SD.open(dataFile, FILE_WRITE);
    if (f) { f.println("temp_c,temp_f,humidity,pressure,time,day"); f.close(); }
  }
}

URL root /

Ensuite, gérez le serveur Web. Lorsque vous recevez une requête sur l'URL root (/) (cela se produit lorsque vous accédez à l'adresse IP ESP), envoyez le texte HTML stocké dans la variable html String pour afficher la page Web :

server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
  (...)
  request->send(200, "text/html; charset=UTF-8", html);
});

La variable html contient le texte avec le HTML, CSS et JavaScript pour créer la page Web.




  ESP32 Charts with Data Logger
  
  
  
  
  
  


  
    
    

New readings are added to your chart automatically, you don't need to refresh the web page.

Refresh Charts Download CSV Delete All Data Reset All Zoom

Humidity

Pressure

Latest Reading

  
  

Nombre de points de données

Par défaut, dans cet exemple, les graphiques afficheront un maximum de 1 200 points de données. Vous pouvez modifier cela dans la ligne suivante.

const displayData = allData.slice(-1200);

Notez que si vous augmentez beaucoup cette valeur, le chargement de toutes les données dans les graphiques peut prendre plus de temps.

Télécharger le fichier CSV /télécharger

Cette route envoie le fichier .csv stocké dans la carte microSD au client connecté (pour charger les données pour créer les graphiques).

server.on("/control", HTTP_GET, [](AsyncWebServerRequest *request) {
  if (request->hasParam("state")) {
    int state = request->getParam("state")->value().toInt();
    digitalWrite(ledPin, state ? HIGH : LOW);
    Serial.printf("LED set to %s\n", state ? "ON" : "OFF");
  }
  request->send(200, "text/plain", "OK");
});

Supprimer le fichier CSV/supprimer

Cette route supprime le fichier .csv stocké dans la carte microSD.

server.on("/delete", HTTP_POST, [](AsyncWebServerRequest *request){
    if (SD.exists(dataFile)) SD.remove(dataFile);
    File f = SD.open(dataFile, FILE_WRITE);
    if (f) { f.println("temp_c,temp_f,humidity,pressure,time,day"); f.close(); }
    request->send(200);
  });

Initialiser le serveur

Enfin, appelez la méthode Begin() sur l'objet serveur pour initialiser le serveur.

server.begin();

boucle()

Dans la fonction loop(), nous avons une minuterie qui appelle la fonction logData() pour obtenir de nouvelles lectures à chaque valeur d'intervalle (par défaut toutes les 60 secondes).

if (millis() - previousMillis >= interval) {
  previousMillis = millis();
  logData();
}

La fonction logData() prend de nouvelles lectures du capteur BME280 et les stocke dans des variables auxiliaires avec un horodatage du serveur NTP. Enfin, il ajoute ces lectures à la dernière ligne du fichier .csv.

void logData() {
  float tempC = bme.readTemperature();
  float tempF = tempC * 9.0 / 5.0 + 32.0;
  float hum = bme.readHumidity();
  float press = bme.readPressure() / 100.0F;

  File file = SD.open(dataFile, FILE_APPEND);
  if (file) {
    file.printf("%.2f,%.2f,%.2f,%.2f,%s,%s\n", 
                tempC, tempF, hum, press, getTimeStr().c_str(), getDateStr().c_str());
    file.close();
  }
}

Démonstration

Après avoir inséré vos informations d'identification réseau, téléchargez le code sur la carte ESP32. Après le téléchargement, ouvrez le moniteur série à une vitesse de transmission de 115 200 bauds et appuyez sur le bouton ESP32 RST.

Ouvrir le moniteur série Arduino 2

L'adresse IP de l'ESP32 sera imprimée dans le moniteur série.

Graphique ESP32 Serveur Web Démarrer le moniteur série Arduino IDE

Ouvrez n'importe quel navigateur sur votre réseau local et saisissez l'adresse IP ESP32. La page Web suivante se chargera.

ESP32 Chart Web Server Première page Web chargée sans données Arduino IDE

En haut de la page web, vous disposez de 4 boutons :

  • Actualiser les graphiques : les graphiques sont mis à jour en temps réel, vous n'avez donc pas besoin d'utiliser ce bouton. Cependant, en cas d'échec du chargement du fichier .csv depuis la carte microSD, vous pouvez utiliser ce bouton ;
  • Télécharger CSV : télécharge le fichier .csv stocké sur votre carte microSD ;
  • Supprimer toutes les données : supprime toutes les données stockées dans le fichier .csv ;
  • Réinitialiser tout le zoom : vous pouvez zoomer sur les graphiques pour voir les valeurs plus clairement, vous pouvez utiliser ce bouton pour effectuer un zoom arrière et revenir à la première vue.
Boutons IDE Arduino du serveur Web graphique ESP32

Par défaut, le graphique de température affiche les valeurs en degrés Celsius. Il y a un bouton pour passer aux degrés Fahrenheit.

Graphique ESP32 Température du serveur Web Celsius Fahrenheit commutateur Arduino IDE

Avec votre curseur, vous pouvez sélectionner une section spécifique du graphique pour zoomer (cela fonctionne également sur les appareils dotés d'un écran tactile. Vous pouvez simplement pincer pour zoomer).

Serveur Web graphique ESP32 Zoom avant la valeur Arduino IDE

Ensuite, ce graphique sera agrandi. Vous pouvez également sélectionner les valeurs pour voir toutes les informations mises en évidence comme illustré ci-dessous. Pour effectuer un zoom arrière, vous pouvez double-cliquer sur le graphique ou utiliser le bouton Réinitialiser tout le zoom en haut de la page Web.

Serveur Web de graphiques ESP32 Section agrandie mettant en surbrillance Valeur Arduino IDE

Ensuite, vous avez le graphique de pression, vous pouvez ignorer les données, car je testais juste le projet pendant quelques jours en l'allumant/éteignant.

Graphique ESP32 Valeurs de pression du serveur Web Arduino IDE

Enfin, au bas de la page Web, il affiche uniquement les dernières lectures des capteurs.

ESP32 Chart Web Server Température humidité pression dernières valeurs

Conclusion

Dans ce didacticiel, vous avez appris à créer un projet qui enregistre les données de température, d'humidité et de pression avec des horodatages dans un fichier .csv sur une carte microSD. Vous avez appris à faire en sorte que ces valeurs affichent des graphiques sur une page Web servie par l'ESP32.

Si vous avez aimé ce projet, vous aimerez peut-être également ces autres tutoriels :

Si vous souhaitez en savoir plus sur la construction de serveurs web avec l'ESP32 à partir de zéro, nous vous recommandons de jeter un œil à notre eBook dédié à ce sujet :

Merci d'avoir lu.

Cette vidéo vous emmène dans l'histoire de Raspberry Pi :

Youtube video

  • Ulegqin ESP32 S3 ESP-S3-Devkitc-1 N16R8 Carte mère avec IPEX Interface ESP32 S3 Module avec WiFi, Bluetooth 5.0 Extension de mémoire Externe Typ-C Interface Compatible avec Arduino(2 Pièces)
  • diymore Carte de développement pour ESP32-S3 CAM avec caméra OV3660, module ESP32-S3 N16R8, flash 16 Mo, PSRAM 8 Mo, double USB-C (OTG/TTL), WiFi, Bluetooth 5 LE, microSD, connecteur d'antenne IPEX