📱 Программирование пульта дистанционного управления

Создаем систему беспроводного управления роботом

🎮 Интерфейс • 📡 Связь • 💻 Программирование • 🔧 Отладка
7 класс • Технология • 45 минут
mw285748 • 15.06.2025

🎯 Цель урока

💡 Научимся:

  • Программировать пульты дистанционного управления
  • Настраивать беспроводные модули связи
  • Создавать системы обработки команд
  • Тестировать и оптимизировать управление

🤖 Результат: Функциональная система дистанционного управления роботом!

🏗️ Архитектура системы управления

📊 Компоненты системы

1[ОПЕРАТОР] ←→ [ПУЛЬТ] ~~~📡~~~ [РОБОТ] ←→ [ДАТЧИКИ]
2    ↑           ↑                    ↑         ↑
3 Команды    Интерфейс           Исполнение  Обратная
4                                            связь

Основные блоки:

  1. Пульт управления - формирование команд
  2. Канал связи - передача данных
  3. Робот - исполнение команд
  4. Обратная связь - контроль состояния

🔄 Цикл управления

Алгоритм работы системы:

 1while True:
 2    # 1. Получение команд от оператора
 3    user_input = read_user_interface()
 4    
 5    # 2. Формирование пакета данных
 6    command_packet = encode_command(user_input)
 7    
 8    # 3. Передача по беспроводному каналу
 9    send_wireless(command_packet)
10    
11    # 4. Получение и обработка на роботе
12    if packet_received():
13        execute_command(decode_packet())
14    
15    # 5. Отправка обратной связи
16    telemetry = read_sensors()
17    send_feedback(telemetry)
18    
19    delay(10)  # Период управления

⏱️ Временные характеристики:

  • Период управления: 10-100 мс
  • Задержка передачи: 5-50 мс
  • Время обработки: 1-10 мс

📱 Программирование пульта управления

🎮 Типы интерфейсов

Мобильное приложение (Android/iOS):

 1// Пример кода для Android
 2public class RobotController extends AppCompatActivity {
 3    private BluetoothAdapter bluetoothAdapter;
 4    private BluetoothSocket socket;
 5    
 6    // Обработка джойстика
 7    @Override
 8    public boolean onTouchEvent(MotionEvent event) {
 9        float x = event.getX();
10        float y = event.getY();
11        
12        // Преобразование координат в команды
13        int speed = calculateSpeed(y);
14        int direction = calculateDirection(x);
15        
16        // Отправка команды
17        sendCommand("MOVE", speed, direction);
18        return true;
19    }
20    
21    private void sendCommand(String type, int param1, int param2) {
22        String command = type + ":" + param1 + ":" + param2 + "\n";
23        socket.getOutputStream().write(command.getBytes());
24    }
25}

🖥️ Веб-интерфейс

HTML + JavaScript:

 1<!DOCTYPE html>
 2<html>
 3<head>
 4    <title>Робот Control</title>
 5</head>
 6<body>
 7    <div class="joystick-container">
 8        <div id="joystick"></div>
 9    </div>
10    
11    <div class="buttons">
12        <button onclick="sendCommand('LED_ON')">💡 Свет</button>
13        <button onclick="sendCommand('HORN')">🔊 Сигнал</button>
14        <button onclick="sendCommand('STOP')">🛑 Стоп</button>
15    </div>
16    
17    <script>
18        // WebSocket соединение
19        const ws = new WebSocket('ws://192.168.1.100:8080');
20        
21        function sendCommand(cmd) {
22            const packet = {
23                command: cmd,
24                timestamp: Date.now(),
25                source: "web_interface"
26            };
27            ws.send(JSON.stringify(packet));
28        }
29        
30        // Виртуальный джойстик
31        const joystick = new VirtualJoystick({
32            container: document.getElementById('joystick'),
33            mouseSupport: true,
34            onMove: function(event, data) {
35                const speed = Math.round(data.force * 100);
36                const angle = Math.round(data.angle.degree);
37                sendCommand(`MOVE:${speed}:${angle}`);
38            }
39        });
40    </script>
41</body>
42</html>

