ESP32/ESP8266 : Contrôlez les sorties du serveur Web et du bouton physique

ESP32/ESP8266 : Contrôlez les sorties du serveur Web et du bouton physique

Ce tutoriel montre comment contrôler les sorties ESP32 ou ESP8266 à l’aide d’un serveur Web et d’un bouton physique simultanément. L’état de la sortie est mis à jour sur la page Web, qu’il soit modifié via un bouton physique ou un serveur Web.

ESP32 ESP8266 NodeMCU : contrôler les sorties avec un serveur Web et un bouton physique simultanément IDE Arduino

Lecture recommandée: Données d’entrée sur le serveur Web HTML Form ESP32/ESP8266

Les cartes ESP32/ESP8266 seront programmées à l’aide de l’IDE Arduino. Assurez-vous donc que ces cartes sont installées :

Aperçu du projet

Voyons rapidement comment fonctionne le projet.

Serveur Web ESP32 ESP8266 NodeMCU avec aperçu du projet de bouton physique
  • L’ESP32 ou l’ESP8266 héberge un serveur web qui permet de contrôler l’état d’une sortie ;
  • L’état actuel de la sortie est affiché sur le serveur Web ;
  • L’ESP est également connecté à un bouton-poussoir physique qui contrôle la même sortie ;
  • Si vous modifiez l’état de la sortie à l’aide du puhsbutton physique, son état actuel est également mis à jour sur le serveur Web.

En résumé, ce projet vous permet de contrôler la même sortie à l’aide d’un serveur Web et d’un bouton poussoir simultanément. Chaque fois que l’état de la sortie change, le serveur Web est mis à jour.

Diagramme schématique

Avant de procéder, vous devez assembler un circuit avec une LED et un bouton-poussoir. Nous connecterons la LED à GPIO 2 et le bouton poussoir pour GPIO 4.

Pièces requises

Voici une liste des pièces dont vous avez besoin pour construire le circuit :

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

1644073924 711 ESP32ESP8266 Controlez les sorties du serveur Web et du bouton

Schéma ESP32

Bouton-poussoir LED du circuit schématique des entrées numériques et des sorties numériques ESP32

Schéma ESP8266 NodeMCU

ESP8266 NodeMCU Entrée numérique et Circuit schématique de sortie numérique LED Bouton-poussoir

Installation de bibliothèques – Serveur Web asynchrone

Pour construire le serveur Web, vous devez installer les bibliothèques suivantes :

Ces bibliothèques ne peuvent pas être installées via le gestionnaire de bibliothèque Arduino, vous devez donc copier les fichiers de bibliothèque dans le dossier Bibliothèques d’installation Arduino. Alternativement, dans votre IDE Arduino, vous pouvez accéder à Esquisser > Inclure la bibliothèque > Ajouter une bibliothèque .zip et sélectionnez les bibliothèques que vous venez de télécharger.

Code du serveur Web ESP

Copiez le code suivant dans votre IDE Arduino.

/*********
  Rui Santos
  Complete project details at https://Raspberryme.com/esp32-esp8266-web-server-physical-button/
  
  The above copyright notice and this permission notice shall be included in all
  copies or substantial portions of the Software.
*********/

// Import required libraries
#ifdef ESP32
  #include <WiFi.h>
  #include <AsyncTCP.h>
#else
  #include <ESP8266WiFi.h>
  #include <ESPAsyncTCP.h>
#endif
#include <ESPAsyncWebServer.h>

// Replace with your network credentials
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

const char* PARAM_INPUT_1 = "state";

const int output = 2;
const int buttonPin = 4;

// Variables will change:
int ledState = LOW;          // the current state of the output pin
int buttonState;             // the current reading from the input pin
int lastButtonState = LOW;   // the previous reading from the input pin

// the following variables are unsigned longs because the time, measured in
// milliseconds, will quickly become a bigger number than can be stored in an int.
unsigned long lastDebounceTime = 0;  // the last time the output pin was toggled
unsigned long debounceDelay = 50;    // the debounce time; increase if the output flickers

