Arduino

Оптический разрывной датчик и ИК-модуль обхода препятствий для робота

1 просмотров

Введение

Оптический разрывной датчик (slot/break-beam sensor) и комплексный модуль «умная машинка, датчик препятствий, инфракрасный датчик, фотоэлектрический переключатель» — оба относятся к категории оптических датчиков обнаружения объекта, но с разной геометрией применения: разрывной датчик обнаруживает объект, проходящий через специальную щель датчика, а модуль обхода препятствий — объект, отражающий ИК-излучение перед датчиком на некотором расстоянии, что типично для роботов, объезжающих препятствия.

Концепция

Оптический разрывной датчик содержит излучатель и приёмник, расположенные друг напротив друга через небольшую щель — пока щель свободна, приёмник получает излучение непрерывно, и любой тонкий объект, проходящий через щель (например, спица колеса, перфорированная полоса), временно прерывает этот луч, что датчик регистрирует как дискретное событие — классическое применение — счётчики оборотов (аналогично датчику Холла, но через оптический, а не магнитный принцип) или детекторы прохождения объекта через определённую точку. Модуль обхода препятствий для робота, в отличие от разрывного датчика, использует отражённое излучение — излучатель и приёмник расположены рядом друг с другом, направленными в одну сторону, и приёмник регистрирует количество отражённого от близко расположенного объекта излучения, что позволяет обнаруживать препятствие перед роботом без необходимости физического контакта.

Пример кода

// Оптический разрывной датчик — счётчик прохождений объекта через щель
const int SLOT_SENSOR_PIN = 2;
volatile unsigned long passCount = 0;

void slotSensorInterrupt() {
    passCount++;
}

void setupSlotSensor() {
    pinMode(SLOT_SENSOR_PIN, INPUT);
    attachInterrupt(digitalPinToInterrupt(SLOT_SENSOR_PIN), slotSensorInterrupt, FALLING);
}

// Практическое применение — измерение скорости через перфорированный диск
float calculateRpm(int slotsPerRevolution, unsigned long measurementWindowMs) {
    float revolutions = (float)passCount / slotsPerRevolution;
    float rpm = revolutions / (measurementWindowMs / 60000.0);
    passCount = 0;
    return rpm;
}
// ИК-модуль обхода препятствий — типичная конфигурация двух датчиков для робота
const int LEFT_OBSTACLE_PIN = 4;
const int RIGHT_OBSTACLE_PIN = 5;

void setupObstacleAvoidance() {
    pinMode(LEFT_OBSTACLE_PIN, INPUT);
    pinMode(RIGHT_OBSTACLE_PIN, INPUT);
}

enum class RobotAction { FORWARD, TURN_LEFT, TURN_RIGHT, STOP };

RobotAction decideNextAction() {
    // Большинство ИК-модулей обхода препятствий дают LOW при обнаружении препятствия
    bool leftBlocked = !digitalRead(LEFT_OBSTACLE_PIN);
    bool rightBlocked = !digitalRead(RIGHT_OBSTACLE_PIN);

    if (leftBlocked && rightBlocked) return RobotAction::STOP;
    if (leftBlocked) return RobotAction::TURN_RIGHT;  // препятствие слева — уходим вправо
    if (rightBlocked) return RobotAction::TURN_LEFT;   // препятствие справа — уходим влево
    return RobotAction::FORWARD;
}

Пояснения к коду

slotSensorInterrupt()/calculateRpm() показывают практически идентичный по структуре подход к измерению скорости вращения, что и для датчика Холла — оба используют прерывание для подсчёта дискретных событий за известный промежуток времени, отличаясь лишь физическим принципом обнаружения (оптическим прерыванием луча против магнитного поля), что подтверждает общий паттерн: многие разные по физике датчики решают концептуально одну и ту же задачу подсчёта дискретных событий, и код их обработки часто структурно похож. decideNextAction() показывает простую, но практичную логику принятия решения для робота с двумя датчиками препятствий — при обнаружении препятствия только с одной стороны робот поворачивает в противоположную, свободную сторону, а при обнаружении препятствий с обеих сторон одновременно — останавливается, не имея однозначно безопасного направления для продолжения движения вперёд.

Подводные камни

  • Использование оптического разрывного датчика на ярком, прямом солнечном свете без защиты от внешней засветки — поскольку датчик опирается на собственный, относительно слабый ИК-излучатель, интенсивный посторонний источник ИК-излучения (солнечный свет содержит значительную ИК-составляющую) может «ослепить» приёмник, делая невозможным надёжное обнаружение прерывания луча собственным излучателем датчика; для применений на открытом воздухе стоит рассмотреть экранирование датчика от прямого попадания посторонних источников излучения.
  • Слишком простая, «реактивная» логика обхода препятствий без какой-либо памяти о предыдущих решениях, как в показанном упрощённом примере decideNextAction() — робот, реагирующий исключительно на текущие, мгновенные показания датчиков, может попасть в колебательный цикл (например, поочерёдно «видя» препятствие то слева, то справа в узком проходе, постоянно дёргаясь между поворотами без реального продвижения), и для более надёжного поведения стоит добавить логику, учитывающую недавнюю историю принятых решений, а не только мгновенный снимок показаний датчиков.
  • Использование только двух ИК-датчиков обхода препятствий (направленных вперёд) для робота, движущегося с заметной скоростью, без датчика, направленного вперёд по центру — конфигурация из примера хорошо обнаруживает препятствия по бокам, но может пропустить узкое препятствие прямо по центру направления движения, если оно находится между зонами обнаружения левого и правого датчика; для более надёжного обхода препятствий стоит рассмотреть добавление третьего, центрального датчика или датчика с более широким углом обнаружения (например, ультразвукового, который часто комбинируют именно с боковыми ИК-датчиками для более полного покрытия).
  • Игнорирование того, что дальность срабатывания ИК-модулей обхода препятствий обычно нерегулируема программно (хотя у многих физических модулей есть подстроечный потенциометр непосредственно на самой плате для аппаратной регулировки чувствительности) — попытка изменить эффективную дальность обнаружения исключительно через изменение кода (без физической настройки потенциометра на модуле) не даст желаемого эффекта, поскольку порог обнаружения в таких модулях обычно устанавливается именно аппаратно, встроенным компаратором на плате, а не считывается как аналоговое значение, доступное для программной интерпретации с произвольным порогом.