Проект 11: Управление роботом с помощью ИК-пульта

Робот Фобо управляется инфракрасным пультом! Используем кнопки пульта (▲▼◄► и OK) для ручного управления роботом. Это основа дистанционного управления — в следующих проектах добавим переключение между автономными режимами.

Управление роботом Фобо с ИК-пульта

Как это работает:

  1. Нажимаете кнопку на пульте (например, ▲)

  2. ИК-приёмник получает сигнал и передаёт код кнопки в Arduino

  3. Arduino распознаёт код и выполняет команду (едет вперёд)

  4. Отпускаете кнопку — робот останавливается

Подготовка: Библиотеки AlashIRControlRX и AlashMotorControlLite должны быть установлены (см. Проекты 10, 2).

Рабочий код

Скопируйте и загрузите этот код в Arduino IDE:

/*
 * Проект 11: Управление роботом Фобо с ИК-пульта
 * Кнопки: ▲ - вперёд, ▼ - назад, ◄ - налево, ► - направо, OK - стоп
 */

#include <AlashIRControlRX.h>
#include <AlashMotorControlLite.h>

// ============ ПИНЫ ============
const uint8_t IR_PIN = A3;  // ИК-приёмник на аналоговом пине A3 (используется как цифровой)

// ============ КОДЫ КНОПОК ПУЛЬТА ============
// ВАЖНО: Если ваши коды отличаются, измените их (см. Проект 10)
const unsigned long BTN_UP = 0xFF18E7;      // ▲ Вперёд
const unsigned long BTN_DOWN = 0xFF4AB5;    // ▼ Назад
const unsigned long BTN_LEFT = 0xFF10EF;    // ◄ Налево
const unsigned long BTN_RIGHT = 0xFF5AA5;   // ► Направо
const unsigned long BTN_OK = 0xFF38C7;      // OK - Стоп
const unsigned long BTN_REPEAT = 0xFFFFFFFF; // Код повтора (кнопка удерживается)

// ============ НАСТРОЙКИ СКОРОСТИ ============
const int speedForward = 75;    // Скорость движения вперёд
const int speedBackward = 70;   // Скорость движения назад
const int speedTurn = 65;       // Скорость поворота

// ============ ОБЪЕКТЫ ============
AlashIRControlRX irReceiver(IR_PIN);
AlashMotorControlLite motorRight(DIR_DIR_PWM, 4, 2, 5);   // IN1, IN2, ENA
AlashMotorControlLite motorLeft(DIR_DIR_PWM, 8, 12, 6); // IN3, IN4, ENB

// ============ ПЕРЕМЕННЫЕ СОСТОЯНИЯ ============
unsigned long lastCommand = 0;  // Последняя полученная команда

void setup() {
  Serial.begin(9600);
  irReceiver.begin();

  Serial.println("=== Робот Фобо: Управление с ИК-пульта ===");
  Serial.println("Кнопки: ▲▼◄► - движение, OK - стоп");
  Serial.println("Готов к работе!");

  stopMotors();
}

void loop() {
  if (irReceiver.check()) {
    unsigned long code = irReceiver.data;

    // Игнорируем код повтора, используем последнюю команду
    if (code == BTN_REPEAT) {
      code = lastCommand;
    } else {
      lastCommand = code;
    }

    // Обработка команд
    switch (code) {
      case BTN_UP:
        moveForward();
        Serial.println("▲ ВПЕРЁД");
        break;

      case BTN_DOWN:
        moveBackward();
        Serial.println("▼ НАЗАД");
        break;

      case BTN_LEFT:
        turnLeft();
        Serial.println("◄ НАЛЕВО");
        break;

      case BTN_RIGHT:
        turnRight();
        Serial.println("► НАПРАВО");
        break;

      case BTN_OK:
        stopMotors();
        Serial.println("● СТОП");
        break;

      default:
        // Неизвестная кнопка - показываем код

        Serial.print("? Неизвестная кнопка: 0x");
        Serial.println(code, HEX);
        break;
    }
  }
}

// ============ ФУНКЦИИ ДВИЖЕНИЯ ============
void moveForward() {
  motorLeft.setSpeed(speedForward);
  motorRight.setSpeed(speedForward);
}

void moveBackward() {
  motorLeft.setSpeed(-speedBackward);
  motorRight.setSpeed(-speedBackward);
}

void turnLeft() {
  // Поворот на месте: левый назад, правый вперёд
  motorLeft.setSpeed(-speedTurn);
  motorRight.setSpeed(speedTurn);
}

void turnRight() {
  // Поворот на месте: левый вперёд, правый назад
  motorLeft.setSpeed(speedTurn);
  motorRight.setSpeed(-speedTurn);
}

void stopMotors() {
  motorLeft.stop();
  motorRight.stop();
}

Как работает код:

  • irReceiver.check() — проверяет, получен ли сигнал с пульта

  • Код повтора (0xFFFFFFFF) — игнорируется, используется последняя команда

  • switch-case — распознаёт кнопку и вызывает нужную функцию

  • Повороты на месте — один мотор вперёд, другой назад

  • Serial Monitor — показывает какая кнопка нажата