🎛️ Физический пульт

Arduino-пульт с джойстиками:

 1// Пульт на Arduino с nRF24L01
 2#include <SPI.h>
 3#include <nRF24L01.h>
 4#include <RF24.h>
 5
 6RF24 radio(9, 10); // CE, CSN пины
 7const byte address[6] = "Robot1";
 8
 9struct ControlData {
10    int leftStickX;
11    int leftStickY;
12    int rightStickX;
13    int rightStickY;
14    bool button1;
15    bool button2;
16    bool button3;
17    unsigned long timestamp;
18};
19
20void setup() {
21    Serial.begin(9600);
22    radio.begin();
23    radio.openWritingPipe(address);
24    radio.setPALevel(RF24_PA_MIN);
25    radio.stopListening();
26}
27
28void loop() {
29    ControlData data;
30    
31    // Чтение аналоговых джойстиков
32    data.leftStickX = analogRead(A0);
33    data.leftStickY = analogRead(A1);
34    data.rightStickX = analogRead(A2);
35    data.rightStickY = analogRead(A3);
36    
37    // Чтение цифровых кнопок
38    data.button1 = digitalRead(2);
39    data.button2 = digitalRead(3);
40    data.button3 = digitalRead(4);
41    
42    // Временная метка
43    data.timestamp = millis();
44    
45    // Отправка данных
46    bool result = radio.write(&data, sizeof(data));
47    
48    if (result) {
49        Serial.println("Данные отправлены успешно");
50    } else {
51        Serial.println("Ошибка передачи");
52    }
53    
54    delay(50); // 20 пакетов в секунду
55}

📡 Настройка беспроводных модулей

📶 Bluetooth (HC-05/ESP32)

Настройка HC-05:

 1// AT-команды для настройки HC-05
 2void setupBluetooth() {
 3    Serial.begin(9600);
 4    
 5    // Вход в режим AT-команд
 6    delay(1000);
 7    
 8    // Настройка имени устройства
 9    Serial.println("AT+NAME=RobotController");
10    delay(1000);
11    
12    // Настройка скорости передачи
13    Serial.println("AT+UART=115200,0,0");
14    delay(1000);
15    
16    // Настройка пин-кода
17    Serial.println("AT+PSWD=1234");
18    delay(1000);
19    
20    // Роль - ведущий
21    Serial.println("AT+ROLE=1");
22    delay(1000);
23}

ESP32 Bluetooth Classic:

 1#include "BluetoothSerial.h"
 2
 3BluetoothSerial SerialBT;
 4
 5void setup() {
 6    Serial.begin(115200);
 7    SerialBT.begin("ESP32_Robot"); // Имя Bluetooth устройства
 8    Serial.println("Устройство готово к сопряжению");
 9}
10
11void loop() {
12    if (SerialBT.available()) {
13        String command = SerialBT.readString();
14        command.trim();
15        
16        Serial.println("Получена команда: " + command);
17        processCommand(command);
18        
19        // Отправка подтверждения
20        SerialBT.println("OK:" + command);
21    }
22}

📶 Wi-Fi (ESP32/ESP8266)

Точка доступа (AP режим):

 1#include <WiFi.h>
 2#include <WebSocketsServer.h>
 3
 4const char* ssid = "Robot_Control";
 5const char* password = "robot123";
 6
 7WebSocketsServer webSocket = WebSocketsServer(81);
 8
 9void setup() {
10    Serial.begin(115200);
11    
12    // Создание точки доступа
13    WiFi.softAP(ssid, password);
14    Serial.println("AP IP адрес: " + WiFi.softAPIP().toString());
15    
16    // Настройка WebSocket
17    webSocket.begin();
18    webSocket.onEvent(webSocketEvent);
19}
20
21void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t length) {
22    switch(type) {
23        case WStype_DISCONNECTED:
24            Serial.printf("Клиент [%u] отключен\n", num);
25            break;
26            
27        case WStype_CONNECTED:
28            Serial.printf("Клиент [%u] подключен\n", num);
29            break;
30            
31        case WStype_TEXT:
32            String command = String((char*)payload);
33            Serial.println("Получена команда: " + command);
34            processCommand(command);
35            
36            // Отправка ответа
37            webSocket.sendTXT(num, "OK");
38            break;
39    }
40}
41
42void loop() {
43    webSocket.loop();
44}