// Create AsyncWebServer object on port 80
AsyncWebServer server(80);

const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html>
<head>
  <title>ESP Web Server</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <style>
    html {font-family: Arial; display: inline-block; text-align: center;}
    h2 {font-size: 3.0rem;}
    p {font-size: 3.0rem;}
    body {max-width: 600px; margin:0px auto; padding-bottom: 25px;}
    .switch {position: relative; display: inline-block; width: 120px; height: 68px} 
    .switch input {display: none}
    .slider {position: absolute; top: 0; left: 0; right: 0; bottom: 0; background-color: #ccc; border-radius: 34px}
    .slider:before {position: absolute; content: ""; height: 52px; width: 52px; left: 8px; bottom: 8px; background-color: #fff; -webkit-transition: .4s; transition: .4s; border-radius: 68px}
    input:checked+.slider {background-color: #2196F3}
    input:checked+.slider:before {-webkit-transform: translateX(52px); -ms-transform: translateX(52px); transform: translateX(52px)}
  </style>
</head>
<body>
  <h2>ESP Web Server</h2>
  %BUTTONPLACEHOLDER%
<script>function toggleCheckbox(element) {
  var xhr = new XMLHttpRequest();
  if(element.checked){ xhr.open("GET", "/update?state=1", true); }
  else { xhr.open("GET", "/update?state=0", true); }
  xhr.send();
}

setInterval(function ( ) {
  var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      var inputChecked;
      var outputStateM;
      if( this.responseText == 1){ 
        inputChecked = true;
        outputStateM = "On";
      }
      else { 
        inputChecked = false;
        outputStateM = "Off";
      }
      document.getElementById("output").checked = inputChecked;
      document.getElementById("outputState").innerHTML = outputStateM;
    }
  };
  xhttp.open("GET", "/state", true);
  xhttp.send();
}, 1000 ) ;
</script>
</body>
</html>
)rawliteral";

// Replaces placeholder with button section in your web page
String processor(const String& var){
  //Serial.println(var);
  if(var == "BUTTONPLACEHOLDER"){
    String buttons ="";
    String outputStateValue = outputState();
    buttons+= "<h4>Output - GPIO 2 - State <span id=\"outputState\"></span></h4><label class=\"switch\"><input type=\"checkbox\" onchange=\"toggleCheckbox(this)\" id=\"output\" " + outputStateValue + "><span class=\"slider\"></span></label>";
    return buttons;
  }
  return String();
}

String outputState(){
  if(digitalRead(output)){
    return "checked";
  }
  else {
    return "";
  }
  return "";
}

void setup(){
  // Serial port for debugging purposes
  Serial.begin(115200);

  pinMode(output, OUTPUT);
  digitalWrite(output, LOW);
  pinMode(buttonPin, INPUT);
  
  // Connect to Wi-Fi
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi..");
  }

  // Print ESP Local IP Address
  Serial.println(WiFi.localIP());

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

  // Send a GET request to <ESP_IP>/update?state=<inputMessage>
  server.on("/update", HTTP_GET, [] (AsyncWebServerRequest *request) {
    String inputMessage;
    String inputParam;
    // GET input1 value on <ESP_IP>/update?state=<inputMessage>
    if (request->hasParam(PARAM_INPUT_1)) {
      inputMessage = request->getParam(PARAM_INPUT_1)->value();
      inputParam = PARAM_INPUT_1;
      digitalWrite(output, inputMessage.toInt());
      ledState = !ledState;
    }
    else {
      inputMessage = "No message sent";
      inputParam = "none";
    }
    Serial.println(inputMessage);
    request->send(200, "text/plain", "OK");
  });

  // Send a GET request to <ESP_IP>/state
  server.on("/state", HTTP_GET, [] (AsyncWebServerRequest *request) {
    request->send(200, "text/plain", String(digitalRead(output)).c_str());
  });
  // Start server
  server.begin();
}
  
