Руководство · Средний · 1.5 hours
Управление роботом из браузера с помощью веб-сервера ESP32
Превратите ESP32 в точку доступа Wi-Fi с собственной страницей управления, чтобы любой телефон мог управлять роботом из браузера без приложения.
Введение
HC-05 требует приложения последовательного терминала и танца с сопоставлением. ESP32 может сделать кое-что лучше: быть собственной сетью и раздавать собственную страницу управления. Подключаете телефон к Wi-Fi робота, открываете браузер и управляете. Ничего устанавливать не нужно, и это работает с любого устройства с браузером.
В ESP32 на кристалле есть Wi-Fi и Bluetooth, два ядра по 240 MHz и достаточно ОЗУ (RAM), чтобы хранить веб-страницу во flash-памяти и раздавать её. В этом весь секрет.
Точка доступа или существующая сеть?
Есть два режима, и выбор важнее, чем кажется.
Точка доступа (AP) — ESP32 создаёт собственную сеть Wi-Fi, и телефон подключается к ней.
- Работает где угодно, без маршрутизатора. Робот самодостаточен.
- Телефон теряет интернет-соединение во время управления, и некоторые телефоны молча переключатся на мобильные данные и отключают вас.
- Адрес всегда один и тот же, обычно
192.168.4.1.
Станция (STA) — ESP32 подключается к существующей сети Wi-Fi.
- Телефон сохраняет интернет-соединение.
- IP-адрес робота назначает маршрутизатор, и он может меняться между загрузками.
- Бесполезно вне зоны действия этой конкретной сети, что исключает демонстрации.
Для переносного робота режим AP почти всегда правильный:
#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
}
Раздача страницы управления
Страница хранится во flash-памяти как необработанная строка. Делайте её небольшой — каждый байт раздаётся с микроконтроллера, — а элементы управления сделайте удобными для касания, потому что весь смысл состоит в управлении с телефона.
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 на кнопках важен: без него мобильные браузеры ждут около 300 ms, чтобы понять, не было ли это двойным нажатием, и робот кажется сломанным.
Аварийный тайм-аут, снова
Всё, что учебник по Bluetooth говорит о потере связи, применимо здесь ещё сильнее: дальность действия Wi-Fi обрывается резко, а не плавно.
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();
}
Браузер отправляет удерживаемую команду каждые 100 ms, поэтому тайм-аут 400 ms допускает три потерянных запроса до остановки. Это соотношение и нужно настраивать: слишком жёсткое — робот заикается на слабой связи, слишком мягкое — продолжает движение после потери связи.
Когда переходить на WebSockets
Подход с fetch выше открывает новое HTTP-соединение для каждой команды. Он прост, его легко отлаживать на вкладке сети браузера, а при 10 командах в секунду он вполне подходит.
Он перестаёт подходить, когда нужна телеметрия обратно. Опрос значений датчиков дополнительными HTTP-запросами удваивает трафик и добавляет задержку в обоих направлениях. WebSocket поддерживает одно открытое соединение и позволяет любой стороне говорить в любой момент:
#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
}
Последняя строка — настоящее улучшение. При HTTP робот может только предположить потерю соединения по молчанию; WebSocket сообщает момент закрытия, поэтому робот останавливается сразу, а не после тайм-аута.
Начните с HTTP. Переходите на WebSockets, когда роботу нужно передавать данные обратно.
Питание
ESP32 — микросхема на 3.3 V, и он потребляет ток резкими импульсами при передаче по радио — значительно больше 200 mA в пике. Отсюда два следствия.
Не питайте его от вывода 3.3 V Arduino. Этот стабилизатор не выдержит пиков передачи, и симптомом будет перезагрузка платы при загруженном Wi-Fi, что выглядит как ошибка кода, но ею не является.
Выводы GPIO не допускают 5 V. Всё, что подаёт сигнал на ESP32 от логики 5 V, нуждается в делителе или преобразователе уровня — как линия RX HC-05.
Подавайте ему отдельное питание от аккумуляторного блока через собственный стабилизатор, а питание двигателей держите отдельным.
Проверьте перед движением
- Раздайте страницу. Подключите телефон к
RobotCar, откройтеhttp://192.168.4.1и убедитесь, что появились кнопки. - Наблюдайте за командами. Печатайте каждую принятую команду по USB. Удерживайте кнопку и убедитесь, что повторы приходят примерно 10 раз в секунду.
- Разорвите связь. Удерживайте движение вперёд, затем выключите Wi-Fi телефона. Робот должен остановиться за время тайм-аута.
Затем поместите это в робота: проект робота с управлением с телефона собирает всю систему с любым из двух радиоспособов на шасси, которое также может двигаться самостоятельно.
Исследуйте граф
Входит в эти сборки
Проекты и учебные пути, в которые входит это руководство.
Дополнительные материалы