Загрузка и запуск

Примечание

Процесс загрузки кода: см. подробную инструкцию в Уроке 1.

Важно: Коды кнопок могут отличаться! Если ваши коды не совпадают, используйте программу сканирования из Проекта 10 и замените их в разделе «КОДЫ КНОПОК ПУЛЬТА».

Тестирование

  1. Отключите USB, вставьте батареи

  2. Включите питание (переключатель на батарейном отсеке)

  3. Наведите пульт на ИК-приёмник (угол до 30°)

  4. Нажимайте кнопки: - ▲ — робот едет вперёд - ▼ — робот едет назад - ◄ — робот поворачивает налево на месте - ► — робот поворачивает направо на месте - OK — робот останавливается

Предупреждение

Безопасность:

  • Тестируйте на открытом пространстве (2×2 метра)

  • Держите пульт наготове для остановки (кнопка OK)

  • Не допускайте падения робота со стола!

Эксперименты

Эксперимент 1: Регулировка скорости

Попробуйте разные значения скорости:

const int speedForward = 50;   // Медленное движение
const int speedTurn = 40;
const int speedForward = 100;  // Быстрое движение
const int speedTurn = 80;

Вопрос: При какой скорости робот наиболее управляем? При какой самый быстрый?

Эксперимент 2: Плавные повороты

Измените функции поворотов на плавные (движение по дуге):

void turnLeft() {
  // Плавный поворот: правый быстрее, левый медленнее
  motorLeft.setSpeed(speedTurn / 2);
  motorRight.setSpeed(speedTurn);
}

void turnRight() {
  // Плавный поворот: левый быстрее, правый медленнее
  motorLeft.setSpeed(speedTurn);
  motorRight.setSpeed(speedTurn / 2);
}

Задание: Сравните повороты на месте и плавные повороты. Какой вариант удобнее для управления?

Эксперимент 3: Автостоп при потере сигнала

Добавьте автоматическую остановку, если сигнал не приходит более 500 мс:

unsigned long lastSignalTime = 0;

void loop() {
  if (irReceiver.check()) {
    unsigned long code = irReceiver.data;
    lastSignalTime = millis();  // Запоминаем время последнего сигнала

    // ... обработка команд ...
  }

  // Автостоп через 500 мс без сигнала
  if (millis() - lastSignalTime > 500) {
    stopMotors();
  }
}

Вопрос: Как изменилось поведение робота? Останавливается ли он сразу после отпускания кнопки?

Эксперимент 4: Дополнительные кнопки

Добавьте функции для других кнопок пульта (1-9, *, #):

const unsigned long BTN_1 = 0xFFA25D;  // Кнопка "1" - медленная скорость
const unsigned long BTN_2 = 0xFF629D;  // Кнопка "2" - средняя скорость
const unsigned long BTN_3 = 0xFFE21D;  // Кнопка "3" - быстрая скорость

int currentSpeed = 75;  // Глобальная переменная скорости

// В switch добавить:
case BTN_1:
  currentSpeed = 50;
  Serial.println("Скорость: МЕДЛЕННАЯ");
  break;

case BTN_2:
  currentSpeed = 75;
  Serial.println("Скорость: СРЕДНЯЯ");
  break;

case BTN_3:
  currentSpeed = 100;
  Serial.println("Скорость: БЫСТРАЯ");
  break;

// И в функциях использовать currentSpeed вместо speedForward

Задание: Реализуйте переключение скоростей кнопками 1-2-3.

Решение проблем

Проблема 1: Робот не реагирует на пульт

Решение: См. раздел «Поиск неисправностей» в Проекте 10.

Проблема 2: Коды кнопок не совпадают

Решение: Используйте программу сканирования из Проекта 10 и замените коды в разделе «КОДЫ КНОПОК ПУЛЬТА».

Проблема 3: Робот продолжает движение после отпускания кнопки

Решение: Используйте Эксперимент 3 (автостоп при потере сигнала).

Проблема 4: Робот едет криво при движении вперёд

Решение: Откалибруйте моторы (см. Проект 2) или добавьте коррекцию:

void moveForward() {
  motorLeft.setSpeed(speedForward);
  motorRight.setSpeed(speedForward - 5);  // Коррекция для правого мотора
}

Заключение

Отлично! 🎉 Теперь робот Фобо управляется дистанционно!

Что вы узнали:

✅ Приём и обработку ИК-сигналов с пульта

✅ Распознавание кодов кнопок и фильтрацию повторов

✅ Ручное управление роботом (вперёд, назад, повороты)

✅ Отладку через Serial Monitor

Что дальше:

  • Проект 12: Bluetooth HM-10 — беспроводная связь с телефоном

  • Проект 13: Управление по Bluetooth — управление со смартфона

  • Проект 14: Мастер-режим — переключение между автономными режимами!

В Проекте 14 мы объединим ИК-пульт с автономными режимами (следование за рукой, объезд препятствий, движение по линии) — одна кнопка запускает режим, другая останавливает!

Успехов в управлении роботом! 🤖🎮