Tutorial · Intermedio · 1.5 horas
Conduce un robot desde el navegador con un ESP32
Convierte un ESP32 en un punto de acceso Wi-Fi que sirve su propia página de control, para pilotar el robot desde el navegador del móvil sin instalar nada.
Introduccion
Un HC-05 necesita una aplicacion de terminal serie y un baile de emparejamiento. Un ESP32 puede hacer algo mejor: ser su propia red y servir su propia pagina de control. Conectas el movil al Wi-Fi del robot, abres un navegador y conduces. Nada que instalar y funciona desde cualquier dispositivo con navegador.
El ESP32 lleva Wi-Fi y Bluetooth en el propio chip, dos nucleos a 240 MHz y RAM suficiente para guardar una pagina web en flash y servirla. Ese es todo el truco.
Punto de acceso o red existente?
Dos modos, y la eleccion importa mas de lo que parece.
Punto de acceso (AP): el ESP32 crea su propia red Wi-Fi y el movil se une a ella.
- Funciona en cualquier sitio, sin router. El robot es autonomo.
- El movil pierde su conexion a internet mientras conduce, y algunos telefonos volveran en silencio a los datos moviles y te desconectaran.
- La direccion es siempre la misma, tipicamente
192.168.4.1.
Estacion (STA): el ESP32 se une a tu Wi-Fi existente.
- El movil conserva su conexion a internet.
- El router asigna la IP del robot y esta puede cambiar entre arranques.
- Inutil fuera del alcance de esa red concreta, lo que descarta las demostraciones.
Para un robot que llevas contigo, el modo AP casi siempre es lo correcto:
#include <WiFi.h>
#include <WebServer.h>
WebServer server(80);
void setup() {
WiFi.softAP("RobotCar", "drive1234"); // la contrasena debe tener 8 caracteres o mas
Serial.println(WiFi.softAPIP()); // 192.168.4.1
server.on("/", handleRoot);
server.on("/cmd", handleCommand);
server.begin();
}
void loop() {
server.handleClient();
applyDeadman(); // ver mas abajo: esto no es opcional
}
Servir la pagina de control
La pagina vive en flash como una cadena literal. Mantenla pequena (cada byte se sirve desde un microcontrolador) y haz los controles aptos para el tacto, porque el objetivo es conducir desde un movil.
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')) {
// Repite mientras se mantiene pulsado, para que soltar y perder senal se vean igual para el 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); }
El touch-action: manipulation en los botones importa: sin el, los navegadores moviles esperan unos 300 ms para ver si querias hacer doble toque, y el robot se siente averiado.
El tiempo de espera de hombre muerto, otra vez
Todo lo que dice el tutorial de Bluetooth sobre perder el enlace se aplica aqui, y mas aun: el alcance del Wi-Fi termina de golpe en lugar de hacerlo con elegancia.
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();
}
El navegador envia la orden mantenida cada 100 ms, asi que un tiempo de espera de 400 ms tolera tres peticiones perdidas antes de detenerse. Esa proporcion es lo que hay que ajustar: demasiado estrecha y el robot tartamudea con un enlace debil; demasiado holgada y sigue conduciendo despues de haberlo perdido.
Cuando pasar a WebSockets
El enfoque con fetch anterior abre una conexion HTTP nueva por cada orden. Es sencillo, se depura facil en la pestana de red del navegador y a 10 ordenes por segundo va bien.
Deja de ir bien cuando quieres telemetria de vuelta. Consultar valores de sensores con mas peticiones HTTP duplica el trafico y anade latencia en ambos sentidos. Un WebSocket mantiene una sola conexion abierta y permite que cualquiera de los dos lados hable en cualquier momento:
#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(); // que se cierre el enlace ES una orden de parada
}
Esa ultima linea es la mejora de verdad. Con HTTP el robot solo puede inferir una conexion perdida a partir del silencio; un WebSocket te avisa en el momento en que se cierra, asi que el robot se detiene de inmediato en lugar de tras un tiempo de espera.
Empieza con HTTP. Pasa a WebSockets cuando quieras que el robot te hable de vuelta.
Alimentarlo
El ESP32 es un componente de 3,3 V y consume corriente en rafagas bruscas cuando la radio transmite: bastante mas de 200 mA en el pico. Dos consecuencias:
No lo alimentes desde el pin de 3,3 V del Arduino. Ese regulador no puede suministrar los picos de transmision, y el sintoma es una placa que se reinicia cada vez que el Wi-Fi se ocupa, lo que parece un fallo de codigo y no lo es.
Sus pines GPIO no toleran 5 V. Cualquier cosa que meta una senal dentro del ESP32 desde logica de 5 V necesita un divisor o un adaptador de nivel, igual que la linea RX del HC-05.
Dale una alimentacion adecuada desde el paquete de baterias a traves de su propio regulador, con la alimentacion de los motores mantenida aparte.
Verifica antes de conducir
- Sirve la pagina. Conecta un movil a
RobotCar, abrehttp://192.168.4.1y confirma que aparecen los botones. - Observa las ordenes. Imprime cada orden recibida por USB. Manten pulsado un boton y confirma que las repeticiones llegan a unas 10 por segundo.
- Corta el enlace. Manten pulsado avance y luego apaga el Wi-Fi del movil. El robot debe detenerse dentro del tiempo de espera.
Despues metelo en un robot: el proyecto de robot controlado por movil construye todo el conjunto, con cualquiera de las dos radios, sobre un chasis que tambien puede conducirse solo.
Explora el grafo
Forma parte de estos montajes
Proyectos y rutas de aprendizaje que incluyen este tutorial.
Lecturas adicionales