📻 Радиомодули (nRF24L01)

Настройка приемника:

 1#include <SPI.h>
 2#include <nRF24L01.h>
 3#include <RF24.h>
 4
 5RF24 radio(9, 10); // CE, CSN
 6const byte address[6] = "Robot1";
 7
 8struct CommandPacket {
 9    char command[10];
10    int param1;
11    int param2;
12    unsigned long timestamp;
13    byte checksum;
14};
15
16void setup() {
17    Serial.begin(9600);
18    radio.begin();
19    radio.openReadingPipe(0, address);
20    radio.setPALevel(RF24_PA_MAX); // Максимальная мощность
21    radio.setDataRate(RF24_250KBPS); // Низкая скорость = больше дальность
22    radio.startListening();
23}
24
25void loop() {
26    if (radio.available()) {
27        CommandPacket packet;
28        radio.read(&packet, sizeof(packet));
29        
30        // Проверка целостности
31        if (validateChecksum(packet)) {
32            Serial.println("Команда: " + String(packet.command));
33            executeCommand(packet);
34        } else {
35            Serial.println("Ошибка целостности пакета");
36        }
37    }
38}
39
40bool validateChecksum(CommandPacket& packet) {
41    // Простая проверка контрольной суммы
42    byte calculated = 0;
43    for (int i = 0; i < sizeof(packet) - 1; i++) {
44        calculated ^= ((byte*)&packet)[i];
45    }
46    return calculated == packet.checksum;
47}

🛠️ Практическая работа

📋 Варианты заданий

🟢 Вариант 1: Bluetooth-управление

  • Создать Android/iOS приложение
  • Настроить HC-05 модуль
  • Реализовать виртуальный джойстик
  • Добавить кнопки дополнительных функций

🟡 Вариант 2: Wi-Fi веб-интерфейс

  • Создать ESP32 точку доступа
  • Разработать веб-страницу управления
  • Использовать WebSocket для связи
  • Добавить видеопоток с камеры

🔴 Вариант 3: Радиопульт

  • Собрать физический пульт на Arduino
  • Настроить nRF24L01 модули
  • Создать эргономичный интерфейс
  • Реализовать обратную связь

⏱️ План работы (90 минут)

 1Этап 1: Выбор и планирование (10 мин)
 2• Выбор типа системы управления
 3• Распределение ролей в команде
 4• Планирование архитектуры
 5
 6Этап 2: Настройка связи (15 мин)
 7• Подключение беспроводного модуля
 8• Настройка параметров связи
 9• Тест базового соединения
10
11Этап 3: Программирование пульта (20 мин)
12• Создание интерфейса управления
13• Программирование отправки команд
14• Тестирование элементов управления
15
16Этап 4: Программирование робота (25 мин)
17• Код приема и обработки команд
18• Преобразование команд в действия
19• Обработка ошибок и потери связи
20
21Этап 5: Тестирование и отладка (15 мин)
22• Проверка всех функций
23• Оптимизация параметров
24• Измерение дальности и задержек
25
26Этап 6: Демонстрация (5 мин)
27• Показ работы системы
28• Объяснение реализации

💻 Примеры кода для робота

