Serveur ESP32 et E/S

Dans cet article, nous allons ajouter des fonctionnalités à notre ESP32. Ce dernier va maintenant afficher l’état d’une LED, d’un bouton et d’un potentiomètre en plus de permettre de changer l’état de la LED.

Assurez-vous de lire l’article Serveur Web sur le ESP32 avant de débuter cette partie.

Attention : le ESP32 n’est pas tolérant au 5V sur les E/S. Utilisez le 3.3V pour comme alimentation pour vos circuits.

1 – Lecture des entrées

La lecture d’une broche numérique s’effectue via la fonction digitalRead. Sur le montage, le bouton sera sur la broche 23 donc il sera possible d’afficher l’état du bouton avec un simple test.

if(digitalRead(23))
  client.print("off");
else
  client.print("on");

La lecture du potentiomètre utilise la fonction analogRead. Sur le montage, le potentiomètre sera relié à la broche 34 (ADC1:6). L’affichage de la valeur du potentiomètre sera affichée directement.

client.print(analogRead(34));

2 – Écriture des sorties

Pour modifier l’état de la LED, nous allons utiliser la fonction digitalWrite. La LED sera connectée sur la broche 15 avec une résistance de 1kohms en série. La cathode de la LED sera reliée au GND.

Pour recevoir la commande d’état à partir du navigateur, nous allons ajouter un bouton dans notre code html. Le bouton provoquera une requête html vers  un URL qui contiendra l’adresse IP du ESP32, ainsi que l’état désirée du LED.

Ajout du bouton dans le code HTML.

if (led1State)
client.println("<p><a href=\"/LED1/off\"><button>ON</button></a></p>");
else
client.println("<p><a href=\"/LED1/on\"><button>OFF</button></a></p>");

Dans le code précédent,  on ajoute un bouton dans la page html qui affiche l’état actuel du bouton, et qui appel  le URL avec le IP plus le text /LED1/X où X est le nouvel état désiré.

Pour récupérer l’information dans le URL, il faudra dans un premier temps conserver la requete html reçue, puis analyser celle-ci pour voir si l’on y retrouve la commande GET avec un des deux href configurer dans le bouton.

 // ajout de la récupération de la requête http complète
char rxData = client.read();
rxHttpRequest+=rxData;
// Ajout de l'analyse de la requête, lorsque qu'elle est reçue au complet
if (rxHttpRequest.indexOf("GET /LED1/on") >= 0)
{
  digitalWrite(15,1); // gestion de la sortie
   led1State=1; // gestion de la variable d'état pour modifier le bouton
}
if (rxHttpRequest.indexOf("GET /LED1/off") >= 0)
{
  digitalWrite(15,0); // gestion de la sortie
   led1State=0; // gestion de la variable d'état pour modifier le bouton
}

Il faudra aussi activer la LED en sortie dans la fonction setup avec la fonction pinMode.

pinmode(15,OUTPUT);

Finalement, lorsque l’on ferme la connexion avec le client, il faut vider la requête http. Voici donc le code complet pour le moment. 

#include <Arduino.h>
#include <WiFi.h>
// Informations sur le réseau Wi-Fi
// Vous devez remplacer les informations pas celles de votre réseau
const char* ssid = "devRouteur";
const char* password = "#1234#fafa";
// Créer un serveur sur le port 80
WiFiServer serveur(80);
// Créer une string pour conserver la requête http
String rxHttpRequest = "";
//Variable pour conserver l'état du LED
boolean led1State = 0;

void setup()
{
 // Nous allons utiliser la console pour afficher des informations
Serial.begin(9600);
//Début de la connexion au réseau
Serial.print("Connection au réseau ");
Serial.println(ssid);
WiFi.disconnect();
WiFi.begin(ssid, password);

// Tant que le status n'est pas connecté, attendre...
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
    Serial.print(".");
  }
  // Une fois connecté, on affiche l'adresse IP du ESP32
  Serial.println("");
  Serial.println("Connecté au Wi-fi");
  Serial.println("Adresse IP = ");
  Serial.println(WiFi.localIP());
  serveur.begin();
  pinMode(15,OUTPUT);
}
void loop() 
{
// Regarde s'il y a un client sur le serveur
  WiFiClient client = serveur.available();
  if(client)
  {
  Serial.println("Nouveau Client.");
    // rester dans la boucle tant que le client est connecté
    while (client.connected())
    {
     if (client.available()) // Vérifie si le client a envoyé des données
     {
        char rxData = client.read();
        rxHttpRequest+=rxData;
      Serial.write(rxData);
       if (rxData == '\n') // si c'.est la fin de la commande reçue
       {
//analyse de la commande reçue
if (rxHttpRequest.indexOf("GET /LED1/on") >= 0)
{
digitalWrite(15,1); // gestion de la sortie
led1State=1; // gestion de la variable d'état pour modifier le bouton
}
if (rxHttpRequest.indexOf("GET /LED1/off") >= 0)
{
digitalWrite(15,0); // gestion de la sortie
led1State=0; // gestion de la variable d'état pour modifier le bouton
}
Serial.println("");
Serial.println("Charge page HTML");
client.println("HTTP/1.1 200 OK"); //send new page
client.println("Content-Type: text/html");
client.println();
client.println("<html>");
client.println("<body>");
client.print("<p>Bouton=");
if(digitalRead(23))
client.print("off");
else
client.print("on");
client.println("</p>");
client.print("<p>Potentiometre=");
client.print(analogRead(34));
client.println("</p>");
if (led1State)
client.println("<p><a href=\"/LED1/off\"> <button>ON</button></a></p>");
else
client.println("<p><a href=\"/LED1/on\"><button>OFF</button></a></p>");

client.println("</body>");
client.println("</html>");
client.stop();
rxHttpRequest = "";
}
}
}
}
}

