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.
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.
- 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 !
Schéma ESP32
Schéma ESP8266 NodeMCU
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;
}
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.
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.
Vous pouvez basculer le bouton sur le serveur Web pour allumer le voyant.
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.
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.