Skip to main content

Отказоустойчивость (Fault Tolerance). Как сделать робота, который не подведет

Представьте: ваш робот участвует в соревнованиях. Все зависит от финального заезда. И в этот момент:

  • Отвалился провод от датчика
  • Батарея почти села
  • Программа зависла на полпути

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


Три уровня защиты робота

1. Аппаратная защита (Железо)

Задача: Не дать роботу сломаться физически.

Концевики (Limit switches):

Как работают: Физическая кнопка на краю движения
Где ставить: В конце хода манипулятора, на дверце
Что делает: "Упёрся — дальше нельзя, мотор выключить!"

Предохранители и самовосстанавливающиеся:

Ситуация: Короткое замыкание в моторе
Без защиты: Контроллер сгорает (50$)
С защитой: Перегорает предохранитель (0.10$)

Дублирование датчиков:

Пример: Два ультразвуковых датчика вместо одного
Если один сломался → использовать второй
Если показывают разное → использовать среднее

2. Программная защита (Код)

Задача: Не дать программе зависнуть или делать глупости.

Watchdog Timer (Сторожевой таймер):

Как работает:
1. Заводим таймер на 1 секунду
2. В основном цикле постоянно его сбрасываем
3. Если программа зависла  таймер досчитает до 0
4. Робот перезагрузится

На Arduino:
#include <avr/wdt.h>
void setup() { wdt_enable(WDTO_1S); }
void loop() {
  wdt_reset(); // "Я живой!"
  // ... основной код ...
}

Проверка “здравого смысла” (Sanity Check):

float readTemperature() {
  float temp = sensor.readTemp();
  
  // НЕВЕРОЯТНЫЕ значения
  if (temp < -50 || temp > 150) {
    logError("Датчик температуры сломан");
    return DEFAULT_TEMP; // Возвращаем безопасное значение
  }
  
  // СЛИШКОМ БЫСТРОЕ изменение
  static float lastTemp = 20;
  if (abs(temp - lastTemp) > 10) { // +10°C за 1 цикл?
    logWarning("Подозрительный скачок температуры");
    // Используем среднее
    temp = (temp + lastTemp) / 2;
  }
  
  lastTemp = temp;
  return temp;
}

Таймауты (Timeouts):

bool readFromSensor(int sensorPin, int timeoutMs = 100) {
  unsigned long startTime = millis();
  
  while (digitalRead(sensorPin) == HIGH) {
    if (millis() - startTime > timeoutMs) {
      // Датчик не ответил вовремя
      return false; // Не зависаем вечно!
    }
  }
  return true;
}

3. Поведенческая защита (Что делать при проблемах)

Задача: Даже если что-то сломалось, робот должен вести себя безопасно.

Failsafe (Безопасный отказ):

Ситуация: Потеря связи с пультом управления
ПЛОХО: Продолжать ехать с той же скоростью
ХОРОШО: Плавно остановиться, включить аварийные огни

Return to Home (Вернуться домой):

Для дронов и мобильных роботов:
1. Батарея < 15% → лететь/ехать к зарядке
2. Потеря связи > 5 сек → возвращаться по GPS
3. Ошибка компаса → зависнуть/остановиться

Graceful Degradation (Плавная деградация):

Если сломался один из двух моторов:
• Не падать и не останавливаться
• Продолжать ехать на одном моторе, но медленнее
• Сообщить: "Работаю в ограниченном режиме"

Практические примеры для школьных проектов

Пример 1: Робот-манипулятор для соревнований

class RobotArm {
private:
  bool isSafeToMove() {
    // Проверяем ВСЕ условия безопасности:
    // 1. Батарея не слишком разряжена
    if (getBatteryVoltage() < 6.0) return false;
    
    // 2. Моторы не перегреты
    if (getMotorTemperature() > 80) return false;
    
    // 3. Не упёрлись в концевик
    if (limitSwitchPressed()) return false;
    
    // 4. Связь с контроллером есть
    if (!isControllerConnected()) return false;
    
    return true;
  }
  
public:
  void moveToPosition(float x, float y) {
    if (!isSafeToMove()) {
      emergencyStop();
      return;
    }
    
    // Только если всё безопасно — двигаемся
    // ...
  }
};

Пример 2: Автономный робот-уборщик

Цикл работы:
1. Еду по комнате
2. Каждые 100 мс проверяю:
   • Напряжение батареи (> 3.3V?)
   • Связь с ИК-датчиками (все отвечают?)
   • Температура моторов (< 70°C?)
   • Программа не зависла (watchdog сбрасываю)
3. При любой проблеме:
   • Останавливаюсь
   • Мигаю красным светодиодом
   • Жду 5 секунд (может самоисправиться)
   • Если не помогло — еду на зарядку

Пример 3: Робот для выставки (много людей вокруг)

Особые меры безопасности:
1. Датчик приближения спереди и сзади
2. Если кто-то ближе 30 см — немедленно остановиться
3. Максимальная скорость 0.5 м/с
4. Яркие светодиоды, показывающие направление движения
5. Кнопка "СТОП" на верхней панели

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

