Tutorial · Intermediário · 1,5 horas
Controle um robô pelo navegador com um servidor web do ESP32
Transforme um ESP32 em um ponto de acesso Wi-Fi para servir uma página de controle e controlar o robô pelo navegador sem aplicativo.
Introdução
Um HC-05 precisa de um aplicativo de terminal serial e de uma dança de pareamento. Um ESP32 pode fazer algo melhor: ser sua própria rede e servir sua própria página de controle. Você conecta o celular à rede Wi-Fi do robô, informa a senha, abre um navegador e controla o robô. Não há nada para instalar, e funciona em qualquer dispositivo com navegador.
O ESP32 tem Wi-Fi e Bluetooth integrados no mesmo chip, dois núcleos a 240 MHz e RAM suficiente para guardar uma página web na flash e servi-la. Esse é todo o truque.
Ponto de acesso ou rede existente?
Dois modos, e a escolha importa mais do que parece.
Ponto de acesso (AP) — o ESP32 cria sua própria rede Wi-Fi e o celular se conecta a ela.
- Funciona em qualquer lugar, sem roteador. O robô é autossuficiente.
- O celular perde a conexão com a internet enquanto você controla o robô, e alguns celulares voltam silenciosamente para os dados móveis e encerram a conexão.
- O endereço é sempre o mesmo, normalmente
192.168.4.1.
Estação (STA) — o ESP32 entra na sua rede Wi-Fi existente.
- O celular mantém a conexão com a internet.
- O IP do robô é atribuído pelo roteador e pode mudar entre inicializações.
- Não serve fora do alcance daquela rede específica, o que inviabiliza demonstrações fora desse ambiente.
Para um robô que você carrega, o modo AP quase sempre é o certo:
#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
}
Servindo a página de controle
A página fica na flash como um literal de texto. Mantenha-a pequena — cada byte é servido pelo microcontrolador — e faça os controles adequados para toque, porque o ponto todo é controlar o robô pelo celular.
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 nos botões importa: sem isso, navegadores móveis esperam cerca de 300 ms para descobrir se você quis dar um toque duplo, e o robô parece quebrado.
O tempo limite de segurança, novamente
Tudo o que o tutorial de Bluetooth diz sobre perder a conexão se aplica aqui, e isso é ainda mais importante — o sinal do Wi-Fi cai de repente quando você se afasta, em vez de desaparecer gradualmente.
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();
}
O navegador envia o comando mantido a cada 100 ms, então um tempo limite de 400 ms tolera três requisições perdidas antes de parar. Essa proporção é a coisa a ajustar: se for muito apertada, o robô dá solavancos em uma conexão fraca; se for muito folgada, continua se movendo depois que você perdeu a conexão.
Quando migrar para WebSockets
A abordagem com fetch acima abre uma nova conexão HTTP para cada comando. É simples, fácil de depurar na aba de rede do navegador e, a dez comandos por segundo, funciona bem.
Ela deixa de funcionar bem quando você quer telemetria de volta. Consultar valores de sensores com mais requisições HTTP dobra o tráfego e acrescenta latência nos dois sentidos. Um WebSocket mantém uma conexão aberta e permite que qualquer uma das partes fale a qualquer 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(); // the link closing IS a stop command
}
Essa última linha é a verdadeira evolução. Com HTTP, o robô só pode inferir uma conexão perdida pelo silêncio; um WebSocket informa o momento em que ela fecha, então o robô para imediatamente, em vez de depois de um tempo limite.
Comece com HTTP. Migre para WebSockets quando quiser que o robô converse de volta.
Alimentação
O ESP32 opera em 3,3 V e consome corrente em picos quando o rádio transmite — bem acima de 200 mA no pico. Duas consequências:
Não alimente-o pelo pino de 3,3 V do Arduino. Esse regulador não fornece os picos de transmissão, e o sintoma é uma placa que reinicia sempre que o Wi-Fi fica ocupado, o que parece uma falha de código, mas não é.
Seus pinos GPIO não são tolerantes a 5 V. Qualquer sinal de lógica de 5 V alimentado ao ESP32 precisa de um divisor ou de um tradutor de nível, assim como a linha RX do HC-05.
Dê a ele uma fonte de alimentação adequada a partir do pacote de bateria por um regulador próprio, mantendo a fonte do motor separada.
Verifique antes de controlar
- Sirva a página. Conecte um celular à
RobotCar, abrahttp://192.168.4.1e confirme que os botões aparecem. - Observe os comandos. Imprima cada comando recebido pelo USB. Mantenha um botão pressionado e confirme que as repetições chegam a cerca de 10 por segundo.
- Interrompa a conexão. Mantenha o avanço pressionado e desligue o Wi-Fi do celular. O robô precisa parar dentro do tempo limite.
Depois coloque-o em um robô: o projeto de robô controlado por celular constrói tudo, por rádio, em um chassi que também é capaz de se controlar sozinho.
Explore o grafo
Faz parte destas montagens
Projetos e caminhos de aprendizagem que incluem este tutorial.
Leitura complementar