Сервопривод-шлагбаум на Arduino: SG90, кнопка и зуммер
Настольный шлагбаум — самый наглядный первый проект с сервоприводом: у механизма два состояния, стрелка либо лежит (0 градусов), либо поднята (90), и весь «интеллект» сводится к кнопке, бипу и двум задержкам. Собирается из того, что есть в каждом стартовом наборе: SG90, тактовая кнопка, пьезозуммер. Сервопривод тут идеален именно потому, что ему всё равно, какой вес давит на вал — он сам держит угол, пока его кормят импульсами каждые 20 миллисекунд.
В нашем симуляторе шлагбаум собирается без единого провода: карточка «Сервопривод SG90» ставится кликом из палитры «Макетка», кнопка и зуммер — такими же карточками на свои пины. Рантайм исполняет attach и write по-настоящему: угол видно на карточке, частоту «бипа» — на зуммере, Serial печатает события по мере проезда. Ниже — проверенный скетч, разбор таймингов и честные границы того, что остаётся за железом.
Механика шлагбаума: два угла и три тайминга
Любой шлагбаум — это автомат с состояниями «закрыто» и «открыто», и писать его конечный автомат не нужно: хватает порядка вызовов внутри loop. Кнопка «проезд» замыкает пин D2 на землю — она читается через INPUT_PULLUP, поэтому нажатая кнопка даёт LOW, а свободная держится на HIGH внутренней подтяжкой. По нажатию скетч пикает зуммером (тон 1200 Гц на 200 миллисекунд), поднимает стрелку за один шаг write(90), держит паузу 2,5 секунды, пока «машина проходит», и опускает обратно.
Тайминги — единственное, что стоит подобрать под свой сценарий. Задержка 300 миллисекунд между бипом и подъёмом даёт водителю секунду на реакцию, пауза 2500 — время проезда, финальная 1000 — чтобы стрелка не молотила вверх-вниз, если кнопку держать зажатой. Функция tone с третьим аргументом блокирует скетч на время звучания, как delay, поэтому темп сценария честный и в симуляторе, и на плате.
#include <Servo.h>Servo shlagbaum;const int PIN_SERVO = 9;const int PIN_KNOPKA = 2;const int PIN_ZUMMER = 8; void setup() { pinMode(PIN_KNOPKA, INPUT_PULLUP); pinMode(PIN_ZUMMER, OUTPUT); shlagbaum.attach(PIN_SERVO); shlagbaum.write(0); // стрелка опущена Serial.begin(9600); Serial.println("shlagbaum gotov");} void loop() { if (digitalRead(PIN_KNOPKA) == LOW) { // кнопка «проезд» нажата Serial.println("proezd!"); tone(PIN_ZUMMER, 1200, 200); // «бип» на въезде delay(300); shlagbaum.write(90); // стрелка поднялась Serial.println("strelka podyata"); delay(2500); // машина проезжает shlagbaum.write(0); // стрелка опустилась Serial.println("strelka opushena"); delay(1000); } delay(100);}Прогон в симуляторе: карточка серво отрабатывает угол 0 → 90 → 0 ровно в тайминги скетча, зуммер показывает «tone: 1200 Гц» в момент проезда, Serial печатает три строки на каждый цикл — proezd!, strelka podyata, strelka opushena. Кнопка нажимается кликом по её карточке из палитры «Макетка»: сначала идёт зажатие, потом цикл доигрывается до конца даже после отпускания — так и задумано, кнопка лишь даёт команду.
Честная граница: что исполняет симулятор
| Проверка | Симулятор | Только железо |
|---|---|---|
| Servo.attach / write, углы 0–180 | исполняется, угол виден на карточке | то же самое |
| tone(pin, 1200, 200) и тайминги delay | исполняются, частота на карточке зуммера | слышно ухом |
| Кнопка с INPUT_PULLUP | карточка-кнопка, клик = нажатие | то же самое |
| Сама стрелка на валу | арта стрелки нет — виден угол | да: рычаг из подручного |
| Ток удержания SG90 (иначе вал дёргается) | нет: электричества в модели нет | да — до 700 мА пиками |
| Дрожание вала при плохом питании | не моделируется | да — отдельный БП |
Грабли: питание, дрожь и залипшая кнопка
- SG90 нельзя кормить от 5V платы при серьёзной стрелке: пик тока при старте — сотни миллиампер, плата перезагружается, серво дёргается. Питание от отдельного БП 5 В и общий GND с платой — правило, разобранное в уроке про питание серво.
- Стрелка дрожит на месте — серво переигрывает импульсы из-за просадки. Временное лечение в скетче: detach() после установки угла, вал отпускает и замолкает, но стрелку начнёт отводить рукой — компромисс против питания.
- Кнопку без INPUT_PULLUP читают висящим пином: она ловит наводки и шлагбаум открывается сам. Подтяжка pinMode(PIN_KNOPKA, INPUT_PULLUP) обязательна.
- Углы 0 и 90 — условность: у кронштейна стрелка может упираться раньше. Границы хода у живого SG90 подбирают калибровкой, а write держит 0–180 — за пределы не выйдет, но и упираться в корпус не надо.
- Не ставьте delay(2500) «на глаз» в реальном шлагбауме: длинная машина не успеет. На живом объекте таймаут переносят на millis и продлевают, пока датчик видит препятствие.