Tutoriel · Intermédiaire · 1,5 h de lecture

Piloter un robot depuis un navigateur avec un serveur web ESP32

Transformez un ESP32 en point d'accès Wi-Fi servant sa propre page de commande, pour piloter le robot depuis le navigateur du téléphone, sans rien installer.

Introduction

Un HC-05 exige une application de terminal série et une danse d’appairage. Un ESP32 peut faire mieux : être son propre réseau et servir sa propre page de commande. Vous connectez votre téléphone au Wi-Fi du robot, ouvrez un navigateur, et pilotez. Rien à installer, et cela marche depuis tout appareil avec un navigateur.

L’ESP32 a le Wi-Fi et le Bluetooth sur la puce, deux cœurs à 240 MHz, et assez de RAM pour tenir une page web en flash et la servir. C’est toute l’astuce.

Un schéma de flux vertical en cinq étapes. Un navigateur de téléphone envoie une requête HTTP GET pour la route avant. L'ESP32, agissant comme point d'accès logiciel ou joint à un réseau, la reçoit. Son serveur HTTP aiguille la requête vers un gestionnaire. Le gestionnaire pilote les broches de sens et la PWM du driver moteur. Les roues tournent et le robot avance. Une note avertit qu'un chien de garde arrête les moteurs si les requêtes cessent d'arriver.
Toutes les couches entre un pouce et une roue. Le chien de garde compte le plus : sans lui, une connexion perdue laisse le robot rouler. Télécharger le SVG

Point d’accès ou réseau existant ?

Deux modes, et le choix compte plus qu’il n’y paraît.

Point d’accès (AP) — l’ESP32 crée son propre réseau Wi-Fi et le téléphone s’y joint.

  • Marche partout, sans routeur. Le robot est autonome.
  • Le téléphone perd sa connexion internet en pilotant, et certains téléphones rebascueront silencieusement vers les données mobiles et vous lâcheront.
  • L’adresse est toujours la même, typiquement 192.168.4.1.

Station (STA) — l’ESP32 rejoint votre Wi-Fi existant.

  • Le téléphone garde sa connexion internet.
  • L’IP du robot est attribuée par le routeur et peut changer entre démarrages.
  • Inutile hors de portée de cet unique réseau, ce qui exclut les démos.

Pour un robot que vous transportez, le mode AP est presque toujours le bon :

#include <WiFi.h>
#include <WebServer.h>

WebServer server(80);

void setup() {
  WiFi.softAP("RobotCar", "drive1234");   // password must be 8+ characters
  Serial.println(WiFi.softAPIP());        // 192.168.4.1
  server.on("/", handleRoot);
  server.on("/cmd", handleCommand);
  server.begin();
}

void loop() {
  server.handleClient();
  applyDeadman();                          // see below — this is not optional
}

Servir la page de commande

La page vit en flash comme chaîne brute. Gardez-la petite — chaque octet est servi depuis un microcontrôleur — et faites des commandes adaptées au tactile, parce que tout le propos est de piloter depuis un téléphone.

const char PAGE[] PROGMEM = R"(
<!doctype html><meta name=viewport content="width=device-width,initial-scale=1">
<style>
  body{font-family:system-ui;margin:0;display:grid;place-items:center;height:100vh}
  button{width:90px;height:90px;font-size:24px;margin:4px;touch-action:manipulation}
</style>
<div>
  <div style="text-align:center"><button data-c="F">▲</button></div>
  <div><button data-c="L">◀</button><button data-c="S">■</button><button data-c="R">▶</button></div>
  <div style="text-align:center"><button data-c="B">▼</button></div>
</div>
<script>
let held = null;
const send = c => fetch('/cmd?c=' + c);
for (const b of document.querySelectorAll('button')) {
  // Repeat while held, so releasing and losing signal look the same to the robot.
  b.onpointerdown = e => { held = b.dataset.c; send(held);
                           b.setPointerCapture(e.pointerId); };
  b.onpointerup = b.onpointercancel = () => { held = null; send('S'); };
}
setInterval(() => held && send(held), 100);
</script>
)";