🤖 Обработка команд движения

 1// Универсальная система обработки команд
 2class RobotController {
 3private:
 4    int leftMotorPin1 = 3, leftMotorPin2 = 5;
 5    int rightMotorPin1 = 6, rightMotorPin2 = 9;
 6    unsigned long lastCommandTime = 0;
 7    const unsigned long TIMEOUT = 3000; // 3 секунды
 8    
 9public:
10    void processCommand(String command) {
11        lastCommandTime = millis();
12        
13        if (command.startsWith("MOVE:")) {
14            // Формат: MOVE:speed:direction
15            int firstColon = command.indexOf(':');
16            int secondColon = command.indexOf(':', firstColon + 1);
17            
18            int speed = command.substring(firstColon + 1, secondColon).toInt();
19            int direction = command.substring(secondColon + 1).toInt();
20            
21            move(speed, direction);
22        }
23        else if (command == "STOP") {
24            stop();
25        }
26        else if (command == "LED_ON") {
27            digitalWrite(13, HIGH);
28        }
29        else if (command == "LED_OFF") {
30            digitalWrite(13, LOW);
31        }
32        else if (command.startsWith("SERVO:")) {
33            int angle = command.substring(6).toInt();
34            setServoAngle(angle);
35        }
36    }
37    
38    void move(int speed, int direction) {
39        // Преобразование скорости и направления в команды моторам
40        int leftSpeed = speed;
41        int rightSpeed = speed;
42        
43        // Коррекция для поворота
44        if (direction < 0) { // Поворот влево
45            leftSpeed = speed * (100 + direction) / 100;
46        } else if (direction > 0) { // Поворот вправо
47            rightSpeed = speed * (100 - direction) / 100;
48        }
49        
50        setMotorSpeed(leftMotorPin1, leftMotorPin2, leftSpeed);
51        setMotorSpeed(rightMotorPin1, rightMotorPin2, rightSpeed);
52    }
53    
54    void checkTimeout() {
55        if (millis() - lastCommandTime > TIMEOUT) {
56            stop(); // Аварийная остановка при потере связи
57        }
58    }
59};

📊 Система обратной связи

 1// Отправка телеметрии
 2void sendTelemetry() {
 3    StaticJsonDocument<200> telemetry;
 4    
 5    telemetry["battery"] = readBatteryVoltage();
 6    telemetry["distance"] = readUltrasonic();
 7    telemetry["temperature"] = readTemperature();
 8    telemetry["position"]["x"] = robotX;
 9    telemetry["position"]["y"] = robotY;
10    telemetry["timestamp"] = millis();
11    
12    String output;
13    serializeJson(telemetry, output);
14    
15    // Отправка через выбранный канал связи
16    if (bluetoothConnected) {
17        SerialBT.println(output);
18    }
19    if (wifiConnected) {
20        webSocket.broadcastTXT(output);
21    }
22}
23
24float readBatteryVoltage() {
25    int raw = analogRead(A7);
26    return (raw * 5.0 / 1023.0) * 2; // Делитель напряжения
27}
28
29int readUltrasonic() {
30    digitalWrite(trigPin, LOW);
31    delayMicroseconds(2);
32    digitalWrite(trigPin, HIGH);
33    delayMicroseconds(10);
34    digitalWrite(trigPin, LOW);
35    
36    long duration = pulseIn(echoPin, HIGH);
37    return duration * 0.034 / 2; // Расстояние в см
38}

🔧 Оптимизация системы

⚡ Повышение надежности

Контроль целостности данных:

 1struct SecurePacket {
 2    char command[16];
 3    int params[4];
 4    unsigned long timestamp;
 5    uint16_t crc16;
 6};
 7
 8uint16_t calculateCRC16(uint8_t* data, size_t length) {
 9    uint16_t crc = 0xFFFF;
10    for (size_t i = 0; i < length; i++) {
11        crc ^= data[i];
12        for (int j = 0; j < 8; j++) {
13            if (crc & 0x0001) {
14                crc = (crc >> 1) ^ 0xA001;
15            } else {
16                crc >>= 1;
17            }
18        }
19    }
20    return crc;
21}

