Макетка собрана, оба узла проверены по отдельности: шлагбаум на SG90 поднимается по команде из монитора, стрелка-указатель показывает режим. Сошлись в один корпус — и при первом же одновременном движении светодиод на плате мигнул, в мониторе заново напечаталась строка из setup, а оба серво дёрнулись в середину хода. Никакой команды на перезагрузку в коде нет — плата перезапустилась сама, и повторяется это каждый раз, когда два мотора трогаются вместе.
Причина живёт не в скетче и не в проводах сигнала, а в арифметике тока. USB-порт по стандарту отдаёт 500 мА, из которых Uno с обвязкой забирает себе 40-50 — на пине 5V остаётся около 400-450. SG90 в покое тянет 6-10 мА, на ходу без нагрузки 100-250 мА, а в момент старта показывает бросок, который по замерам доходит до 650-700 мА. Два мотора стартуют одновременно — суммарный запрос на первые мгновения доходит до 1,3-1,4 А, втрое выше того, что шина способна дать.
Дальше — что именно происходит с шиной 5 В в этот момент и почему контроллер воспринимает её как потерю питания; затем приём без паяльника, который снимает половину проблемы, и рабочая схема с отдельным блоком, где земля у платы и моторов обязана быть общей.
Что происходит с шиной 5 В в момент старта
При старте двух моторов линия 5 В проваливается: на тонком USB-кабеле и входных цепях платы просадка доходит до одного-двух вольт. Пока напряжение выше порога, контроллер живёт обычной жизнью, но супервизор ATmega328P следит за питанием непрерывно — при провале ниже критического он держит чип в сбросе, а потом отпускает, и скетч начинается с нуля. Условие ловится легко: если в момент движения серво шина 5 В просаживается глубже порога, плата уходит в перезагрузку без единой строки кода, которая это инициировала.
Диагноз ставится за минуту по монитору — методику вообще по Serial разбирал урок про отладку логики. Печатайте строку из setup один раз при старте: при сбросе она придёт в монитор заново, это и есть след. Второй след — оба серво рывком возвращаются к середине: attach() стартует с 90°, и заново запущенный скетч снова приказывает стартовый угол. Третий — светодиод L мигает в момент, когда моторы трогаются: загрузчик мигает им при каждой загрузке.
Сама по себе перезагрузка плату не жжёт — она вредит косвенно. Переменные обнуляются, позиции забываются, в проекте с расписанием пропускается действие; а если на момент сброса рычаг был поднят с грузом, при рестарте он падает с рывком. Поэтому чинить надо причину — ток, а не следствие.
Отдельно про то, почему сброс не всегда ловится сразу: просадка короче 20-30 мс может не успеть дойти до монитора — строка из setup печатается, но вы в этот момент смотрите на моторы, а не в окно. Дешёвый детектор — светодиод L: он мигает на каждом старте загрузчика, и мигание в момент движения серво значит ровно одно. Два-три прогона — и диагноз есть, осциллограф не нужен.
Смягчение без паяльника: старты по очереди
Первый приём делается в скетче и работает на текущей макетке: не позволяйте двум моторам стартовать в один момент. Команда выдаётся одному, следующий мотор получает свою только после паузы. SG90 по паспорту проходит 60° за 0,1 с, значит, разрыв в 600 мс перекрывает и бросок старта, и ход типовой команды с запасом. Ниже — скетч с этапами: в каждом этапе максимум один write(). Пауза между этапами — не костыль, а честный способ разнести броски; в живых проектах её держат таймером на millis(), а не delay().
Честная граница приёма: он устраняет наложение бросков, но не отменяет арифметику. Один мотор на пике и второй под нагрузкой вместе всё равно упираются в потолок USB — приём годится для отладки и лёгких механизмов, а постоянная работа строится на нормальном питании из следующего раздела.
#include <Servo.h> Servo servoA; // воротаServo servoB; // стрелка-указатель int etap = 0; // сценарий: едет максимум один моторlong tEtap = 0; void setup() { servoA.attach(9); servoB.attach(10); servoA.write(20); servoB.write(160); Serial.begin(9600); Serial.println("Старт: оба серво в исходных, команды идут по очереди"); tEtap = millis();} void loop() { if (millis() - tEtap < 2000) return; // темп: один этап за две секунды if (etap == 0) { servoA.write(100); // ворота открываются, B стоит Serial.println("Этап 1: едет только A"); etap = 1; } else if (etap == 1) { servoB.write(70); // A уже доехала, стартует B Serial.println("Этап 2: едет только B"); etap = 2; } else if (etap == 2) { servoA.write(20); Serial.println("Этап 3: A возвращается, B ждёт"); etap = 3; } else { servoB.write(160); Serial.println("Этап 4: B возвращается"); etap = 0; } tEtap = millis();}Скетч держит очередь этапом: etap хранит, чей сейчас ход, а return в начале loop задаёт темп — один этап за две секунды. Важная деталь: к моменту старта B мотор A уже доехал и сбросил ток до покоя, поэтому броски никогда не складываются. Это скелет приёма: в живом проекте этапы запускаются датчиками или командами из монитора, но принцип один — старты не пересекаются.
Питание при этом всё ещё с шины платы — я сознательно оставляю такой режим для отладки. Как только проект уезжает с рабочего стола, шину серво переводят на собственный источник. Пределы по числу моторов на одной Uno уже считались в уроке про несколько серво, а здесь разберём саму схему переезда.
Про выбор блока: ищите стабилизированные 5 В с запасом в полтора-два раза от суммарного пика: паре SG90 хватит и 1,5 А, пятёрке — 2 А и больше. Подойдут адаптеры от роутеров и внешних дисков на 5-6 В; нестабилизированные трансформаторные не берите — под нагрузкой они выдают и 8-10 В, для серво это на грани. Про цвета проводов и саму вилку подключения — урок про провода и питание SG90.
Отдельный блок питания и общая земля
Рабочая схема выглядит так: моторам — собственный блок 5 В на 2 А, он тянет пять-шесть SG90 с запасом; именно такой советуют на форумах те, кто вешает на Nano пять моторов сразу. Красный провод каждого серво идёт на плюс блока, коричневый — на минус блока, оранжевый — на сигнальный пин платы. Пин 5V в этой цепи не участвует вовсе: контроллер питается как питался, моторы — от своего источника.
Общая земля — не пожелание, а условие работы. Серво читает импульс относительно своего минуса: сигнал высокий — это насколько выше минуса? Если минус блока не соединён с GND платы, опорной точки нет, импульс для серво — колебание неизвестно относительно чего, и моторы дёргаются или стоят как вкопанные. Правило, которое стоит запомнить дословно: сигнал общий, питание раздельное, земля одна на всех.
Про провода — то, что вылезает на практике: макетные перемычки при амперах роняют вольт на метре длины. Силовые плюсы и минусы ведите скруткой от 0,5 мм² или хотя бы парой перемычек параллельно, а на выход блока поставьте электролит 470-1000 мкФ — он добивает остатки бросков. Ток удержания под нагрузкой и нагрев корпуса — отдельная история: ей посвящён урок про ток удержания, а тяжёлые MG995 требуют блока пожирнее — их аппетиты считаются в уроке про MG995 и MG996R.
| Источник для двух SG90 | Что реально отдаёт | Два мотора при старте | Годится для |
|---|---|---|---|
| 5V платы при питании от USB | 400-450 мА после аппетитов платы | Просадка и сброс: бросок двух SG90 — до 1,3 А | Один серво на лёгком ходу, отладка |
| 5V платы при питании от Vin 7-12 В | Стабилизатор отдаёт больше, но греется | На грани: зависит от входного напряжения и охлаждения | Один-два серво с разведёнными стартами |
| Внешний блок 5 В 2 А | 2 А на шине моторов, плата питается отдельно | Броски уходят в запас, просадок нет | Рабочая схема: пять-шесть SG90 |
| Крона 9 В на Vin | Батарея отдаёт десятки-сотню мА | Сброс гарантирован | Только плата без моторов |
- 1. Почему лимит USB в 500 мА не означает, что на пине 5V есть все 500?
- 2. Что видит Serial при сбросе платы от просадки?
- 3. Серво A стартует (бросок 650 мА), серво B едет без нагрузки (250 мА). Суммарный запрос?
- 4. Почему минус внешнего блока обязан соединяться с GND платы?
- 5. Что даёт конденсатор 470-1000 мкФ на рельсе 5 В?
- USB-порт даёт 500 мА, на пине 5V после аппетитов платы остаётся 400-450 — а бросок одного SG90 доходит до 650-700 мА
- Сброс при движении серво виден по строке из setup в мониторе и миганию светодиода L
- Разведённые старты снимают наложение бросков, но не отменяют арифметику — это приём для отладки
- Рабочая схема: блок 5 В 2 А на моторы, плата питается отдельно, минусы соединены — земля одна на всех
- Конденсатор 470-1000 мкФ сглаживает остатки броска, но источник обязан уметь отдать суммарный ток
Частые вопросы по теме урока
- Почему лимит USB в 500 мА не означает, что на пине 5V есть все 500?
- Из 500 мА порта Uno расходует на себя 40-50, и часть напряжения теряется на кабеле — на пине 5V остаётся около 400-450 мА. Плата с обвязкой забирает себе 40-50 мА, плюс напряжение роняется на тонком кабеле — реально 400-450
- Что видит Serial при сбросе платы от просадки?
- Повторная строка из setup — самый дешёвый след сброса: скетч начался заново, значит, питание провалилось. Строки из setup печатаются заново — скетч начался с нуля
- Серво A стартует (бросок 650 мА), серво B едет без нагрузки (250 мА). Суммарный запрос?
- 650 плюс 250 — это 900 мА, почти вдвое выше того, что USB отдаёт на пин 5V. Отсюда и просадка даже без одновременных стартов. 900 мА — за лимитом USB
- Почему минус внешнего блока обязан соединяться с GND платы?
- Серво отсчитывает ширину импульса относительно своего минуса. Без общего провода опорной точки нет — моторы дёргаются или стоят. Иначе импульсам сигнала не с чем сравниваться: у серво и платы нет общей опорной земли
- Что даёт конденсатор 470-1000 мкФ на рельсе 5 В?
- Банка гасит остатки броска, но 1,3 А она не создаст из ничего: источник должен уметь отдать суммарный ток моторов. Сглаживает короткие просадки, но суммарный ток всё равно обязан уметь отдать источник