void handleRoot() { server.send_P(200, "text/html", PAGE); }

touch-action: manipulation sur les boutons compte : sans cela, les navigateurs mobiles attendent ~300 ms pour voir si vous vouliez un double-tap, et le robot semble cassé.

Le délai de sécurité, encore

Tout ce que le tutoriel Bluetooth dit de la perte de liaison s’applique ici, et davantage — la portée Wi-Fi finit abruptement plutôt qu’en douceur.

unsigned long lastCommandAt = 0;

void handleCommand() {
  char c = server.arg("c")[0];
  drive(c);
  lastCommandAt = millis();
  server.send(200, "text/plain", "ok");
}

void applyDeadman() {
  if (millis() - lastCommandAt > 400) stop();
}

Le navigateur envoie la commande maintenue toutes les 100 ms, donc un délai de 400 ms tolère trois requêtes perdues avant d’arrêter. Ce rapport est la chose à régler : trop serré et le robot saccade sur une liaison faible, trop lâche et il continue de rouler après que vous l’avez perdu.

Quand passer aux WebSockets

L’approche fetch ci-dessus ouvre une connexion HTTP fraîche pour chaque commande. C’est simple, c’est facile à déboguer dans l’onglet réseau du navigateur, et à 10 commandes par seconde cela suffit.

Cela cesse de suffire quand vous voulez de la télémétrie en retour. Sondez les valeurs des capteurs avec plus de requêtes HTTP et vous doublez le trafic et ajoutez de la latence dans les deux sens. Un WebSocket tient une connexion ouverte et laisse chaque côté parler à tout moment :

#include <WebSocketsServer.h>
WebSocketsServer ws(81);

void onWsEvent(uint8_t num, WStype_t type, uint8_t* payload, size_t len) {
  if (type == WStype_TEXT) { drive(payload[0]); lastCommandAt = millis(); }
  if (type == WStype_DISCONNECTED) stop();   // the link closing IS a stop command
}

Cette dernière ligne est la vraie amélioration. Avec HTTP le robot ne peut qu’inférer une connexion perdue du silence ; un WebSocket vous dit dès qu’elle se ferme, donc le robot s’arrête immédiatement au lieu d’après un délai.

Commencez en HTTP. Passez aux WebSockets quand vous voulez que le robot réponde.

L’alimenter

L’ESP32 est un composant 3,3 V et tire le courant par à-coups violents quand la radio émet — bien plus de 200 mA en crête. Deux conséquences :

Ne l’alimentez pas depuis la broche 3,3 V de l’Arduino. Ce régulateur ne peut pas fournir les crêtes d’émission, et le symptôme est une carte qui redémarre dès que le Wi-Fi s’active, ce qui ressemble à un bogue de code et n’en est pas un.

Ses broches GPIO ne tolèrent pas le 5 V. Tout ce qui injecte un signal dans l’ESP32 depuis de la logique 5 V exige un diviseur ou un adaptateur de niveaux, comme la ligne RX du HC-05.

Donnez-lui une alimentation propre depuis le pack de batteries via son propre régulateur, avec l’alimentation moteur gardée séparée.

Vérifiez avant de rouler

  1. Servez la page. Connectez un téléphone à RobotCar, ouvrez http://192.168.4.1, et confirmez que les boutons apparaissent.
  2. Observez les commandes. Affichez chaque commande reçue sur USB. Maintenez un bouton et confirmez que les répétitions arrivent à environ 10 par seconde.
  3. Coupez la liaison. Maintenez avant, puis coupez le Wi-Fi de votre téléphone. Le robot doit s’arrêter dans le délai.

Puis mettez-le dans un robot : le projet de robot commandé au téléphone construit le tout, avec l’une ou l’autre radio, sur un châssis qui peut aussi rouler seul.

Explorer le graphe

Fait partie de ces réalisations

Les projets et parcours d'apprentissage qui incluent ce tutoriel.

Pour aller plus loin

Références