Автоматическое переподключение:

 1void maintainConnection() {
 2    if (!bluetooth.connected()) {
 3        Serial.println("Потеря Bluetooth соединения. Переподключение...");
 4        bluetooth.reconnect();
 5    }
 6    
 7    if (WiFi.status() != WL_CONNECTED) {
 8        Serial.println("Потеря Wi-Fi. Переподключение...");
 9        WiFi.reconnect();
10    }
11}

📡 Оптимизация дальности

Настройки для максимальной дальности:

 1// nRF24L01 настройки
 2radio.setPALevel(RF24_PA_MAX);        // Максимальная мощность
 3radio.setDataRate(RF24_250KBPS);      // Низкая скорость
 4radio.setChannel(76);                 // Свободный канал
 5radio.setRetries(15, 15);             // Максимум повторов
 6radio.enableAckPayload();             // Подтверждение доставки
 7radio.enableDynamicPayloads();        // Динамический размер пакета
 8
 9// ESP32 Wi-Fi настройки
10WiFi.setTxPower(WIFI_POWER_19_5dBm);  // Максимальная мощность
11wifi_config_t conf;
12esp_wifi_get_config(WIFI_IF_AP, &conf);
13conf.ap.max_connection = 1;           // Один клиент
14esp_wifi_set_config(WIFI_IF_AP, &conf);

🎤 Демонстрация проектов

📊 Защита работ

План презентации (3 минуты на команду):

  1. Тип системы - какую технологию выбрали?
  2. Интерфейс - как выглядит пульт управления?
  3. Функции - что умеет делать робот?
  4. Демонстрация - показ в действии
  5. Особенности - уникальные решения

❓ Вопросы для обсуждения:

  • Почему выбрана именно эта технология связи?
  • Какая дальность действия достигнута?
  • Как система ведет себя при помехах?
  • Какие функции можно добавить?

🏆 Критерии оценки

📊 Оценочная матрица (20 баллов):

Критерий Максимум Описание
Настройка связи 5 Стабильность, дальность, качество
Программирование пульта 5 Интерфейс, функциональность, эргономика
Обработка команд 5 Точность, плавность, обработка ошибок
Общий результат 5 Надежность, демонстрация, творчество

🎯 Перевод в оценки:

  • 18-20: “5” (отлично)
  • 14-17: “4” (хорошо)
  • 10-13: “3” (удовлетворительно)

🤔 Рефлексия “3-2-1”

📝 Анализ работы

3 вещи, которые удалось реализовать:

  • 2 трудности, с которыми столкнулись:

  • 1 идея для усовершенствования системы:

    Оценка работы группы (1-5): ___

    🏠 Домашнее задание

    🎯 Основное задание

    Разработать схему усовершенствованного пульта:

    Создать проект пульта управления с дополнительными функциями:

    • Дисплей для отображения телеметрии
    • Кнопки быстрого доступа к функциям
    • Регулировка чувствительности управления
    • Запись и воспроизведение макросов команд

    📋 Структура проекта:

    • Схема расположения элементов
    • Список необходимых компонентов
    • Описание функций каждого элемента
    • Оценка стоимости реализации

    🌟 Исследовательское задание

    Изучить обратную связь в системах управления:

    • Передача видеопотока с камеры робота
    • Телеметрия датчиков в реальном времени
    • Тактильная обратная связь (вибрация)
    • Звуковая индикация состояния робота

    🎉 Итоги урока

    🏆 Что освоили

    ✅ Научились:

    • Программировать интерфейсы дистанционного управления
    • Настраивать различные типы беспроводной связи
    • Создавать системы обработки команд
    • Тестировать и оптимизировать управление

    🧠 Поняли:

    • Программирование пульта требует понимания интерфейсов
    • Настройка связи влияет на качество управления
    • Обработка команд должна быть надежной и быстрой
    • Система управления нуждается в постоянной оптимизации

    🌟 Главный принцип

    “Хорошая система управления = Интуитивный интерфейс + Надежная связь + Быстрая обработка команд”

    🚀 Следующий шаг: Создание автономных роботов с элементами искусственного интеллекта

    💡 Теперь вы можете создать пульт для любого робота!