Сцену я помню дословно: новый модуль реле, первая прошивка тестовой мигалки — и в момент, когда IDE записывает скетч, в тёмной комнате щёлкает реле и вспыхивает лампа, которую я ещё даже не подключал к программе. Секунда дезориентации, затем мультиметр и лист бумаги: digitalWrite в скетче ещё не исполнялся, а реле уже отработало. Виноват не скетч и не брак — так устроен вход практически всех китайских реле-модулей, и если этого не понимать, каждый запуск платы будет начинаться с сюрприза.
Разгадка в схеме входа. Анод светодиода оптопары через резистор сидит на плюсе питания VCC, а катод ждёт, когда его притянут к земле. Тянуть к земле — работа цифрового пина с уровнем LOW: при LOW ток течёт, оптопара открывается, катушка срабатывает. При HIGH ток останавливается, реле выключено. Такой вход называют активным LOW: команда «включить» — это не «подать плюс», а «взять ток в себя». Пин здесь работает потребителем, и для него это безопасный режим: ток ограничен входным резистором.
Разберём, как оптопара даёт развязку, зачем на модуле подтяжка и почему щелчок при прошивке — прямое следствие входа, повисшего в воздухе. Скажу заранее: лечится это тремя строками в setup() и одной привычкой проверять модуль мультиметром, как в уроке про напряжение, ток и прозвонку.
Оптопара PC817: светодиод, фототранзистор и зазор в миллиметр
PC817 — пара «светодиод плюс фототранзистор» в одном четырёхногом корпусе. Светодиод сидит на стороне входа, фототранзистор — на стороне выхода, между ними нет электрического контакта, только свет и зазор внутри корпуса, рассчитанный на изоляцию в единицы киловольт. Входной светодиод за резистором около 1 кОм берёт примерно 4 миллиампера — счёт идёт на миллиамперы, а не на десятки. Выход открывает транзистор модуля, транзистор включает катушку. Для Uno это значит: любые проблемы на релейной стороне — выбросы, наводки, косяки питания — встречают стену из светового барьера.
Развязка раскрывается вместе с перемычкой JD-VCC из урока про подключение реле к Uno: релейная часть может жить от своего блока, а плата — от USB, и между ними только оптопары. Соблазн «для надёжности» объединить минусы до оптрона — классическая промашка с форумов: развязка превращается в декорацию, наводки от катушек возвращаются в плату, и отловить их потом — развлечение для очень настойчивых. Земли соединяют в одной точке и только тогда, когда без этого никак; о том, чем грозит бардак в общих проводах, писал в уроке про GND и общий провод.
Практический бонус развязки — совместимость с 3,3-вольтовой логикой ESP32: там высокий уровень — 3,3 вольта, и кормить им HIGH-активный вход рискованно, а вот притянуть вход к земле может любой GPIO. Поэтому активный LOW на оптопаре — не каприз производителей, а рабочая страховка: включение требует «взять ток в себя», и это умеет любая платформа.
Теперь о щелчке при прошивке. Между сбросом платы и стартом вашего setup() проходит сотня-другая миллисекунд, и всё это время пины находятся в Hi-Z — высокоомном состоянии «не мой вопрос». Вход IN повисает в воздухе, его уровень определяется паразитной ёмкостью и наводками; оптопара ловит случайный потенциал, реле дёргается. У приличных модулей на плате стоит подтяжка 10 кОм от IN к VCC — вход держится у плюса, реле молчит. У дешёвых клонов подтяжки нет, и они честно щёлкают при каждой прошивке, как мой первый модуль.
Лечение — порядок записи. На AVR digitalWrite с уровнем HIGH на пине, который ещё в режиме INPUT, включает внутреннюю подтяжку около 20-50 кОм. Поэтому в setup() сначала пишем выключающее значение, потом переводим пин в OUTPUT: digitalWrite(PIN, HIGH); pinMode(PIN, OUTPUT); digitalWrite(PIN, HIGH). Даже если подтяжки на модуле нет, вход уже не болтается — а дальше скетч держит уровень сам. Тот же трюк выручает и при отладке, когда скетч перезапускается по двадцать раз за вечер.
Подтяжку на модуле видно без вскрытия: мультиметр в режиме измерения сопротивления между IN и VCC показывает около 10 килоом — значит, вход прикрыт. Ноль или бесконечность — подтяжки нет, и тихий старт живёт только в скетче. Для наводки прибора хватит и снятого модуля: эта проверка не требует ни питания, ни нагрузки, но спасает от сюрприза при первой же прошивке. Если на плате стоит резистор, а реле всё равно дёргается, смотрите на длину проводов: вход, растянутый шлейфом на полметра через всю макетку, собирает наводки, которые подтяжка 10 кОм не всегда пересиливает — провода короче и в жгуте, о борьбе с наводками писал в уроке про экранирование.
Светодиод IN на плате — честный маяк и бесплатный логический пробник: он горит ровно тогда, когда ток через оптрон течёт, независимо от того, что вы думаете о своём скетче. Если индикатор светится, а реле молчит — дело в релейной части: питание катушки, перемычка JD-VCC или сам транзистор. Если реле щёлкает, а индикатор нет — у вас модуль с прямым входом, и инверсия из этого урока вам не подходит, хотя таблица истинности меняется зеркально.
И запасной вариант на время отладки: перевести пин в INPUT_PULLUP и забыть про OUTPUT, пока крутите остальную логику. Подтяжка AVR держит вход у плюса, реле молчит, а включить реле на секунду можно временной строкой pinMode(OUTPUT) — включилось — digitalWrite(LOW) — pinMode(INPUT_PULLUP). Неаккуратно, зато наглядно: удобно, когда проверяешь механику клемм, а не пишешь финальный скетч. Тем же способом удобно разбудить «уснувший» модуль после экспериментов с питанием: подтяжка вернёт вход в покой, и реле перестанет ловить привидения с вашей же руки над платой.
Тихий старт: три строки против утреннего щелчка
// Тихий старт: выключающее значение пишется в пин ДО pinMode.// На AVR это поднимает внутреннюю подтяжку — вход модуля не висит// в воздухе в те сотни миллисекунд, пока IDE перезапускает плату.const int PIN_RELAY = 7;const int PIN_BTN = 2;const int RELAY_ON = LOW; // активный LOW: ток через оптопару течёт при LOWconst int RELAY_OFF = HIGH; bool releVkl = false;bool prevBtn = HIGH; void setup() { Serial.begin(9600); digitalWrite(PIN_RELAY, RELAY_OFF); // подтяжка уже включена pinMode(PIN_RELAY, OUTPUT); digitalWrite(PIN_RELAY, RELAY_OFF); pinMode(PIN_BTN, INPUT_PULLUP); Serial.println("tihij start: rele molchit, knopka perelyuchaet");} void loop() { bool pressed = digitalRead(PIN_BTN) == LOW; if (pressed && prevBtn == HIGH) { releVkl = !releVkl; digitalWrite(PIN_RELAY, releVkl ? RELAY_ON : RELAY_OFF); Serial.println(releVkl ? "IN=LOW - rele vklyuchen" : "IN=HIGH - rele vyklyuchen"); } prevBtn = pressed; delay(20); // грубый антидребезг для демо}Обратите внимание на дуализм: кнопка в скетче читается через INPUT_PULLUP, и «нажата» — это тоже LOW. Активный LOW на входе реле и активный LOW на кнопке — одна и та же схема в двух исполнениях: ток течёт, когда пин прижат к земле. Как только вы это видите, инверсия перестаёт путаться: и там, и там «истина» приходит нулём. Термостат, который щёлкает реле каждые полминуты из-за колебаний порога, лечится гистерезисом — приём разобран в уроке про клацанье реле и гистерезис.
В больших проектах инверсия всплывает на каждом шагу. В MQTT-уроке про свет из брокера статус команды сверяется с фактическим уровнем пина — и без констант RELAY_ON/RELAY_OFF легко записать наоборот; то же при подтверждениях с QoS1 в уроке про реле и QoS1. Мой дисциплинарный минимум: в любом проекте с реле сначала пишу две константы, потом первый digitalWrite — и тестирую щелчком при прошивке до подключения нагрузки. Этот же порядок описан в уроке про реле и мощную нагрузку со стороны схемы.
| Уровень на IN | Ток через оптрон | Контакты реле | Когда встречается |
|---|---|---|---|
| HIGH (5 В) | ноль, светодиод оптопары погашен | COM держит НЗ | норма покоя, реле молчит |
| LOW (0 В) | около 4 мА, пин втягивает ток | COM переходит на НО | команда «включить» |
| Пин в Hi-Z (сброс) | зависит от подтяжки модуля | случайные щелчки | прошивка без подтяжки — главная сцена урока |
| INPUT_PULLUP на пине | нулевой, подтяжка AVR держит уровень | COM держит НЗ | резервный режим покоя на время отладки |
- 1. Почему реле-модуль включается от LOW?
- 2. Какой ток течёт через вход оптопары при резисторе около 1 кОм и питании 5 В?
- 3. Какая строка в setup() защищает от щелчка при прошивке?
- 4. Как одним взглядом отличить активный-LOW модуль?
- 5. Какая подтяжка обычно стоит на приличных модулях от IN к VCC?
- Активный LOW — следствие схемы: анод оптрона на VCC, пин втягивает ток, чтобы включить катушку.
- PC817 — светодиод и фототранзистор с изоляцией на киловольты; входной резистор держит ток около 4 мА.
- Против щелчка при прошивке: digitalWrite выключающего уровня до pinMode(OUTPUT) — подтяжка AVR поднимет вход.
- Проверка модуля за минуту: подали VCC и GND, коснулись IN проводком с GND — щёлкнул, значит активный LOW.
- Развязка жива, пока минусы релейной части не слиты с платой раньше оптрона; общий минус — только в одной точке.
Частые вопросы по теме урока
- Почему реле-модуль включается от LOW?
- Вход оптопары питается от VCC, поэтому ток течёт тогда, когда пин открывает ему путь на землю — уровнем LOW. Отсюда и название «активный LOW». анод светодиода оптопары сидит на VCC, и пин втягивает ток, прижимая катод к земле
- Какой ток течёт через вход оптопары при резисторе около 1 кОм и питании 5 В?
- Падение на светодиоде около 1,2 В, остальное на резисторе: (5 − 1,2) / 1000 — примерно 4 мА. Для пина это пустяк. около 4 мА
- Какая строка в setup() защищает от щелчка при прошивке?
- На AVR digitalWrite с HIGH на входном пине включает внутреннюю подтяжку 20-50 кОм — вход модуля перестаёт висеть в воздухе до и во время старта. digitalWrite(PIN, HIGH) до pinMode(PIN, OUTPUT)
- Как одним взглядом отличить активный-LOW модуль?
- Тест с проводком от GND к IN — надёжный: щёлкнул — активный LOW. Индицирующий светодиод входа при этом горит, потому что ток течёт именно при LOW. индикатор IN светится, когда вход прижат к земле, и реле щёлкает от касания GND
- Какая подтяжка обычно стоит на приличных модулях от IN к VCC?
- 10 кОм — типовое значение: держит вход у плюса в паузах между сбросом и setup(), не мешая пину прижать его к земле при включении. 10 кОм