Станция обслуживания дрона — это комплексный автоматизированный модуль, выполняющий функции замены аккумуляторов и обработки грузов (загрузка/выгрузка) в полностью автономном режиме. Управление ею реализовано с помощью микроконтроллера Arduino Uno, связанного с модулем ESP8266, который подключается к удалённому серверу по WebSocket и обменивается командами в формате JSON.
🔧 Архитектура управления станцией
Станция состоит из нескольких механических компонентов, управляемых шаговыми двигателями и отслеживаемых с помощью концевых датчиков. Управляющая логика разбита на два уровня:
1. Arduino Uno — логика управления станцией
Arduino отвечает за:
-
Поворотную платформу для грузов и аккумуляторов;
-
Подъём/опускание лифта;
-
Фиксацию/освобождение дрона;
-
Механизм загрузки/выгрузки груза;
-
Калибровку всех компонентов;
-
Отправку телеметрии на сервер;
-
Приём JSON-команд через UART от ESP8266 и их выполнение.
Каждый механизм снабжён шаговым двигателем, а его положение контролируется концевыми выключателями. Arduino обрабатывает команды вида:
{ "command": "move_lift", "value": 50, "operation_id": "abc123" }
…и, выполнив их, возвращает результат, например:
{ "type": "operation_result", "success": true, "message": "Lift moved", "operation_id": "abc123" }
Также отправляется телеметрия о текущем состоянии всех систем.
2. ESP8266 — шлюз между сервером и Arduino
ESP8266 подключается к Wi-Fi и устанавливает WebSocket-соединение с сервером. Его роль — посредник:
-
Принимает команды с сервера и передаёт их Arduino через UART.
-
Считывает ответы от Arduino и пересылает обратно на сервер.
-
Автоматически повторно подключается при потере связи.
-
Отвечает на
PING-запросы сервера для поддержания heartbeat и передачи общего статуса работы.
3. Сервер управления
Сервер принимает WebSocket-соединения от устройств и предоставляет пользователю веб-интерфейс (временное решение для тестирования). Он:
-
Хранит список зарегистрированных устройств и пользователей.
-
Обеспечивает аутентификацию устройств.
-
Принимает и маршрутизирует команды, отправленные с веб-интерфейса.
-
Обрабатывает телеметрию и ошибки от устройств.
-
Показывает актуальное состояние системы через веб-интерфейс.
В дальнейшем планируется, что сервер управления будет лишён пользовательского интерфейса и будет действовать как промежуточное звено между системами высокого уровня и станцией, получая команды от внешнего управляющего сервера.
🔑 Принцип работы в реальном времени
-
Пользователь отправляет команду через веб-интерфейс сервера.
-
Сервер отправляет JSON-команду устройству
esp02(станция). -
ESP8266 передаёт JSON по UART на Arduino Uno.
-
Arduino выполняет команду и возвращает JSON-результат.
-
ESP8266 передаёт результат обратно на сервер.
-
Сервер отображает результат пользователю.
📊 Пример телеметрии
{ "type": "telemetry", "status": "работает", "lift_position": 50, "platform_position": 90, "is_drone_locked": true, "has_cargo": false, "is_error": false, "last_operation": "Drone locked", "switches": [true, false, false, true, false, false, true, false] }
🧩 Преимущества архитектуры
-
🔌 Модульность: Arduino Uno отделяет механику от сетевой логики.
-
🌐 Удалённое управление: весь обмен данными через WebSocket.
-
🔁 Устойчивость: повторные подключения, heartbeat, обработка ошибок.
-
🔄 Автоматизация: полностью автоматическое выполнение команд.
Код WIFI модуля
#include <ESP8266WiFi.h> #include <WebSocketsClient.h> #include <ArduinoJson.h> const char* ssid = "ASUS"; const char* password = "123456789098"; WebSocketsClient webSocket; const char* deviceName = "esp02"; const char* devicePassword = "5678"; const int LED_PIN = LED_BUILTIN; unsigned long previousMillis = 0; unsigned long lastConnectionAttempt = 0; const long connectionInterval = 10000; // 10 секунд между попытками подключения int ledState = LOW; int connectionState = 0; // 0 - нет подключения, 1 - WiFi подключен, 2 - WebSocket подключен void updateLed() { unsigned long currentMillis = millis(); unsigned long interval; switch(connectionState) { case 0: // Нет подключения - быстрое мигание (500ms) interval = 500; break; case 1: // WiFi подключен - медленное мигание (1000ms) interval = 1000; break; case 2: // WebSocket подключен - постоянно включен digitalWrite(LED_PIN, LOW); return; } if (currentMillis - previousMillis >= interval) { previousMillis = currentMillis; ledState = (ledState == LOW) ? HIGH : LOW; digitalWrite(LED_PIN, ledState); } } void sendToArduino(const String& message) { Serial.println(message); // Просто перенаправляем сообщение на Arduino } void webSocketEvent(WStype_t type, uint8_t* payload, size_t length) { switch (type) { case WStype_CONNECTED: //Serial.println("[WS] Connected"); connectionState = 2; // WebSocket подключен updateLed(); // Отправляем информацию об устройстве при подключении { StaticJsonDocument<256> doc; doc["type"] = "auth"; doc["name"] = deviceName; doc["password"] = devicePassword; String json; serializeJson(doc, json); webSocket.sendTXT(json); } break; case WStype_DISCONNECTED: //Serial.println("[WS] Disconnected"); connectionState = (WiFi.status() == WL_CONNECTED) ? 1 : 0; break; case WStype_TEXT: //Serial.printf("[WS] Received: %s\n", payload); // Обработка PING if (String((char*)payload) == "PING") { StaticJsonDocument<128> doc; doc["type"] = "telemetry"; doc["status"] = "работает"; String json; serializeJson(doc, json); webSocket.sendTXT(json); } // Обработка команды reboot else if (String((char*)payload) == "reboot") { //Serial.println("Rebooting..."); ESP.restart(); } // Все остальные сообщения просто перенаправляем на Arduino else { //Serial.printf("Сообщения отправлено на arduino\n"); sendToArduino(String((char*)payload)); } break; } } void checkUART() { if (Serial.available() > 0) { String received = Serial.readStringUntil('\n'); received.trim(); if (received.length() > 0) { // Serial.printf("Received from Arduino: %s\n", received.c_str()); // Просто перенаправляем полученные данные на сервер if (webSocket.isConnected()) { webSocket.sendTXT(received); } } } } void setup() { pinMode(LED_PIN, OUTPUT); digitalWrite(LED_PIN, HIGH); Serial.begin(115200); // Инициализация UART для связи с другим Arduino WiFi.begin(ssid, password); // Начальное состояние - нет подключения connectionState = 0; } void loop() { unsigned long currentMillis = millis(); // Обновляем состояние подключения WiFi if (WiFi.status() != WL_CONNECTED) { connectionState = 0; if (currentMillis - lastConnectionAttempt >= connectionInterval) { //Serial.println("Connecting to WiFi..."); WiFi.begin(ssid, password); lastConnectionAttempt = currentMillis; } } else if (connectionState == 0) { connectionState = 1; //Serial.println("\nWiFi connected"); //Serial.print("IP address: "); //Serial.println(WiFi.localIP()); } updateLed(); webSocket.loop(); // Если WiFi подключен, но WebSocket еще нет - пытаемся подключиться if (WiFi.status() == WL_CONNECTED && !webSocket.isConnected() && currentMillis - lastConnectionAttempt >= connectionInterval) { connectionState = 1; //Serial.println("Connecting to WebSocket server..."); webSocket.begin("178.66.182.97", 8765, "/"); webSocket.onEvent(webSocketEvent); webSocket.setReconnectInterval(5000); lastConnectionAttempt = currentMillis; } // Проверяем входящие сообщения от Arduino checkUART(); delay(10); // Небольшая задержка для стабильности }
ссылка на оригинал статьи https://habr.com/ru/articles/923826/
Добавить комментарий