Le Wi-Fi est l’argument décisif de l’ESP32 : un objet connecté sans module radio externe. Avec quelques lignes, la carte rejoint un réseau (mode station) ou crée le sien (mode point d’accès), puis échange des données — interroger une API, exposer une page web de pilotage, publier des mesures. C’est une capacité que l’Arduino classique n’a pas, et le cœur de ce que la famille ESP32 apporte. Le concept général de liaison sans fil est traité dans technologies sans fil et Wi-Fi. Cette fiche en donne l’incarnation ESP32.
À quoi ça sert ?
Le Wi-Fi de l’ESP32 ouvre trois usages typiques en projet :
Relier le système à Internet — récupérer l’heure, une météo, une consigne depuis une API ; envoyer des mesures vers un serveur ou un tableau de bord. La carte est client.
Offrir une interface sans écran — l’ESP32 héberge une petite page web. On pilote le système et on lit son état depuis un navigateur, téléphone ou PC. La carte est serveur.
Se passer d’infrastructure — en mode point d’accès, l’ESP32 crée son propre réseau auquel on se connecte directement, sans box ni routeur (configuration sur le terrain, démonstration).
Warning
Wi-Fi actif = ADC2 indisponible. Dès que le Wi-Fi tourne, les broches du convertisseur ADC2 ne lisent plus rien. Tout capteur analogique d’un projet connecté doit être sur ADC1 (GPIO32-39, voir configurer les GPIO).
Deux modes : station et point d’accès
Tout part de la bibliothèque WiFi.h, incluse dans le cœur ESP32.
Station (STA) — l’ESP32 se connecte à un réseau existant (votre box). C’est le mode courant pour accéder à Internet.
Point d’accès (AP) — l’ESP32 crée un réseau auquel d’autres appareils se connectent. Pratique pour une configuration locale.
#include <WiFi.h>const char* ssid = "MonReseau";const char* motDePasse = "********";void setup() { Serial.begin(115200); WiFi.begin(ssid, motDePasse); // mode station Serial.print("Connexion"); int tentatives = 0; while (WiFi.status() != WL_CONNECTED && tentatives < 20) { // 20 x 500 ms = 10 s max delay(500); Serial.print("."); tentatives++; } Serial.println(); if (WiFi.status() != WL_CONNECTED) { // echec : on le signale, on ne fige pas Serial.println("Echec de connexion - verifier SSID et mot de passe"); return; } Serial.print("Connecte, IP = "); Serial.println(WiFi.localIP()); // adresse attribuée par la box}void loop() {}
L’attente est bornée : au bout d’une dizaine de secondes, la carte renonce et le dit, au lieu de rester figée sur un SSID mal tapé. Les exemples suivants gardent la forme courte pour ne pas noyer leur sujet. En projet, reprendre ce motif borné.
Pour le mode point d’accès, deux lignes suffisent : la carte crée le réseau au lieu de le rejoindre.
#include <WiFi.h>void setup() { Serial.begin(115200); WiFi.softAP("ESP32-Demo", "motdepasse"); // reseau cree par la carte Serial.print("Point d'acces actif, IP = "); Serial.println(WiFi.softAPIP()); // 192.168.4.1 par defaut}void loop() {}
On rejoint le réseau ESP32-Demo depuis un téléphone, puis on ouvre 192.168.4.1 (pratique en démonstration sur table, sans box ni routeur). Le mot de passe doit faire au moins 8 caractères : en dessous, softAP() échoue et le réseau n’apparaît pas.
Warning
L’ESP32 (hors C5) est en 2,4 GHz seulement. Il ne se connecte pas à un réseau diffusé uniquement en 5 GHz. Sur une box bi-bande, vérifier que le 2,4 GHz est actif et que le SSID visé est bien le réseau 2,4 GHz.
Exemple — Piloter une LED depuis un navigateur
L’usage le plus parlant : l’ESP32 rejoint le réseau, héberge une page web minimale, et pilote une LED selon le lien cliqué. Un téléphone sur le même réseau ouvre l’adresse IP et commande la carte.
#include <WiFi.h>#include <WebServer.h>const char* ssid = "MonReseau";const char* motDePasse = "********";const int LED = 16;WebServer serveur(80); // serveur HTTP sur le port 80void pageAccueil() { String html = "<h1>ESP32</h1>" "<p><a href=\"/on\">Allumer</a> | " "<a href=\"/off\">Eteindre</a></p>"; serveur.send(200, "text/html", html);}void allumer() { digitalWrite(LED, HIGH); serveur.send(200, "text/html", "LED allumee. <a href=\"/\">Retour</a>");}void eteindre() { digitalWrite(LED, LOW); serveur.send(200, "text/html", "LED eteinte. <a href=\"/\">Retour</a>");}void setup() { Serial.begin(115200); pinMode(LED, OUTPUT); WiFi.begin(ssid, motDePasse); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.print("\nOuvrez http://"); Serial.println(WiFi.localIP()); // l'URL à taper dans le navigateur serveur.on("/", pageAccueil); // associer chemins -> fonctions serveur.on("/on", allumer); serveur.on("/off", eteindre); serveur.begin();}void loop() { serveur.handleClient(); // traiter les requêtes en continu}
Téléversez, ouvrez le moniteur série (115200) pour lire l’adresse IP affichée, puis tapez http://<cette IP> dans un navigateur du même réseau. La page propose deux liens qui allument et éteignent la LED. On a une interface de pilotage sans écran ni application en une cinquantaine de lignes.
Le navigateur affiche Non sécurisé à côté de l’adresse, sur les trois pages. C’est attendu : la page est servie en HTTP simple, sans chiffrement : l’ESP32 n’a pas de certificat, et le trafic ne quitte pas votre réseau local. Rien n’est cassé, rien n’est à corriger. L’avertissement devient un vrai sujet le jour où la carte est accessible depuis l’extérieur, ou transporte autre chose qu’un état de LED.
Pièges
Capteur analogique muet en Wi-Fi. Une mesure analogRead qui devient nulle dès la connexion : la broche est sur ADC2. Migrer le capteur sur ADC1 (GPIO32-39).
Réseau 5 GHz. L’ESP32 (sauf C5) ne voit pas un SSID diffusé en 5 GHz uniquement. Activer/cibler le 2,4 GHz.
Boucle de connexion infinie. Le while (WiFi.status() != WL_CONNECTED) bloque indéfiniment si le SSID ou le mot de passe est faux. En projet, borner l’attente (compteur + message d’échec) plutôt que de figer la carte.
Identifiants en clair dans le code. SSID et mot de passe écrits dans le sketch finissent dans le binaire et dans Git. Pour un livrable, les sortir du code (fichier de configuration non versionné, ou portail de configuration).
Brown-out à l’émission. L’émission Wi-Fi appelle des pointes de courant. Sur une alimentation USB faible, la tension chute et la carte redémarre (Brownout detector was triggered). Alimentation et câble soignés.
Page web qui ne répond plus. Oublier serveur.handleClient() dans loop(), ou bloquer la boucle avec un delay long, gèle le serveur. La boucle doit tourner librement.
Exercices
Exercice 1 — Scanner les réseaux
Au démarrage, listez au moniteur série tous les réseaux Wi-Fi détectés, avec leur puissance de signal (RSSI). Quelle fonction de WiFi.h ?
Corrigé
WiFi.scanNetworks() renvoie le nombre de réseaux trouvés. On lit ensuite chaque entrée par index.
#include <WiFi.h>void setup() { Serial.begin(115200); WiFi.mode(WIFI_STA); // mode station pour scanner int n = WiFi.scanNetworks(); Serial.print(n); Serial.println(" reseaux :"); for (int i = 0; i < n; i++) { Serial.print(WiFi.SSID(i)); Serial.print(" "); Serial.print(WiFi.RSSI(i)); // dBm, plus proche de 0 = plus fort Serial.println(" dBm"); }}void loop() {}
Le RSSI (en dBm, négatif) renseigne sur la portée : ~-50 dBm est excellent, ~-80 dBm est faible.
Exercice 2 — Page d'état d'un capteur
Modifiez l’exemple pour que la page web affiche la valeur d’un capteur analogique (sur GPIO34, ADC1) au lieu de piloter une LED. La valeur doit être à jour à chaque rechargement de la page.
Corrigé
La valeur est lue dans le gestionnaire de page, donc relue à chaque requête.
#include <WiFi.h>#include <WebServer.h>const char* ssid = "MonReseau";const char* motDePasse = "********";const int CAPTEUR = 34; // ADC1WebServer serveur(80);void pageAccueil() { int valeur = analogRead(CAPTEUR); // relu à chaque requête String html = "<h1>Capteur</h1><p>Valeur : "; html += valeur; html += " / 4095</p>"; serveur.send(200, "text/html", html);}void setup() { Serial.begin(115200); WiFi.begin(ssid, motDePasse); while (WiFi.status() != WL_CONNECTED) { delay(500); } Serial.println(WiFi.localIP()); serveur.on("/", pageAccueil); serveur.begin();}void loop() { serveur.handleClient();}
Recharger la page dans le navigateur affiche la mesure courante. Pour une mise à jour automatique sans recharger, on ajouterait un rafraîchissement HTML (<meta http-equiv="refresh">) ou du JavaScript.
Cas particulier — La carte comme client (interroger une API)
L’autre direction : l’ESP32 va chercher une donnée sur Internet. La bibliothèque HTTPClient fait une requête en quelques lignes.
#include <WiFi.h>#include <HTTPClient.h>void requete() { if (WiFi.status() == WL_CONNECTED) { HTTPClient http; http.begin("http://exemple.com/api/mesure"); // URL en http simple int code = http.GET(); // > 0 = réponse reçue if (code > 0) { Serial.println(http.getString()); // corps de la réponse } http.end(); }}
Pour une URL en HTTPS (la majorité des API publiques aujourd’hui), il faut un client sécurisé (WiFiClientSecure) et, en toute rigueur, le certificat du serveur (sujet plus avancé, à voir dans la documentation Espressif). En interne (capteur vers serveur local), le HTTP simple suffit souvent.
Raccrochage projet
Étape 4 de la phase de preuve de concept — si le projet est un objet connecté, valider tôt la connexion Wi-Fi et un premier échange (page d’état, publication d’une mesure) lève l’incertitude principale de la PoC. C’est la brique qui justifie souvent le choix de l’ESP32 plutôt qu’un Arduino.
Interface d’exploitation — une page web hébergée par la carte sert d’IHM de secours ou de configuration sur le terrain, sans développer d’application dédiée.
Sortir les identifiants du code et borner les tentatives de connexion dès le prototype évite de transformer une démo en livrable fragile (mot de passe versionné, carte figée si le réseau change).