Serveur Web ESP32 : définir la programmation de la minuterie (Arduino IDE)

Serveur Web ESP32 : définir la programmation de la minuterie (Arduino IDE)

Dans ce projet, nous allons construire un serveur Web avec l’ESP32 qui vous permet de contrôler une LED en planifiant une minuterie avec une action ON/OFF pour n’importe quelle durée (secondes, minutes ou heures). La page Web comporte également deux boutons que vous pouvez utiliser pour allumer ou éteindre la LED immédiatement. L’ESP32 sera programmé à l’aide de l’IDE Arduino.

Programmeur de minuterie du serveur Web ESP32 IDE Arduino

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.

Programmation du serveur Web ESP32 - Présentation du projet Arduino IDE Core

Voici les principales fonctionnalités de ce serveur Web :

  • Étiquette de texte de l’état actuel de la LED : « GPIO est activé » / « GPIO est désactivé »
  • Contrôle instantané des LED : boutons allumer/éteindre
  • Formulaire HTML Définir la minuterie : vous pouvez définir l’action (allumer/éteindre), l’unité de temps et la durée de la minuterie.
  • État de la minuterie et temps restant pour effectuer l’action sélectionnée
  • Bouton Annuler la minuterie

Pour plus de simplicité, nous enregistrerons le HTML et le CSS pour créer la page Web dans une variable du croquis Arduino, mais vous pouvez utiliser le système de fichiers LittleFS.

Conditions préalables

Avant de suivre ce guide, vous devez installer le module complémentaire ESP32 Core dans votre IDE Arduino. Suivez le guide suivant pour l’installer, si ce n’est pas déjà fait :

Vous aurez également besoin d’un modèle de carte de développement ESP32 de votre choix.

Installer les bibliothèques requises dans l’IDE Arduino

Nous allons construire le serveur Web en utilisant 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

Ensuite, installez la bibliothèque AsyncTCP. Recherchez AsyncTCP et installez AsyncTCP par ESP32Async.

Installation de l'IDE Arduino AsyncTCP ESP32

Serveur Web ESP32 : Programmation de la minuterie – Arduino Sketch

Le code suivant crée un serveur Web qui dessert une page Web qui vous permet de planifier une minuterie pour allumer/éteindre une LED pendant une durée sélectionnée.