Voici le résulta que vous devriez obtenir au navigateur.

Si le montage est complété, vous devriez obtenir la lecture du bouton et du potentiomètre, en plus de pouvoir contrôler la LED.

Notez que vous devez rafraîchir le navigateur afin de voir les changements pour le bouton et le potentiomètre. Vous pouvez ajouter la commande suivante dans l’entête html afin de provoquer le rafraîchissement automatique aux 2s.

<meta http-equiv="refresh" content="2">

Aussi, nous pourrions améliorer l’esthétique de notre page en utilisant les styles CSS. Le code suivant permet d’ajouter un style pour le bouton et le texte en général.

 <style>
html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}
.button1 { background-color: #d1c819; border:2px solid #d1c819;color: white; width: 100px;border-radius: 12px;padding-top: 10px;padding-bottom: 10px;
transition-duration: 0.1s; text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}
.button1:hover { background-color: white; color:black ;border: 2px solid #d1c819;}
.buttonoff {background-color: #27282e;border:2px solid #27282e;}
.buttonoff:hover { background-color: white; color:black ;border: 2px solid #27282e;}
</style>

Pour appliquer le style à notre site, il suffit ajouter ce code à notre entête html et de modifier l’appel du bouton comme suit :

if (led1State)
client.println("<p><a href=\"/LED1/off\"><button class=\"button1\">ON</button></a></p>");
else
client.println("<p><a href=\"/LED1/on\"><button class=\"button1 buttonoff\">OFF</button></a></p>");

Pour simplifier l’ajout de code html dans l’entête, il est possible d’utiliser un tableau de caractères constant et de définir son contenu comme littéral. Ça évite d’avoir à mettre les \ partout devant les ” ou à la fin des lignes.

Voici le code complet avec le style. Notez que le site à un titre et même un icone.

#include <Arduino.h>
#include <WiFi.h>
// Informations sur le réseau Wi-Fi
// Vous devez remplacer les informations pas celles de votre réseau
const char* ssid = "devRouteur";
const char* password = "#1234#fafa";
// code html de l'entête 
const char pageHeadHtml[] = R"(
HTTP/1.1 200 OK
Content-Type: text/html
Connection: close

<!DOCTYPE html>
<html>
<meta http-equiv="refresh" content="2">
<head><meta name="viewport" content="width=device-width, initial-scale=1">
<title>ESP32 Serveur</title>
<link rel="icon" href="https://www.iconsdb.com/icons/download/red/online-16.png">
<style>
html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}
.button1 { background-color: #d1c819; border:2px solid #d1c819;color: white; width: 100px;border-radius: 12px;padding-top: 10px;padding-bottom: 10px;
transition-duration: 0.1s; text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}
.button1:hover { background-color: white; color:black ;border: 2px solid #d1c819;}
.buttonoff {background-color: #27282e;border:2px solid #27282e;}
.buttonoff:hover { background-color: white; color:black ;border: 2px solid #27282e;}
</style>
</head>
<body><h1> Serveur ESP32 </h1>
)";
// Créer un serveur sur le port 80
WiFiServer serveur(80);
// Créer une string pour conserver la requête http
String rxHttpRequest = "";
//Variable pour conserver l'état du LED
boolean led1State = 0;
void setup() 
{
// Nous allons utiliser la console pour afficher des informations
Serial.begin(9600);
//Début de la connexion au réseau
Serial.print("Connection au réseau ");
Serial.println(ssid);
WiFi.disconnect();
WiFi.begin(ssid, password);
// Tant que le status n'est pas connecté, attendre...
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print(".");
}
// Une fois connecté, on affiche l'adresse IP du ESP32
Serial.println("");
Serial.println("Connecté au Wi-fi");
Serial.println("Adresse IP = ");
Serial.println(WiFi.localIP());
serveur.begin();
pinMode(15,OUTPUT);
}
void loop() 
{
// Regarde s'il y a un client sur le serveur
WiFiClient client = serveur.available();
if(client)
{
Serial.println("Nouveau Client.");
// rester dans la boucle tant que le client est connecté
while (client.connected())
{
if (client.available()) // Vérifie si le client a envoyé des données
{
char rxData = client.read();
rxHttpRequest+=rxData;
Serial.write(rxData);
if (rxData == '\n') // si c'.est la fin de la commande reçue
{
//analyse de la commande reçue
if (rxHttpRequest.indexOf("GET /LED1/on") >= 0)
{
digitalWrite(15,1); // gestion de la sortie
led1State=1; // gestion de la variable d'état pour modifier le bouton
}
if (rxHttpRequest.indexOf("GET /LED1/off") >= 0)
{
digitalWrite(15,0); // gestion de la sortie
led1State=0; // gestion de la variable d'état pour modifier le bouton
}
client.print(pageHeadHtml);
client.print("<p>Bouton=");
if(digitalRead(23))
client.print("off");
else
client.print("on");
client.println("</p>");
client.print("<p>Potentiometre=");
client.print(analogRead(34));
client.println("</p>");
if (led1State)
client.println("<p><a href=\"/LED1/off\"><button class=\"button1\">ON</button></a></p>");
else
client.println("<p><a href=\"/LED1/on\"><button class=\"button1 buttonoff\">OFF</button></a></p>");

client.println("</body>");
client.println("</html>");

client.stop();
rxHttpRequest = "";
}
}
}
}
}

Laisser un commentaire

Votre adresse courriel ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Ce site utilise Akismet pour réduire le pourriel. En savoir plus sur comment les données de vos commentaires sont utilisées.