Панорамная штанга была моим любимым проектом до вторника: камера на серво поворачивалась на 180 градусов, снимала таймлапс и возвращалась. Проблема всплыла, когда я захотел снять полную окружность: SG90 доезжала до края, билась об упор и трещала — дальше её не пускал собственный механизм. Я взял вторую серво, вскрыл корпус и спилил упор, гордый своей решительностью. Новый сюрприз пришёл через минуту: на команде, которая раньше значила «стой», серво молотила по кругу, как будто я приказал ей бежать марафон. Час я переписывал скетч, подозревая библиотеку, прежде чем понял: я сломал не механику, а обратную связь, и даже «стоп» теперь надо находить заново — по своему, отдельному для каждой серво, углу. Хорошая новость: операция занимает полчаса, стоит копейки и не требует ничего, кроме паяльника, надфиля и пары резисторов.
В этом уроке разберём, что именно делает серво обычной: датчик-потенциометр и упор на главной шестерне. Пройдём модификацию по шагам — спил упора и делитель из двух резисторов вместо потенциометра — и соберём Serial-стенд, который на живой плате находит стоп-угол и меряет обороты. В симуляторе ниже стенд уже работает: циферблат показывает приказы, Serial печатает пары «угол — обороты», и на этих рядах видно всю шкалу скоростей, которую вы получите на настоящей плате.
Что мы ломаем: датчик и упор
Я уже разбирал серво по винтикам в уроке про анатомию сервопривода, там схема такая: моторчик, редуктор из пластиковых шестерён и потенциометр, механически связанный с выходным валом. Плата внутри непрерывно сравнивает два числа — какой угол заказан импульсом и где вал стоит по показаниям потенциометра — и гонит мотор в сторону рассогласования. Как только разница стала нулём, мотор останавливается: серво держит угол.
Непрерывное вращение получается обманом этой пары. Если потенциометр навсегда показывает середину — примерно 90 градусов, — плата верит, что вал всегда в центре. Приказ write(90) означает «разница ноль» — мотор молчит. Приказ write(0) — «разница огромная, крути туда» — мотор крутится до посинения, а потенциометр всё так же докладывает про центр. Скорость при этом пропорциональна величине обмана: чем дальше приказ от стоп-точки, тем быстрее вращение. Вторая часть операции — механическая: на главной шестерне SG90 отлиты ступеньки-упоры, о которые вал бьётся на краях хода. Их спиливают заподлицо, чтобы шестерня могла крутиться без конца. У некоторых партий второй упор отлит в крышке корпуса — если вал после спила всё равно спотыкается на одном месте, ищите выступ в пластике.
Из этой схемы следствия два. Первое: непрерывная серво никогда не узнает, где её вал, — удержание позиции исчезает вместе с датчиком, и никакой код его не вернёт. Второе: приказ write() перестаёт быть координатой и становится газом: те же импульсы теперь командуют оборотами, а не положением, поэтому весь словарь «углы, градусы, упоры» в скетчах меняется на «проценты, обороты, стоп». На циферблате это выглядит странно: серво отвечает на каждый приказ вращением — глазом вы видите только факт движения, а цифры снимаете через Serial.
| Приказ write() | Обычная SG90 | Непрерывная серво |
|---|---|---|
| 0 | держит 0°, бьётся об упор | полный ход в одну сторону |
| 60 | держит 60° | примерно треть скорости в ту же сторону |
| 87–93 | держит угол | мёртвая зона: вал стоит (свой стоп у каждой серво) |
| 120 | держит 120° | примерно треть скорости в другую сторону |
| 180 | держит 180°, бьётся об упор | полный ход в другую сторону |
Операция: спил и делитель вместо потенциометра
Порядок работ такой. Четыре винта снизу, снять заднюю крышку, вытащить плату, выложить шестерни. На главной шестерне — большой, с валом — срезаем упорные ступеньки ножом и дорабатываем надфилем заподлицо. Дальше электрика: выпаять потенциометр и поставить на его место делитель из двух резисторов по 2,2 кОм — средняя точка делителя идёт на средний контакт разъёма. Плата увидит постоянную «половину хода» и поверит, что вал всегда в центре. Мой первый заход был хуже: я попытался провернуть потенциометр в среднее положение и закрепить его на шестерне каплей лака. Ничего не вышло — при вращении вала потенциометр крутится вместе с ним, показания плывут, и серво сходила с ума: ползла, дёргалась, ревела на остановках. Правильно именно вырвать датчик из обратной связи, а не успокоить его.
Числа для ожиданий. Полный ход моей модифицированной SG90 при 5 В без нагрузки — оборот за 0,6–0,7 с, это порядка 90–100 об/мин; с приклеенным колесом и грузом платформа теряет треть скорости. Кому паять не хочется: готовая непрерывная серво FS90R стоит немногим дороже двух SG90 и едет предсказуемее — заводская модификация всегда аккуратнее гаражной. Я всё же иногда паяю сам, но только когда серво нужна срочно, а магазин далеко.
Про инструменты: нож, надфиль и паяльник на 25–30 Вт — вот весь набор. Резисторы берите одного номинала и одной партии: разброс внутри пары меньше, чем между партиями, и стоп-точка окажется ближе к середине шкалы. Ножки потенциометра откусывайте по одной и запоминайте цвета — крайние ноги идут на края делителя, средняя на среднюю точку; перепутаете — серво будет ехать только в одну сторону и на всю скорость.
#include <Servo.h> Servo srv; void setup() { srv.attach(11); // сигнальный провод на пине 11 Serial.begin(9600);} void loop() { for (int ugol = 80; ugol <= 100; ugol++) { srv.write(ugol); // перебираем углы вокруг середины Serial.print("ugol="); Serial.println(ugol); delay(300); // 0,3 с на каждый угол — вал успевает показать характер }}Калибровка: стоп-угол и обороты
Делитель из резисторов не даёт ровно половину: два резистора имеют разброс, и стоп-точка конкретной серво оказывается не на 90, а на 86 или 93. Скетч выше перебирает углы от 80 до 100 с шагом в один градус: на живой плате смотрите на вал — на стоп-угле он замрёт, а по обе стороны медленно поползёт в разные стороны. У моего экземпляра стоп был на 88, у соседнего из той же партии — на 92. Найденный угол записывайте константой в каждый скетч: вся «арифметика скорости» дальше строится от него.
Обороты меряю секундомером: отмечаю на колесе метку, даю полный ход и засекаю десять оборотов — на десяти погрешность отсчёта в полсекунды превращается в 5%, на одном обороте она была бы неприличной. Ряды с приказами удобно смотреть на Serial Plotter: пара «угол — обороты» рисует лестницу скоростей, по которой сразу видно и мёртвую зону, и асимметрию — у моей серво полный ход по часовой был 0,62 с на оборот, против часовой — 0,68: резисторы делителя чуть разные. Для платформы это неважно, для одометрии — уже поправка в коде.
Стенд заодно проверяет и механику. Равномерный шелест на краях шкалы — спил сделан чисто; стук на каждом обороте — шестерня задевает остаток упора или в редукторе осталась откушенная ножка. Оба варианта я ловил: недоспиленный ус допиливался за минуту, а болтающаяся деталь в редукторе заставила разбирать серво второй раз — не закрывайте крышку до тихого хода.
Жизнь после модификации меняется сильнее, чем кажется до скальпеля. Непрерывная серво не держит позицию в принципе: ей нечем знать, где её вал, — датчика больше нет. Тормоз здесь — команда стоп-угла: плата продолжает сопротивляться вращению и гасит вал, пока рука не сильнее мотора. Для парковки платформы на уклоне этого мало, нужна механика — храповик, червячная пара или обычная серво с упором. Взамен вы получаете привод с честной скоростной шкалой и готовой электроникой: колесо робота, конвейерную ленту, вращающийся стенд для фотосъёмки. Как выжать из этой шкалы разгон, торможение и стоп без сюрпризов — предмет следующего урока про управление скоростью; библиотечные основы attach() и write() при этом не меняются, они разобраны в уроке про Servo.h, а провода и питание — в уроке про подключение SG90.
Отдельная благодарность серво за простоту диагностики. Привод молчит на всех приказах — проверяйте провода и стоп-угол. Крутится только в одну сторону — делитель собран с ошибкой. Греется на «стопе» — стоп-угол найден неточно, и мотор молотит впустую внутри мёртвой зоны. Три симптома, три адреса, и ни один не требует осциллографа: мой второй экземпляр после такой таблицы ожил за пять минут.
- 1. Что внутри SG90 служит датчиком угла, который отключают при модификации?
- 2. После спила упора write(90) не останавливает вал. Самая вероятная причина?
- 3. Что ставят вместо выпаянного потенциометра?
- 4. Сколько времени занимает полный оборот модифицированной SG90 при 5 В без нагрузки?
- 5. Как остановить непрерывную серво скетчем?
- Непрерывная серво — это SG90 без датчика (делитель 2 по 2,2 кОм) и без упора на главной шестерне; упор бывает и в крышке корпуса.
- write() задаёт скорость: чем дальше приказ от стоп-угла, тем быстрее вращение, до полного хода на краях шкалы.
- Стоп-угол у каждого экземпляра свой — у моего был 88: находите его стендом-перебором и пишите константой.
- Полный ход при 5 В без нагрузки — оборот за 0,6–0,7 с; с грузом минус треть.
- Модификация необратима; без пайки берите готовую FS90R, а для парковки всё равно нужна механика.
Частые вопросы по теме урока
- Что внутри SG90 служит датчиком угла, который отключают при модификации?
- Плата сверяет заказанный угол с положением вала через потенциометр. Замена его делителем из двух резисторов оставляет плате вечную «середину» — так серво перестаёт знать про угол. потенциометр, связанный с выходным валом
- После спила упора write(90) не останавливает вал. Самая вероятная причина?
- Делитель задаёт условную середину с разбросом, поэтому стоп лежит где-то в 86–95. Его находят стендом-перебором и записывают константой в скетч. стоп-точка конкретной серво не ровно 90 — она уезжает из-за разброса резисторов делителя
- Что ставят вместо выпаянного потенциометра?
- Делитель из одинаковых резисторов даёт плате постоянное напряжение середины шкалы. Потенциометр на шестерне не годится — он крутится вместе с валом и плывёт. делитель из двух резисторов по 2,2 кОм
- Сколько времени занимает полный оборот модифицированной SG90 при 5 В без нагрузки?
- Полный ход — порядка 90–100 об/мин без нагрузки. Под колёсами с грузом скорость падает примерно на треть: меряйте на своей сборке секундомером по десяти оборотам. около 0,6–0,7 секунды на оборот
- Как остановить непрерывную серво скетчем?
- Стоп — это команда в мёртвую зону: плата продолжает тормозить вал. detach() отпускает вал совсем, а кратковременный write(0) просто даст оборот в сторону. отдать write(стоп-угол), найденный при калибровке