Стрелка-индикатор на серво, показывавшая загрузку домашнего сервера, дрожала мелко-мелко: на фотографии с выдержкой в полсекунды кончик размазывался в пятно. Скетч писал угол один раз при изменении значения и больше ничего не делал, но рог на месте не стоял никогда. В тишине мастерской слышно, как редуктор поскуливает: контур внутри серво живёт постоянно, даже когда со стороны кажется, что всё стоит.
Дрожь на месте — не одна поломка, а три слоя, и искать их лучше по очереди: электрика (питание и общий минус), сигнал (шум на АЦП и лишние перезаписи) и сам режим библиотеки. В уроке про помехи и питание список симптомов уже проговаривался; здесь спускаемся в каждое звено глубже — почему просадка выглядит как дрожь, при чём тут земля, и что реально гасит подрагивание, с фильтром, который собирается в симуляторе.
Разбирать слои удобно в порядке дешевизны: питание и земля проверяются взглядом и батарейным боксом, шум сигнала — кнопкой фильтра, и лишь потом, если ничего не помогло, стоит подозревать механику или саму серво. Порядок экономит вечер: конденсатор за пару сотен рублей лечит то, что часами правят в коде. Соберём и фильтр — усреднение восьми чтений с редким темпом обновления, который в симуляторе щёлкается кнопкой и слышен по редуктору.
Три слоя дрожи
Первый слой — питание, и это самая частая причина. У SG90 пусковой ток под 650 миллиампер при пяти вольтах, а USB-порт Uno отдаёт полампера на всё, включая саму плату. Каждое микродвижение серво — скачок тока, на котором проседает шина 5 В; потенциометр на валу читает сместившееся питание, контур видит ложное расхождение и делает ещё один шаг — дрожь подпитывает сама себя. На форумах эту спираль описывают коротко: серво трясётся сама по себе — чаще всего виновато питание.
Чинится слоями. Конденсатор 470-1000 микрофарад поперёк питания серво, вплотную к разъёму, съедает пик пуска — дешёвая первая помощь, о которой мы писали ещё в уроке про подключение SG90. Тяжёлые случаи — отдельный источник на 5-6 вольт с общей землёй, как в уроке про внешнее питание. И следите за соседями по макетке: просадка в момент хода серво роняет радиомодули — nrf24 отваливается от сети первым, хотя сертить его не приходилось.
Ёмкость выбирают сверху: 470 микрофарад — минимум для одной SG90, 1000 — если рядом вторая серво или тяговый мотор. Керамика вместо электролита не спасёт: она держит микросекунды, а просадка при пуске живёт миллисекунды. Полярность соблюдайте — электролит, включённый навыворот, надувается быстро и громко.
Второй слой — земля, и его пропускают чаще всего. Через минусный провод течёт и ток серво, и возвратный ток сигнала: на тонкой перемычке с сопротивлением в десятые доли ома полампера оставляют десятки милливольт падения — для контура, меряющего расхождение по потенциометру в милливольтах, это уже ложный сигнал. На длинных линиях радиомоделисты давно прокладывают минус питания серво отдельным проводом и сводят его с сигнальной землёй в одной точке: звезда, а не гирлянда, — так дребезг уходит без единой строчки кода. Правило простое: чем больше ток серво, тем толще нужен её собственный минус.
Проверка без осциллографа: подайте питание серво от отдельного батарейного бокса — если дрожь ушла, виновата шина, а не скетч. Заодно посмотрите на сам минус: перемычка метр длиной — это порядка 0,2 Ома, и пусковые полампера рисуют на ней падение около сотни милливольт. Не ушла дрожь после разделения питания — переходите к третьему слою, сигналу.
Плюс земля у нас общая для всей макетки: ход одного серво виден на сигналах остальных, если все минусы собраны гирляндой через тонкие перемычки. Сводить обратные токи в одной точке стоит ещё до первого дрожащего рога: переделка на живом макете занимает вечер, а на смонтированном роботе — неделю.
Фильтр, который гасит дрожь
Третий слой — сам сигнал. АЦП Uno дрожит на единицу-две от отсчёта к отсчёту, провод ручки ловит наводки от сетевых шнуров, и если в loop() писать в серво каждый проход, угол будет прыгать на градус — контур честно отработает каждый прыжок. Период в двадцать миллисекунд библиотека держит всегда, мы раскладывали это в уроке про импульсы: даже один записанный угол живёт под непрерывными импульсами, и контур всё время чуть-чуть правит рог. Отсюда же помогает detach на простое — без импульсов править нечего. А наводки от сетевого шнура, лежащего рядом с макеткой, АЦП честно превращает в угол: держите провода в порядке.
Лекарство — усреднение и темп. Восемь чтений подряд с делением на восемь гасят шум примерно втрое — корень из восьми; обновлять серво достаточно раз в пятьдесят миллисекунд: глаз разницы не замечает, а контур перестаёт гоняться за цифрами. Остаточную мелочь добирает мёртвая зона, но это отдельная техника — ей посвящён следующий урок. По числам: сырая дрожь в пару градусов после усреднения восьми чтений садится до десятых долей — корень из восьми равен 2,83, и он работает на любой плате.
В симуляторе шума нет — движок отдаёт ровное значение АЦП, и честнее сказать прямо: я добавил его в модель сам, случайной добавкой к чтению, как это делает настоящая электроника. Механика фильтра от этого не меняется: усредняете — серво затихает.
#include <Servo.h> // Индикатор на ручке: рог следует за A0, но не дрожит.// D2 переключает фильтр: усреднение 8 чтений + темп 50 мс. Servo horn; const int BTN = 2; int filter = 0; // 0 - сырой сигнал, 1 - усреднениеint lastBtn = HIGH;int lastSent = -1;unsigned long t = 0; int noisyRead() { return analogRead(A0) + random(-12, 13); // шум: в симуляторе его нет} void setup() { horn.attach(11); pinMode(BTN, INPUT_PULLUP); randomSeed(42); Serial.begin(9600); Serial.println("D2: filtr VKL/VYKL");} void loop() { int nowBtn = digitalRead(BTN); if (lastBtn == HIGH && nowBtn == LOW) { filter = 1 - filter; if (filter == 1) { Serial.println("filtr: VKL"); } else { Serial.println("filtr: VYKL"); } } lastBtn = nowBtn; if (millis() - t >= 50) { // темп: не чаще 20 раз в секунду t = millis(); int deg; if (filter == 1) { long sum = 0; for (int i = 0; i < 8; i++) { sum += noisyRead(); } deg = map(sum / 8, 0, 1023, 0, 180); } else { deg = map(noisyRead(), 0, 1023, 0, 180); } deg = constrain(deg, 0, 180); horn.write(deg); if (deg != lastSent) { // печать только при смене угла lastSent = deg; Serial.print("sent="); Serial.println(deg); } }}В скетче две скорости. Кнопка D2 переключает фильтр: без него в Serial сыплется калейдоскоп sent= — рог мелко трясётся вслед за шумом. С фильтром серво берёт среднее из восьми чтений и обновляется раз в пятьдесят миллисекунд: значения в логе затихают, рог замирает на месте. Печать идёт только при смене угла — иначе лог тонул бы в повторах.
Разницу стоит посмотреть графиком: сырой угол и отфильтрованный в Serial Plotter рисуют две кривые, и вторая заметно спокойнее. На реальной плате тот же скетч работает без правок — там шум даст сама электроника вместо моего random. Единственное, что стоит помнить: усреднение подряд ничего не задерживает, запаздывание приносит редкий опрос, — и пятьдесят миллисекунд для стрелки-индикатора не чувствуются.
На реальной плате к этому скетчу я добавляю два телодвижения. Первое — послушать: дрожь слышна как мелкое шуршание редуктора, и после включения фильтра оно уходит. Второе — посмотреть на Serial Plotter ещё раз через час работы: если кривая поползла, дело не в коде, а в разболтавшемся контакте ручки. Код при этом не переписывается — от макетки к макетке правится только ёмкость и, в плохих случаях, источник.
| Слой | Как выглядит | Что чинит |
|---|---|---|
| Питание | Дрожь с просадкой 5 В, плата иногда перезагружается | Конденсатор 470-1000 мкФ у разъёма, отдельный источник на 5-6 В |
| Земля | Дрожь растёт с длиной проводов и соседними нагрузками | Толстый минус, звезда: минус серво и сигнальная земля в одной точке |
| Сигнал | Угол скачет на градус при неподвижной ручке | Усреднение восьми чтений, обновление раз в 50 мс |
| Лишние записи | Рог микродёргается даже с ровным АЦП | Пишем в серво только при смене угла, таймер на millis() |
- Контур серво живёт всегда: импульс каждые 20 мс — рог правится даже при одном записанном угле
- Питание — первый подозреваемый: пусковой ток SG90 до 650 мА против 500 мА USB-порта
- Конденсатор 470-1000 мкФ поперёк питания серво у разъёма — первая помощь, отдельный источник — вторая
- Минус серво и сигнальная земля сводите в одной точке: на тонком проводе полампера оставляют десятки милливольт
- Усреднение восьми чтений гасит шум примерно втрое, темп 50 мс снимает лишнюю суету контура
- 1. Серво подрагивает на месте. С чего я советую начинать проверку?
- 2. Почему рог дрожит, даже если скетч записал угол один раз?
- 3. Конденсатор против просадок — какой и куда?
- 4. Провод к серво длиной метр. Как разводить землю?
- 5. Во сколько раз гасит шум усреднение восьми чтений?
Частые вопросы по теме урока
- Серво подрагивает на месте. С чего я советую начинать проверку?
- Дрожь без причины почти всегда электрика: пусковой ток серво просаживает шину, контур видит ложное расхождение и дёргает рог. Начинаем с электрики, фильтр ставим потом. Питание: пусковой ток просаживает 5 В
- Почему рог дрожит, даже если скетч записал угол один раз?
- Servo шлёт импульсы весь срок жизни объекта. Пока они идут, контур сравнивает и правит рог — в том числе реагируя на шум питания и сигнала: двадцатая поправка в секунду выглядит как дрожь. Библиотека шлёт импульс каждые 20 мс, контур корректирует постоянно
- Конденсатор против просадок — какой и куда?
- Ёмкость ставят у разъёма серво: она локально держит пик пуска, не давая просесть шине. Заодно проверьте напряжение под нагрузкой: просадка ниже 4,5 вольта уже ощутима контуром. 470-1000 мкФ поперёк питания серво, вплотную к разъёму
- Провод к серво длиной метр. Как разводить землю?
- Звезда: ток серво течёт своим минусом, сигнал — своим, и встречаются они в одной точке. Гирлянда минусов — классический источник наводок на сигнальной земле. Минус серво — отдельным проводом, сводить с сигнальной землёй в одной точке
- Во сколько раз гасит шум усреднение восьми чтений?
- Случайный шум при усреднении N отсчётов падает в корень из N раз: восемь чтений дают примерно 2,8-кратное улучшение. Ровно в восемь — только при коррелированном шуме, а это не наш случай. Примерно втрое — корень из восьми