/*********
  Rui Santos & Sara Santos - Raspberryme.com
  Complete project details at https://Raspberryme.com/esp32-web-server-timer-schedule-arduino/
  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 

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

// LED connected to GPIO 5
const int ledPin = 5;

// Global variables
AsyncWebServer server(80);

TimerHandle_t gpioTimer = NULL;
// Timer action: 1 = ON, 0 = OFF
int targetAction = -1;

TickType_t timerStartTick = 0;
uint64_t totalDurationTicks = 0;

// HTML Web Page
const char index_html[] PROGMEM = R"rawliteral(



  ESP32 Web Server - Timer Schedule
  
  


  
  
    

GPIO is Loading...

TURN ON TURN OFF

Set Timer

Timer Status: No active timers

CANCEL TIMER

)rawliteral"; // Timer Callback - Turns the LED on or off depending on the action selected void IRAM_ATTR timerCallback(TimerHandle_t xTimer) { if (targetAction != -1) { digitalWrite(ledPin, targetAction ? HIGH : LOW); Serial.printf("Timer finished: GPIO %d set to %s\n", ledPin, targetAction ? "HIGH (ON)" : "LOW (OFF)"); } targetAction = -1; timerStartTick = 0; totalDurationTicks = 0; } void setup() { Serial.begin(115200); delay(1000); // Define ledPin as an OUTPUT and initialize it off (LOW) pinMode(ledPin, OUTPUT); digitalWrite(ledPin, LOW); // Create a timer and assign the timerCallback function gpioTimer = xTimerCreate("GPIO_Timer", pdMS_TO_TICKS(1000), pdFALSE, 0, timerCallback); // 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()); // Root URL handler server.on("/", HTTP_GET, [](AsyncWebServerRequest *request) { request->send_P(200, "text/html", index_html); }); // Instant LED control 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"); }); // Get current LED state server.on("/led-state", HTTP_GET, [](AsyncWebServerRequest *request) { int state = digitalRead(ledPin); request->send(200, "application/json", "{\"state\":" + String(state) + "}"); }); // Set the timer duration to perform the action selected server.on("/set-timer", HTTP_POST, [](AsyncWebServerRequest *request) { if (request->hasParam("action", true) && request->hasParam("duration", true) && request->hasParam("unit", true)) { targetAction = request->getParam("action", true)->value().toInt(); int dur = request->getParam("duration", true)->value().toInt(); String unit = request->getParam("unit", true)->value(); uint64_t durationSeconds = 0; if (unit == "s") durationSeconds = (uint64_t)dur; else if (unit == "m") durationSeconds = (uint64_t)dur * 60ULL; else if (unit == "h") durationSeconds = (uint64_t)dur * 3600ULL; if (durationSeconds > 0) { if (xTimerIsTimerActive(gpioTimer)) xTimerStop(gpioTimer, 0); uint64_t tempTicks = durationSeconds * (uint64_t)configTICK_RATE_HZ; TickType_t timerTicks = (tempTicks > 0xFFFFFFFFULL) ? 0xFFFFFFFFULL : (TickType_t)tempTicks; timerStartTick = xTaskGetTickCount(); totalDurationTicks = tempTicks; xTimerChangePeriod(gpioTimer, timerTicks, 0); xTimerStart(gpioTimer, 0); Serial.printf("Timer scheduled: GPIO %d will be set to %s in %llu seconds\n", ledPin, targetAction ? "ON" : "OFF", durationSeconds); } } request->redirect("/"); }); // Cancel Timer server.on("/cancel-timer", HTTP_POST, [](AsyncWebServerRequest *request) { // Stop the active timer if (xTimerIsTimerActive(gpioTimer)) { xTimerStop(gpioTimer, 0); Serial.println("Timer cancelled"); } targetAction = -1; timerStartTick = 0; totalDurationTicks = 0; request->send(200, "text/plain", "OK"); }); // Timer Status - Returns the remaining time in seconds server.on("/timer-status", HTTP_GET, [](AsyncWebServerRequest *request) { if (targetAction != -1 && xTimerIsTimerActive(gpioTimer) && totalDurationTicks > 0) { // Calculate how many seconds are left for the timer to end TickType_t now = xTaskGetTickCount(); uint64_t elapsedTicks = 0; if (now >= timerStartTick) { elapsedTicks = now - timerStartTick; } else { elapsedTicks = (0xFFFFFFFFULL - timerStartTick) + now + 1; } uint64_t remainingTicks = (totalDurationTicks > elapsedTicks) ? totalDurationTicks - elapsedTicks : 0; uint64_t remainingSeconds = remainingTicks / (uint64_t)configTICK_RATE_HZ; // Return the amount of seconds left and action that will execute when the timer ends String json = "{\"status\":\"Setting GPIO "+ String(ledPin) +" to " + String(targetAction ? "ON" : "OFF") + "\","; json += "\"active\":true,"; json += "\"remaining_seconds\":" + String((unsigned long)remainingSeconds) + "}"; request->send(200, "application/json", json); } else { request->send(200, "application/json", "{\"status\":\"No active timers\",\"active\":false,\"remaining_seconds\":0}"); } }); server.begin(); Serial.println("ESP32 Web Server Timer Schedule is Ready!"); } void loop() { vTaskDelay(pdMS_TO_TICKS(100)); }

Afficher le code brut

Il vous suffit d’insérer vos informations d’identification réseau dans le 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 savoir 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 et utiliser les minuteries FreeRTOS.

#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";

Broche LED

Définissez le GPIO qui sera utilisé pour contrôler la LED. Vous pouvez modifier la variable ledPin pour contrôler n’importe quel autre GPIO.

const int ledPin = 5;

Création d’un objet serveur

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

AsyncWebServer server(80);

Minuteries

Créez des variables auxiliaires pour exécuter les minuteries.

TimerHandle_t gpioTimer = NULL;
// Timer action: 1 = ON, 0 = OFF
int targetAction = -1;

TickType_t timerStartTick = 0;
uint64_t totalDurationTicks = 0;

En savoir plus sur les minuteries FreeRTOS : ESP32 avec FreeRTOS : minuteries logicielles/interruptions de minuterie (Arduino IDE).

Page web

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

const char index_html[] PROGMEM = R"rawliteral(



  ESP32 Web Server - Timer Schedule
  
  


  
  
    

GPIO is Loading...

TURN ON TURN OFF

Set Timer

Timer Status: No active timers

CANCEL TIMER

)rawliteral";

Dans la page Web, nous créons deux boutons qui effectuent des requêtes sur les chemins d’URL suivants pour contrôler l’allumage/extinction de la LED :

  • ALLUMER : /control?state=1
  • DÉSACTIVER : /control?state=0
TURN ON
TURN OFF

L’autre section principale de la page Web est le formulaire Web HTML dans lequel vous pouvez sélectionner l’action, l’unité et la durée du minuteur. Il affiche également l’état actuel de la minuterie, le temps restant et un bouton pour annuler la minuterie.


  

Set Timer

Timer Status: No active timers

CANCEL TIMER

Fonction de rappel de minuterie

La fonction timerCallback() est le gestionnaire de minuterie unique FreeRTOS qui, lorsqu’il a expiré, active/désactive le GPIO en fonction de l’action précédemment sélectionnée sur le serveur Web.

void IRAM_ATTR timerCallback(TimerHandle_t xTimer) {
  if (targetAction != -1) {
    digitalWrite(ledPin, targetAction ? HIGH : LOW);
    Serial.printf("Timer finished: GPIO %d set to %s\n", ledPin, targetAction ? "HIGH (ON)" : "LOW (OFF)");
  }
  targetAction = -1;
  timerStartTick = 0;
  totalDurationTicks = 0;
}

installation()

Dans le setup(), nous commençons par initialiser le Serial Monitor et préparer le GPIO.

Serial.begin(115200);
delay(1000);

pinMode(ledPin, OUTPUT);
digitalWrite(ledPin, LOW);

Ensuite, créez le gpioTimer et attribuez la fonction timerCallback décrite précédemment qui s’exécute lorsque le minuteur expire.

gpioTimer = xTimerCreate("GPIO_Timer", pdMS_TO_TICKS(1000), pdFALSE, 0, timerCallback);

Démarrez la connexion Wi-Fi et imprimez l’adresse IP ESP32 dans le moniteur série.

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());

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 PROGMEM pour afficher la page Web :

server.on("/", HTTP_GET, [](AsyncWebServerRequest *request) {
  request->send_P(200, "text/html", index_html);
});

Itinéraire de contrôle LED/contrôle

Cette route GET contrôle la LED ON/OFF en fonction du paramètre d’état (1 = HIGH et 0 = LOW).

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");
});

GET LED State Route /led-state

Cette route GET lit l’état actuel de la LED et le renvoie sous la forme d’un simple objet JSON contenant la valeur de l’état.

server.on("/led-state", HTTP_GET, [](AsyncWebServerRequest *request) {
  int state = digitalRead(ledPin);
  request->send(200, "application/json", "{\"state\":" + String(state) + "}");
});

Définir l’itinéraire du minuteur /set-timer

Cette route HTTP POST reçoit les données de la page Web avec l’action, la durée et l’unité de temps sélectionnées. Il convertit la durée en secondes, puis FreeRTOS coche pour démarrer le chronomètre unique. Lorsque le délai expire, l’action s’exécute.

server.on("/set-timer", HTTP_POST, [](AsyncWebServerRequest *request) {
  if (request->hasParam("action", true) && request->hasParam("duration", true) && request->hasParam("unit", true)) {

    targetAction = request->getParam("action", true)->value().toInt();
    int dur = request->getParam("duration", true)->value().toInt();
    String unit = request->getParam("unit", true)->value();

    uint64_t durationSeconds = 0;
    if (unit == "s")      durationSeconds = (uint64_t)dur;
    else if (unit == "m") durationSeconds = (uint64_t)dur * 60ULL;
    else if (unit == "h") durationSeconds = (uint64_t)dur * 3600ULL;

    if (durationSeconds > 0) {
      if (xTimerIsTimerActive(gpioTimer)) xTimerStop(gpioTimer, 0);

      uint64_t tempTicks = durationSeconds * (uint64_t)configTICK_RATE_HZ;
      TickType_t timerTicks = (tempTicks > 0xFFFFFFFFULL) ? 0xFFFFFFFFULL : (TickType_t)tempTicks;

      timerStartTick = xTaskGetTickCount();
      totalDurationTicks = tempTicks;

      xTimerChangePeriod(gpioTimer, timerTicks, 0);
      xTimerStart(gpioTimer, 0);

      Serial.printf("Timer scheduled: GPIO %d will be set to %s in %llu seconds\n", ledPin,
                    targetAction ? "ON" : "OFF", durationSeconds);
    }
  }
  request->redirect("/");
});

Annuler l’itinéraire du minuteur / annuler le minuteur

Cette route arrête tout minuteur FreeRTOS actif et réinitialise les variables globales du minuteur (timerStartTick, totalDurationTicks) à leur état d’inactivité.

server.on("/cancel-timer", HTTP_POST, [](AsyncWebServerRequest *request) {
  // Stop the active timer
  if (xTimerIsTimerActive(gpioTimer)) {
    xTimerStop(gpioTimer, 0);
    Serial.println("Timer cancelled");
  }
  targetAction = -1;
  timerStartTick = 0; 
  totalDurationTicks = 0;
  request->send(200, "text/plain", "OK");
});

Statut du minuteur Itinéraire /statut-minuterie

Cette route vérifie si une minuterie est en cours d’exécution, calcule le temps restant exact en secondes et renvoie un objet JSON avec le message d’état actuel.

server.on("/timer-status", HTTP_GET, [](AsyncWebServerRequest *request) {
  if (targetAction != -1 && xTimerIsTimerActive(gpioTimer) && totalDurationTicks > 0) {
    // Calculate how many seconds are left for the timer to end
    TickType_t now = xTaskGetTickCount();
    uint64_t elapsedTicks = 0;

    if (now >= timerStartTick) {
      elapsedTicks = now - timerStartTick;
    } else {
      elapsedTicks = (0xFFFFFFFFULL - timerStartTick) + now + 1;
    }

    uint64_t remainingTicks = (totalDurationTicks > elapsedTicks) ? totalDurationTicks - elapsedTicks : 0;
    uint64_t remainingSeconds = remainingTicks / (uint64_t)configTICK_RATE_HZ;

    // Return the amount of seconds left and action that will execute when the timer ends
    String json = "{\"status\":\"Setting GPIO "+ String(ledPin) +" to " + 
                  String(targetAction ? "ON" : "OFF") + "\",";
    json += "\"active\":true,";
    json += "\"remaining_seconds\":" + String((unsigned long)remainingSeconds) + "}";
    request->send(200, "application/json", json);
  } else {
    request->send(200, "application/json", "{\"status\":\"No active timers\",\"active\":false,\"remaining_seconds\":0}");
  }
});

Initialiser le serveur

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

server.begin();

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.

ESP32 Web Server Set Timer Programmation Arduino IDE Serial Monitor Adresse IP

Avec un ESP32 doté d’une LED connectée au GPIO 5, ouvrez n’importe quel navigateur sur votre réseau local et saisissez l’adresse IP de l’ESP32. La page Web suivante se chargera.

Page Web de programmation de la minuterie du serveur Web ESP32

Cliquez sur les boutons TURN ON ou TURN OFF pour contrôler la LED. Vous pouvez également vérifier l’état actuel de la LED sur l’étiquette de texte.

Programmation de la minuterie du serveur Web ESP32 Arduino IDE Allumer les boutons LED

Ensuite, vous disposez d’un formulaire HTML dans lequel vous pouvez sélectionner l’action, l’unité de temps et la durée de la minuterie. Après avoir sélectionné les paramètres de minuterie souhaités, appuyez sur le bouton « START TIMER ».

Programmation de la minuterie du serveur Web ESP32 Arduino IDE Set Timer Formulaire Web HTML

Au bas de la page Web, l’état du temps affichera l’action en attente actuelle et le temps restant. Il y a aussi un bouton pour annuler la minuterie.

Programmation de la minuterie du serveur Web ESP32 Temps restant de l'IDE Arduino Bouton d'annulation de la minuterie

Dans le moniteur série Arduino IDE, vous pouvez vérifier toutes les actions effectuées sur le serveur Web.

Programmation du serveur Web ESP32 Démonstration du moniteur série Arduino IDE

Conclusion

Dans ce didacticiel, vous avez appris à créer un serveur Web simple pour créer une minuterie permettant de contrôler vos GPIO ESP32. Vous pouvez maintenant étendre ce projet pour contrôler plus de sorties. Vous pouvez consulter d’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

  • KEYESTUDIO ESP32 Smart Home IoT Kit Compatible avec Arduino IDE, avec ESP32 Board, Python C, Musical Project, etc.
  • Ulegqin ESP32 NodeMCU mit CH340 Cartes de développement, ESP32 30 Pins ESP ESP-32-WROOM-32D Module 2.4 GHz WiFi + Bluetooth 2-in-1 Faible consommation Typ-C Interface Compatible avec Arduino(3 pcs)