void loop() {
  // read the state of the switch into a local variable:
  int reading = digitalRead(buttonPin);

  // check to see if you just pressed the button
  // (i.e. the input went from LOW to HIGH), and you've waited long enough
  // since the last press to ignore any noise:

  // If the switch changed, due to noise or pressing:
  if (reading != lastButtonState) {
    // reset the debouncing timer
    lastDebounceTime = millis();
  }

  if ((millis() - lastDebounceTime) > debounceDelay) {
    // whatever the reading is at, it's been there for longer than the debounce
    // delay, so take it as the actual current state:

    // if the button state has changed:
    if (reading != buttonState) {
      buttonState = reading;

      // only toggle the LED if the new button state is HIGH
      if (buttonState == HIGH) {
        ledState = !ledState;
      }
    }
  }

  // set the LED:
  digitalWrite(output, ledState);

  // save the reading. Next time through the loop, it'll be the lastButtonState:
  lastButtonState = reading;
}

Afficher le code brut

Il vous suffit d’entrer vos informations d’identification réseau (SSID et mot de passe) et le serveur Web fonctionnera immédiatement. Le code est compatible avec les deux ESP32 et ESP8266 tableaux et contrôles GPIO 2 – vous pouvez changer le code pour contrôler n’importe quel autre GPIO.

Comment fonctionne le code

Nous avons déjà expliqué en détail le fonctionnement des serveurs Web comme celui-ci dans les didacticiels précédents (DHT Temperature Web Server), nous allons donc simplement examiner les parties pertinentes pour ce projet.

Informations d’identification réseau

Comme dit précédemment, vous devez insérer vos identifiants réseau dans les lignes suivantes :

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

État du bouton et état de la sortie

le étatled variable contient l’état de sortie de la LED. Par défaut, lorsque le serveur Web démarre, il est MEUGLER.

int ledState = LOW; // the current state of the output pin

le état du bouton et lastButtonState servent à détecter si le bouton-poussoir a été enfoncé ou non.

int buttonState;            // the current reading from the input pin
int lastButtonState = LOW;  // the previous reading from the input pin

Bouton (serveur Web)

Nous n’avons pas inclus le code HTML pour créer le bouton sur le index_html variable. C’est parce que nous voulons pouvoir le changer en fonction de l’état actuel de la LED qui peut également être modifié avec le bouton-poussoir.

Donc, nous avons créé un espace réservé pour le bouton %BUTTONPLACEHOLDER% qui sera remplacé par du texte HTML pour créer le bouton plus tard dans le code (cela se fait dans le processeur() une fonction).

<h2>ESP Web Server</h2>
%BUTTONPLACEHOLDER%

processeur()

le processeur() La fonction remplace tous les espaces réservés du texte HTML par des valeurs réelles. Tout d’abord, il vérifie si les textes HTML contiennent des espaces réservés %BUTTONPLACEHOLDER%.

if(var == "BUTTONPLACEHOLDER"){

Ensuite, appelez le état de sortie () fonction qui renvoie l’état actuel de la sortie. Nous l’enregistrons dans le outputStateValue variable.

String outputStateValue = outputState();

Après cela, utilisez cette valeur pour créer le texte HTML pour afficher le bouton avec le bon état :

buttons+= "<h4>Output - GPIO 2 - State <span id=\"outputState\"><span></h4><label class=\"switch\"><input type=\"checkbox\" onchange=\"toggleCheckbox(this)\" id=\"output\" " + outputStateValue + "><span class=\"slider\"></span></label>";

Demande HTTP GET pour modifier l’état de sortie (JavaScript)

Lorsque vous appuyez sur le bouton, le toggleCheckbox() fonction est appelée. Cette fonction fera une demande sur différentes URL pour allumer ou éteindre la LED.

function toggleCheckbox(element) {
  var xhr = new XMLHttpRequest();
  if(element.checked){ xhr.open("GET", "/update?state=1", true); }
  else { xhr.open("GET", "/update?state=0", true); }
  xhr.send();
}

Pour allumer la LED, il fait une demande sur le /mise à jour?état=1 URL :

if(element.checked){ xhr.open("GET", "/update?state=1", true); }

Sinon, il fait une requête sur le /mise à jour?état=0 URL.

Requête HTTP GET pour mettre à jour l’état (JavaScript)

Pour maintenir l’état de la sortie à jour sur le serveur Web, nous appelons la fonction suivante qui effectue une nouvelle requête sur le /Etat URL chaque seconde.

setInterval(function ( ) {
  var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      var inputChecked;
      var outputStateM;
      if( this.responseText == 1){ 
        inputChecked = true;
        outputStateM = "On";
      }
      else { 
        inputChecked = false;
        outputStateM = "Off";
      }
      document.getElementById("output").checked = inputChecked;
      document.getElementById("outputState").innerHTML = outputStateM;
    }
  };
  xhttp.open("GET", "/state", true);
  xhttp.send();
}, 1000 ) ;

