2.5. Проект.md


Поздравляем! Мы научились управлять двигателями, использовать колёса Mecanum, считывать данные с энкодеров и датчиков линии. Теперь пришло время объединить все эти знания в одном большом и интересном проекте. Мы создадим программу, которая превратит нашего робота в «питомца» — он будет самостоятельно следовать за объектом (например, вашей рукой), поддерживая постоянную дистанцию.

  • Если объект далеко - робот подъезжает.
  • Если объект слишком близко - робот отъезжает.
  • Если объект на нужном расстоянии - робот стоит на месте.

Эта задача не только интересна, но и очень полезна. Она научит нас главному — объединять данные с датчиков с системой управления движением, что является основой любой автономной робототехники.

Программирование с помощью классов

До сих пор мы писали код в простом, процедурном стиле. Но когда проект становится сложным, такой код превращается в «спагетти», в котором легко запутаться. Профессиональные программисты используют объектно-ориентированное программирование (ООП), где вся логика работы с компонентом (например, мотором или датчиком) упаковывается в отдельный, самодостаточный блок — класс.

Класс — это шаблон по которому создаются объекты. Например, у нас может быть класс Motor, который описывает, как в принципе управлять мотором. А leftFrontMotor и rightFrontMotor — это уже объекты, созданные по этому шаблону, каждый со своими пинами, но с одинаковым поведением.

Этот подход делает код чистым, читаемым и легко масштабируемым. В этом проекте мы будем использовать готовые классы для мотора и ультразвукового дальномера.

Подключение

Схема подключения остаётся той же, что и в предыдущих работах. Нам понадобятся:

  • Четыре мотора, подключённые через два драйвера L9110S к пинам, которые мы определим в коде.
  • Ультразвуковой дальномер HC-SR04. Подключим его к пинам 7 (Trig) и 6 (Echo).
  • Питание. Не забывайте про внешнее питание для моторов и общей земле с Рудироном.

Программа

В этой программе мы впервые используем классы. Обратите внимание, насколько чистым и понятным становится основной код, когда вся сложная логика спрятана внутри объектов.

// --- Класс для управления ультразвуковым дальномером ---
class Ultrasonic {
  int trig;
  int echo;
public:
  Ultrasonic(int trig, int echo) {
    this->trig = trig;
    this->echo = echo;
  }
  void begin() {
    pinMode(trig, OUTPUT);
    pinMode(echo, INPUT);
  }
  int read() {
    digitalWrite(trig, LOW);
    delayMicroseconds(2);
    digitalWrite(trig, HIGH);
    delayMicroseconds(10);
    digitalWrite(trig, LOW);
    // Преобразуем время в сантиметры и ограничиваем до 300 см
    long duration = pulseIn(echo, HIGH);
    int cm = duration / 58;
    return constrain(cm, 0, 300);
  }
};

// --- Класс для управления одним мотором через драйвер L9110S ---
class Motor {
  int dirPin;
  int speedPin;
public:
  Motor(int dir, int speed) {
    dirPin = dir;
    speedPin = speed;
  }
  void begin() {
    pinMode(dirPin, OUTPUT);
    pinMode(speedPin, OUTPUT);
  }
  // dir=0 - вперёд, dir=1 - назад
  void run(int dir, int speed) {
    digitalWrite(dirPin, dir);
    analogWrite(speedPin, speed);
  }
};

// --- Создаём объекты для наших устройств ---
// Левые моторы
Motor leftFront(13, 12);
Motor leftBack(11, 8);
// Правые моторы
Motor rightFront(A0, 20);
Motor rightBack(A1, A2);
// Дальномер
Ultrasonic ultrasonic(7, 6);

// --- Глобальные переменные ---
int baseSpeed = 200; // Базовая скорость движения робота (0-255)

void setup() {
  // Инициализируем все наши объекты
  leftFront.begin();
  leftBack.begin();
  rightFront.begin();
  rightBack.begin();
  ultrasonic.begin();
  
  Serial.begin(9600); // Для отладки
}

void loop() {
  // Считываем расстояние до объекта
  int distance = ultrasonic.read();
  Serial.print("Расстояние: ");
  Serial.println(distance);

  // --- Основная логика ---
  if (distance > 30 && distance > 0) {
    // Если объект далеко, едем вперёд
    forward(baseSpeed);
  } else if (distance < 20 && distance > 0) {
    // Если объект слишком близко, отъезжаем назад
    backward(baseSpeed);
  } else {
    // Если объект в "зоне комфорта" (20-30 см) или датчик не видит ничего (distance = 0),
    // стоим на месте.
    stopMotors();
  }
  
  delay(50); // Небольшая пауза между циклами
}

// --- Функции для управления движением робота ---
void forward(int speed) {
  leftFront.run(0, speed);
  leftBack.run(0, speed);
  rightFront.run(0, speed);
  rightBack.run(0, speed);
}

void backward(int speed) {
  leftFront.run(1, speed);
  leftBack.run(1, speed);
  rightFront.run(1, speed);
  rightBack.run(1, speed);
}

void stopMotors() {
  leftFront.run(0, 0);
  leftBack.run(0, 0);
  rightFront.run(0, 0);
  rightBack.run(0, 0);
}

Проверка работы

  • Загрузите код на Рудирон.
  • Поставьте робота на пол.
  • Поместите перед ним руку или другой крупный предмет.
  • Двигайте рукой - когда вы её отдаляете, робот должен ехать за ней, когда приближаете - отъезжать.

Выводы

В этом итоговом проекте вы объединили все знания, полученные в этой главе. Вы научились:

  • Программировать с использованием классов, что является шагом к профессиональной разработке.
  • Интегрировать датчики с системой движения, создавая автономное поведение.
  • Отлаживать и настраивать логику робота для достижения нужного результата.

Вы создали не просто набор движущихся частей, а настоящего робота, способного самостоятельно реагировать на окружающий мир. Теперь у вас есть надежная «база» для создания собственных, ещё более сложных и удивительных проектов!