Что мониторить:

struct RobotHealth {
  float batteryVoltage;     // Напряжение батареи
  float motorCurrent[4];    // Ток каждого мотора
  float cpuTemperature;     // Температура процессора
  uint32_t freeMemory;      // Свободная память
  uint32_t uptime;          // Время работы
  uint32_t errorCount;      // Количество ошибок
  uint8_t sensorStatus;     // Статус датчиков (битовая маска)
};

void checkHealth() {
  RobotHealth health;
  
  // Собираем данные
  health.batteryVoltage = readBatteryVoltage();
  health.motorCurrent[0] = readMotorCurrent(0);
  // ... и так далее
  
  // Проверяем критические параметры
  if (health.batteryVoltage < CRITICAL_VOLTAGE) {
    enterEmergencyMode();
  }
  
  // Отправляем телеметрию
  sendTelemetry(health);
  
  // Логируем для анализа
  logHealthData(health);
}

Индикация состояния:

Светодиоды на роботе:
• ЗЕЛЁНЫЙ: Всё хорошо
• ЖЁЛТЫЙ: Предупреждение (батарея 15%)
• КРАСНЫЙ: Ошибка (остановка)
• СИНИЙ мигает: Идёт зарядка

Звуковые сигналы:
• 1 писк: Начало работы
• 2 писка: Низкий заряд
• Непрерывный писк: Авария!

Как тестировать надежность

Тест 1: “Отрывание проводов”

Что делать: Во время работы робота
• Отключить один датчик
• Вытащить кабель мотора
• Закрыть чем-то датчик расстояния

Что должен делать робот:
• Сообщить об ошибке
• Перейти в безопасный режим
• Не уехать в стену

Тест 2: “Помехи”

Создать помехи:
• Включить мощный мотор рядом
• Использовать Wi-Fi роутер на полную
• Посветить ярким светом в датчик

Робот должен:
• Фильтровать помехи (скользящее среднее)
• Игнорировать явно ошибочные значения
• Если помехи сильные — остановиться

Тест 3: “Долгая работа”

Запустить робота и оставить на:
• 1 час
• 6 часов  
• 24 часа

Проверить:
• Не завис ли?
• Не перегрелся?
• Батарея правильно разряжается?

Частые ошибки в безопасности

Ошибка 1: “Нет аварийной остановки”

Плохо: Робот едет пока не упрется
Хорошо: Кнопка STOP, отключающая питание моторов

Ошибка 2: “Слепая вера в датчики”

Плохо: "Датчик сказал 0см → значит, ничего нет"
Хорошо: "Датчик 0см + камера видит стену → точно стена"

Ошибка 3: “Молчание при ошибках”

Плохо: Робот просто остановился, непонятно почему
Хорошо: Мигает определенным кодом, пищит, отправляет сообщение

Ошибка 4: “Нет границ возможного”

Плохо: Двигатель пытается повернуть на 500°
Хорошо: Максимум 180°, проверка в коде и концевики

Эксперимент: Сделай неубиваемый светодиод

Что нужно: Arduino, светодиод, резистор 220 Ом, кнопка

Задача: Светодиод должен мигать всегда, даже если:

  • Мы дергаем провода
  • Нажимаем кнопку (помеха)
  • Долго держим кнопку

Код с защитой:

#include <avr/wdt.h>

void setup() {
  wdt_enable(WDTO_1S); // Watchdog на 1 секунду
  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(2, INPUT_PULLUP); // Кнопка
}

void loop() {
  wdt_reset(); // Сбрасываем watchdog
  
  // Основная задача: мигать светодиодом
  digitalWrite(LED_BUILTIN, HIGH);
  delay(100);
  digitalWrite(LED_BUILTIN, LOW);
  delay(900);
  
  // Но мы также "слушаем" кнопку
  // Если кнопка залипла, программа не зависнет
  if (digitalRead(2) == LOW) {
    // Что-то делаем, но быстро
    delay(10); // Небольшая задержка
  }
  
  // Если здесь программа зависнет,
  // через 1 секунду Arduino перезагрузится
  // и светодиод снова начнет мигать!
}

Проверь своего робота

Вопросы для проверки:

  1. Что сделает робот, если отвалится провод от датчика линии?
  2. Как он поведет себя при разрядке батареи до 0%?
  3. Можно ли его случайно заставить ехать в стену?
  4. Поймет ли учитель/судья, что случилось, если робот остановился?
  5. Перезагрузится ли он сам, если программа зависнет?

Если на все вопросы есть хорошие ответы — ваш робот надежный!


Что дальше?

Сделали робота надежным? Теперь можно:

Совет: При проектировании робота сразу закладывайте системы безопасности. Добавить их потом будет в 10 раз сложнее. И помните: надежный робот — это не тот, у которого нет проблем, а тот, который правильно на них реагирует.