Traiter les demandes

Ensuite, nous devons gérer ce qui se passe lorsque l’ESP32 ou l’ESP8266 reçoit des requêtes sur ces URL.

Lorsqu’une requête est reçue à la root / URL, nous envoyons la page HTML ainsi que le processeur.

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

Les lignes suivantes vérifient si vous avez reçu une demande sur le /mise à jour?état=1 ou /mise à jour?état=0 URL et modifie le étatled par conséquent.

server.on("/update", HTTP_GET, [] (AsyncWebServerRequest *request) {
  String inputMessage;
  String inputParam;
  // GET input1 value on <ESP_IP>/update?state=<inputMessage>
  if (request->hasParam(PARAM_INPUT_1)) {
    inputMessage = request->getParam(PARAM_INPUT_1)->value();
    inputParam = PARAM_INPUT_1;
    digitalWrite(output, inputMessage.toInt());
    ledState = !ledState;
  }
  else {
    inputMessage = "No message sent";
    inputParam = "none";
  }
  Serial.println(inputMessage);
  request->send(200, "text/plain", "OK");
});

Lorsqu’une demande est reçue sur le /Etat URL, nous envoyons l’état de sortie actuel :

server.on("/state", HTTP_GET, [] (AsyncWebServerRequest *request) {
  request->send(200, "text/plain", String(digitalRead(output)).c_str());
});

boucler()

Dans le boucler()on anti-rebondit le bouton poussoir et on allume ou éteint la LED selon la valeur du étatled variable.

digitalWrite(output, ledState);

Manifestation

Téléchargez le code sur votre carte ESP32 ou ESP8266.

Ensuite, ouvrez le moniteur série à un débit en bauds de 115200. Appuyez sur le bouton EN/RST intégré pour obtenir son adresse IP.

ESP32 ESP8266 Adresse IP du serveur Web NodeMCU Moniteur série Arduino IDE

Ouvrez un navigateur sur votre réseau local et saisissez l’adresse IP ESP. Vous devriez avoir accès au serveur Web comme indiqué ci-dessous.

Les sorties de contrôle ESP32 ESP8266 NodeMCU avec serveur Web et un bouton physique s'éteignent simultanément

Vous pouvez basculer le bouton sur le serveur Web pour allumer le voyant.

ESP32 ESP8266 Sorties de contrôle NodeMCU avec serveur Web et un bouton physique s'allument simultanément

Vous pouvez également contrôler la même LED avec le bouton-poussoir physique. Son état sera toujours mis à jour automatiquement sur le serveur Web.

Bouton de sortie d'entrée ESP32 enfoncé LED sur l'IDE Arduino

Regardez la prochaine vidéo rapide pour une démonstration en direct :

Conclusion

Dans ce tutoriel, vous avez appris à contrôler les sorties ESP32/ESP8266 avec un serveur Web et un bouton physique en même temps. L’état de la sortie est toujours mis à jour, qu’il soit modifié via le serveur Web ou avec le bouton physique.

D’autres projets qui pourraient vous plaire :

Apprenez-en plus sur l’ESP32 et l’ESP8266 avec nos ressources :

Merci d’avoir lu.