Руководство · Начальный · 30 мин
Почему ваш робот перезагружается при запуске двигателей
Перезагрузка похожа на ошибку ПО, но вызвана питанием: сопротивление аккумулятора, бюджет тока и опасный диапазон, который пропускает детектор просадки.
Введение
На стенде робот работает. Вы ставите его на пол, двигатели раскручиваются, и всё останавливается — последовательный монитор перезапускается, светодиодная индикация (LED) начинается заново, а все действия робота забываются.
Почти у всех первый инстинкт — искать причину в коде. Но в коде её нет.
При запуске двигателей аккумулятор не смог обеспечить требуемый ток без снижения напряжения, питание опустилось ниже необходимого микроконтроллеру, и плата перезагрузилась. Это просадка питания, и она является самой распространённой неисправностью первого робота. Сайт говорит об этом на пути управления двигателем, почти на каждой странице компонента и в списках диагностики половины проектов. Настоящая страница объясняет этот случай.
Сначала убедитесь, что это перезагрузка, а не сбой
Для них нужны разные исправления, хотя издалека они выглядят одинаково.
Поместите отличительную строку в самое начало setup():
void setup() {
Serial.begin(115200);
Serial.println(F("---- BOOT ----"));
}
Теперь запустите робота до неправильного поведения и следите за монитором:
---- BOOT ----появляется снова → плата перезагрузилась. Причина в питании. Продолжайте читать.- Вывод прекращается или бесконечно повторяет одну строку → плата зациклилась или завершилась аварийно. Это проблема кода, и эта страница вам не подходит.
- Вывод превращается в нечитаемые символы → питание проседает, но недостаточно для перезагрузки. Это также проблема питания, и исправления те же.
На платах AVR можно пойти дальше и узнать у микросхемы, почему она перезагрузилась. Регистр MCUSR хранит причину, но main() запускается намного позже, поэтому сохраните значение в функции .init3, которая выполняется первой:
uint8_t resetFlags __attribute__((section(".noinit")));
void captureReset(void) __attribute__((naked, used, section(".init3")));
void captureReset(void) {
resetFlags = MCUSR;
MCUSR = 0;
}
void setup() {
Serial.begin(115200);
if (resetFlags & _BV(BORF)) Serial.println(F("cause: BROWN-OUT"));
if (resetFlags & _BV(EXTRF)) Serial.println(F("cause: reset pin"));
if (resetFlags & _BV(PORF)) Serial.println(F("cause: power-on"));
if (resetFlags & _BV(WDRF)) Serial.println(F("cause: watchdog"));
}
Одна честная оговорка: загрузчик Optiboot на Uno считывает MCUSR и очищает его до того, как код увидит значение, сохраняя его в регистре r2. Если на вашей плате все флаги равны нулю, причина именно в этом; вернитесь к проверке ---- BOOT ----, которой ничего не требуется и которая не может лгать.
Почему падает напряжение
Аккумулятор — не просто источник напряжения. Это источник напряжения последовательно с сопротивлением, и именно сопротивление определяет, будет ли работать робот:
V_terminal = V_open_circuit − I × R_internal
R_internal зависит от химии и размера элемента и сильно различается у блоков, лежащих в одном ящике.
| Блок | Холостой ход | R_internal | При скачке 2 A |
|---|---|---|---|
| 2×18650 Li-ion | 7.4 V | ≈ 0.10 Ω | 7.20 V |
| 4×AA NiMH | 4.8 V | ≈ 0.12 Ω | 4.56 V |
| 4×AA щелочные | 6.0 V | ≈ 0.80 Ω | 4.40 V |
| 9 V PP3 блок | 9.0 V | ≈ 2.0 Ω | 5.00 V и продолжает падать |
Из таблицы следуют три вывода, важнее самих чисел:
Блок на девять вольт — худший аккумулятор, который можно поставить в робота. На нём напечатано самое высокое напряжение, но за двумя омами внутреннего сопротивления скрывается ёмкость около 500 mAh. Это аккумулятор для дымовой сигнализации.
Щелочные элементы не обеспечивают стабильное напряжение под нагрузкой. Их внутреннее сопротивление примерно в шесть раз выше, чем у элемента NiMH, и оно возрастает при разряде, поэтому робот работает двадцать минут, а затем начинает перезагружаться. Это выглядит как прерывистая неисправность, но на самом деле разряженный аккумулятор ведёт себя именно так, как и должен.
Аккумуляторы перезаряжаемого типа выигрывают в важном отношении. NiMH и Li-ion являются стандартными химическими составами для роботов не потому, что они перезаряжаемые, а потому, что поддерживают напряжение под нагрузкой.
Составьте бюджет тока до выбора блока
Сложите потребление робота дважды: отдельно обычный режим и отдельно наихудший момент.
| Компонент | Обычный режим | Наихудший случай |
|---|---|---|
| Плата Arduino Uno | 45 mA | 45 mA |
| Редукторный двигатель TT ×2 | 400 mA | 2000 mA (оба заклинили) |
| Массив инфракрасных датчиков отражения (IR) | 100 mA | 100 mA |
| HC-SR04 | 15 mA | 15 mA |
| Сервопривод SG90 | 150 mA | 700 mA (заклинивание) |
| Bluetooth HC-05 | 30 mA | 40 mA |
| ESP32 (Wi-Fi) | 80 mA | 250 mA (пакет передачи) |
Простой робот, следующий по линии, — Uno, два двигателя и массив ИК-датчиков — потребляет около 545 mA в обычном режиме и 2.15 A в наихудший момент. Наихудший момент обычно короткий; исключение — робот, толкающий на пределе сцепления, который остаётся при токе заклинивания в течение всего толкания. Выбирайте блок по первому значению, а просадку — по второму, поскольку они отвечают на разные вопросы:
runtime ≈ capacity / running current 2000 mAh / 545 mA ≈ 3.7 h ideal
sag = worst-case current × R_internal
Ожидайте фактическое время работы около двух третей этого значения. Вы не разрядите блок полностью, скачки тока стоят больше своего среднего значения, а паспортную ёмкость измеряют при небольших токах разряда.
Опасный диапазон, который пропускает детектор просадки питания
В каждом AVR есть детектор просадки питания, который удерживает микросхему в состоянии перезагрузки ниже заданного напряжения. На Arduino Uno этот предохранитель изначально установлен на 2.7 V.
ATmega328P на 16 MHz не рассчитана на работу при 2.7 V. В техническом описании класс скорости задаёт диапазон от 4 MHz при 1.8 V до 20 MHz при 4.5 V; интерполяция для 16 MHz даёт минимум около 3.8 V.
Это объясняет симптом, в который людям сложнее всего поверить: робот не перезагружается, а просто ведёт себя странно, когда работают двигатели. Повреждаются переменные, сервопривод скачет, датчик I²C возвращает бессмысленные значения, конечный автомат оказывается в состоянии, для которого не выполняется переход. В этой полосе микросхема выполняет команды вне гарантированных рабочих условий, и именно слово «гарантированных» здесь ключевое.
Поэтому не считайте «сброса не было» доказательством исправности питания.
Один блок, две шины питания
Решение — не два аккумулятора, а один блок, питающий два направления.
- Ток двигателей идёт от блока прямо на клемму питания двигателя драйвера:
+12Vу L298N илиVMу TB6612FNG. Он никогда не проходит через микроконтроллер. - Ток логики поступает от стабилизированного источника 5 V: встроенного стабилизатора драйвера, отдельного импульсного преобразователя либо USB во время разработки.
- Земли должны быть соединены. Каждый сигнал между платой и драйвером — напряжение относительно земли; без общей точки отсчёта выводы направления не имеют смысла. Это вторая по частоте ошибка подключения после отсутствия общего питания.
Никогда не питайте двигатели через вывод Arduino 5 V или стабилизатор на разъёме типа «бочонок». Стабилизатор Uno — небольшой линейный элемент, который преобразует разницу между входом и выходом в тепло: при входе 7.4 V, выходе 5 V и токе 500 mA это (7.4 − 5) × 0.5 = 1.2 W в корпусе без радиатора. Он нагреется, затем отключится по температуре, и робот перезагрузится по причине, не связанной с аккумулятором.
Что на самом деле устраняет конденсатор
Стандартный совет — поставить большой электролитический конденсатор параллельно питанию двигателя. Совет верный, обычно приводимое обоснование ошибочно, и простой расчёт это показывает:
ΔV = I × Δt / C
Конденсатор 1000 µF, нагруженный на пусковой скачок 2 A длительностью 10 ms, даст падение 2 × 0.010 / 0.001 = 20 V. Он не справится с этой задачей. Конденсатор не выдерживает пусковой ток двигателя — это может сделать только более жёсткий аккумулятор.
Он выдерживает быстрые изменения. При частоте переключения ШИМ (PWM) 8 kHz период равен 125 µs, поэтому тот же конденсатор увидит пульсацию 2 × 0.000125 / 0.001 = 0.25 V — задачу, с которой он справляется с большим запасом. Он также поглощает выбросы напряжения при коммутации, которые коллекторные двигатели возвращают в питание.
Поэтому установите один конденсатор — от 470 до 1000 µF параллельно питанию двигателя и ещё 0.1 µF керамический рядом с драйвером. Ожидайте, что он уменьшит шум и сбои датчиков, но не устранит перезагрузку. Если конденсатор устранил сброс, блок работал на пределе, и запас у вас минимален.
Измерьте, а не гадайте
Десять минут с мультиметром лучше целого дня теорий.
- Переведите измеритель в режим постоянного напряжения (DC) и подключите его к клеммам аккумулятора, а не к Arduino.
- Запишите напряжение без нагрузки.
- Запустите двигатели, желательно под реальной нагрузкой, когда робот стоит на полу.
- Следите за значением.
Падение более чем на несколько десятых вольта — ваш ответ. Чтобы определить R_internal, выполните деление: блок 6.0 V, падающий до 4.4 V при потреблении около 2 A, даёт (6.0 − 4.4) / 2 = 0.8 Ω.
Затем повторите измерение на шине 5 V во время запуска двигателей. Это значение фактически воспринимает микроконтроллер; если оно приближается к 3.8 V, неисправность найдена без осциллографа.
Дешёвые мультиметры слишком медленно усредняют показания, чтобы поймать самое нижнее значение кратковременного провала, поэтому считайте результат оптимистичным. Провал по крайней мере настолько велик.
Исправления от самых дешёвых
- Перестаньте питать двигатели через плату. Это бесплатно и сразу устраняет большую долю случаев.
- Замените блок. Щелочные элементы или 9 V → NiMH или 18650. Обычно это полностью решает проблему.
- Соедините земли. Это бесплатно, а без этого соединения возникают более странные неисправности, чем при просадке питания.
- Добавьте электролитический конденсатор. Для шума и сбоев датчиков, а не для перезагрузок.
- Плавно разгоняйте двигатели вместо ступенчатого включения. Профиль движения распределяет пусковой ток по времени, а не требует его весь сразу; это тот же код, который предотвращает пробуксовку колёс.
- Правильно выберите двигатели. Если от двигателя требуется больше момента, он потребляет больше тока; расчёт момента и оборотов редукторного двигателя стоит в начале всей этой цепочки проблем.
- Отделите стабилизатор. Малый импульсный преобразователь для логической шины полностью развязывает её с просадкой от двигателей.
После устранения просадки следующий шаг — измерение напряжения в программном обеспечении, а честное чтение напряжения сложнее, чем кажется, поскольку опорное напряжение ADC по умолчанию является напряжением этой шины.
Возможные неисправности
| Симптом | Обычная причина |
|---|---|
| Последовательный вывод перезапускается сверху при запуске двигателей | Просадка питания; сначала проверьте блок, затем код |
| Работает от USB, отказывает от аккумулятора | Блок не может обеспечить скачок тока, USB может |
| Работает двадцать минут, затем многократно перезагружается | Внутреннее сопротивление щелочных элементов возрастает при разряде |
| Странное поведение без явной перезагрузки | Питание в диапазоне 2.7–3.8 V; вне допустимых условий, но выше порога |
| Датчики возвращают бессмысленные значения только при движении | Шум питания; электролитический конденсатор и раздельные шины |
| Выводы направления, кажется, ничего не делают | Нет общей земли между платой и драйвером |
| Стабилизатор слишком горячий для касания | Логика питается через линейный стабилизатор при слишком высоком входном напряжении |
| Конденсатор устранил неисправность, но она вернулась | Блок работал на пределе; конденсатор купил миллисекунды, а не амперы |
Питание лежит под всеми остальными уровнями робота, поэтому неисправность здесь имитирует отказ в любом другом месте. Если нечто необъяснимое начинается в момент запуска двигателей, сначала измерьте аккумулятор: это занимает десять минут и чаще даёт правильный ответ, чем любая другая догадка.
Исследуйте граф
Входит в эти сборки
Проекты и учебные пути, в которые входит это руководство.
- ПроектСоберите графоплоттер с двумя точными осями на шаговых двигателях
- ПроектСоберите мини-робота сумо: сцепление, клин и датчики края
- ПроектСоберите робота для захвата и переноса с проверкой
- ПроектСоберите робота для покрытия помещения
- ПроектСоберите робота на колёсах Mecanum, который едет боком
- ПроектСоберите робота-ровера для путевых точек GPS
- Учебный путьОмнидирекционный привод: движение вбок без поворота
- Учебный путьОсновы электроники роботов: дорожная карта обучения
- Учебный путьТочное перемещение со шаговыми двигателями: план обучения
Дополнительные материалы