В LD две катушки на один выход: приоритет сетей и неожиданное перезаписывание
Почему в LD две катушки на один выход дают неожиданное поведение: порядок сетей, latch, reset и поиск через cross-reference.

Насос должен включаться по команде автомата и гаснуть по аварии уровня. На схеме все красиво. В поле насос иногда не стартует, иногда не останавливается, а в онлайн-мониторинге катушка «Пуск» мигает, хотя выход уже в другом состоянии. Открываете LD - и находите вторую катушку на тот же %Q0.3 в сети «Ручной режим», которую никто не помнил. Две катушки на один физический выход - не редкость, а нормальная цена роста проекта. Проблема в том, что IEC 61131-3 не гарантирует «последнюю победившую» без понимания порядка сетей.
Здесь не учебник LD с нуля и не сравнение LD со ST. Разбираем конфликт двух катушек на один выход: дублирование, порядок выполнения сетей, latch и reset, поиск через cross-reference. Статья не повторяет базовую релейную логику - для нее есть отдельный материал по языку LD.
Короткий ответ
Если в LD две и более катушки пишут в один и тот же выход, итоговое состояние определяется порядком выполнения сетей (rungs) в текущем цикле ПЛК, а не «логикой по смыслу». Последняя выполненная запись перезаписывает предыдущую. Катушка с latch удерживает выход, пока не сработает reset в той же или другой сети. Чтобы найти конфликт, используйте cross-reference (перекрестные ссылки) по адресу выхода и просмотрите все POU, где он упоминается.
Симптом «неожиданного» поведения почти всегда означает: выход пишут из нескольких мест, и вы смотрите только одну сеть. Лечение - не перестановка проводов, а явное разделение команд (одна катушка - один выход) или промежуточная переменная с приоритетом в отдельной сети.
Как ПЛК выполняет LD: один цикл, много сетей
В каждом цикле ПЛК обходит сети сверху вниз (в пределах POU и задачи). Катушка - это присвоение булева значения выходу. Если две катушки в разных сетях адресуют %Q0.3, в конце цикла на выходе останется то, что записала последняя сработавшая катушка по порядку выполнения.
Это не OR и не AND «по проводам». Это последовательная перезапись. Сеть 1 включила выход. Сеть 15 ниже по списку его выключила - и оператор видит «автомат дал пуск, а насос мертвый». Или наоборот: аварийная сеть выше по списку сбросила выход, а ручная сеть ниже снова включила - и межблокировка обойдена без злого умысла.
Порядок сетей зависит от организации проекта: несколько POU, порядок вызова, приоритет задач. Подробнее про цикл и задачи - в материале «Цикл ПЛК: порядок выполнения и гонки в программе».
Latch, reset и «залипание»
Катушка latch (SET) удерживает выход после краткого импульса на входе. Reset (RST) сбрасывает. Если latch в сети «Автомат», а reset в сети «Аварии» - поведение предсказуемо, пока порядок сетей согласован. Если reset стоит выше latch и срабатывает каждый цикл по ошибочному условию - выход никогда не включится. Если latch ниже и перезаписывает reset - авария не гасит выход.
Типичная ошибка: дублировать latch на тот же выход в ручном режиме «для надежности». Две latch-катушки на один бит - гарантированный источник сюрпризов при смене режима.
Дублирование в разных POU
Проект растет: основная логика в MAIN, ручной режим в MANUAL, аварии в ALARMS. Cross-reference по %Q0.3 показывает три катушки в трех модулях. Порядок вызова POU в задаче решает, кто победит. Инженер смотрит только MAIN и не понимает, почему «наша катушка активна, а выход ноль».
Правило для сопровождения: один физический выход - одна точка записи в программе. Все остальные места пишут в промежуточную переменную CmdPump или InterlockPump, а одна финальная сеть формирует %Q0.3 по приоритету: авария > ручной > автомат.
Cross-reference: как найти всех, кто пишет в выход
В CODESYS и аналогах: правый клик по переменной выхода - «Перекрестные ссылки» / Cross Reference. Получите список всех сетей и POU, где адрес используется как coil (запись). Отдельно проверьте force, GVL и привязки HMI - иногда «катушка» на экране пишет в тот же тег.
Онлайн-мониторинг показывает состояние сети, но не всегда все POU одновременно. Включите мониторинг в подозрительных модулях и пройдите один цикл: какая катушка последней меняет выход. Trace или запись переменной на один цикл - быстрый способ увидеть гонку.
Базовая механика LD и релейная модель - в «Язык LD (Ladder Diagram): как работает релейная логика».
Таблица: симптом, где еще пишут, как найти в LD
| Симптом на выходе | Где еще могут писать | Как найти в LD |
|---|---|---|
| Катушка ON, выход OFF | сеть ниже по списку сбрасывает | cross-ref, мониторинг сетей по порядку |
| Авария не гасит выход | latch в ручном режиме ниже reset | найти все SET/RST на адрес |
| Выход мигает каждый цикл | две сети поочередно 0/1 | trace на 2-3 цикла, порядок POU |
| Работает только в AUTO | отдельная логика в MANUAL POU | cross-ref по всем задачам |
| После загрузки проекта иначе | изменился порядок POU в task | сравнить конфигурацию задачи |
Явный приоритет вместо войны катушек
Вместо двух катушек на %Q0.3 делают одну выходную сеть:
IF Alarm THEN Out := FALSE ELSIF Manual THEN Out := ManualCmd ELSE Out := AutoCmd END_IFВ LD это выглядит как каскад контактов «разрешение аварии - разрешение ручного - автомат» и одна катушка в конце. Смысл тот же: приоритет задан явно, а не порядком случайных сетей.
Для насосов и клапанов полезно разделять команду (желание включить) и разрешение (можно ли). Тогда межблокировки не конкурируют с катушкой пуска на одном бите.
Типовые ошибки при сопровождении
Добавили ручной режим отдельной сетью «внизу файла» - он перезаписывает автомат каждый цикл, пока включен переключатель.
Скопировали сеть с другого агрегата - адрес катушки остался старым, теперь два механизма на один выход.
Reset только в AUTO - в MANUAL latch не сбрасывается аварией.
Исправили только мнемосхему - на HMI другой тег, в LD конфликт остался.
Пример из практики: насос и авария уровня
Сеть 10: автомат дает пуск насосу на %Q2.1. Сеть 45: авария уровня сбрасывает тот же %Q2.1 через обычную катушку. Сеть 80: ручной режим снова включает %Q2.1, если переключатель LOCAL. Порядок: 10, 45, 80. В AUTO при аварии уровня насос гаснет в сети 45. В LOCAL авария гасит в 45, ручная сеть 80 сразу зажигает снова - оператор видит «авария горит, насос крутится», мастер видит «межблокировка не работает». Cross-reference по %Q2.1 показывает три катушки; лечение - одна выходная сеть с приоритетом аварии над ручным.
Такие истории повторяются на каждом втором объекте с LD старше пяти лет. Не потому что LD плох, а потому что проект рос слоями без ревизии выходов.
LD, FBD и ST в одном проекте
Катушка в LD может писать в переменную, которую ST присваивает тому же %Q в конце цикла. В мониторинге LD «все правильно», а выход - из ST. Cross-reference обязан включать все языки. В CODESYS смотрят не только Coils, но и записи в ST и присвоения в FBD.
При рефакторинге часто выносят конфликтные выходы в отдельный POU OUTPUTS с одной задачей и одним проходом - туда сводят все команды. Остальная логика пишет только промежуточные разрешения. Это проще сопровождать, чем искать сеть 80 в файле на 3000 строк.
Ревью перед сдачей: правило «один выход - один writer»
Перед FAT полезно прогнать отчет: все физические выходы, у которых больше одной записи в проекте. Список согласуют с электросхемой. Для каждого «двойного» выхода - либо обоснование (например, аппаратное дублирование с OR в одной сети), либо исправление до пуска. На объекте такой отчет делают за полдня; на пуске исправление конфликта катушек может стоить смену простоя.
Force, HMI и «третья катушка»
Онлайн force на выходе в отладке - та же перезапись, только с панели. Оператор с правами наладчика может удерживать выход вопреки логике. Если force не сняли ночью - утром LD «врет» в мониторинге. Проверяют список активных force и записей в журнале отладки HMI.
Кнопка на мнемосхеме, привязанная напрямую к %Q, - еще один писатель. Граница «команда с экрана» и «катушка в LD» должна быть явной: экран пишет в HMI_CmdPump, LD решает, что пойдет на физический выход.
Связь с циклом ПЛК и временем реакции
Две катушки на один выход особенно коварны, когда одна сеть в быстрой задаче, другая - в медленной. Быстрая включает, медленная раз в 100 мс выключает - на осциллографе выход мерцает, в LD обе сети «правильные». Смотрят привязку POU к задачам и время цикла. Материал «Цикл ПЛК: порядок выполнения и гонки» дополняет картину: конфликт катушек - частный случай гонки записи.
При удлинении цикла из-за нагрузки порядок «кто последний» может теоретически сдвинуться, если изменили приоритеты задач. После оптимизации проекта перепроверяют спорные выходы.
Документирование выходов в as-built
В исполнительной документации к каждому физическому выходу полезна колонка «источник команды в ПЛК»: один POU, одна сеть, или явный каскад приоритетов. Тогда через три года никто не добавит «временную» катушку внизу файла, не заметив конфликта. Для новых проектов правило «один writer» закрепляют в стандарте кодирования команды - так же, как запрет на дублирование глобальных переменных без префикса участка.
Миграция legacy: не копировать сеть целиком
При переносе проекта с другого ПЛК часто копируют LD файл целиком. Адреса выходов совпадают с новой схемой «по номеру», но логика ручного режима с другого объекта остается. На старте все работает в AUTO; через полгода включают LOCAL на ремонте - и всплывает вторая катушка. При миграции делают отдельный проход: список всех %Q и %M, которые пишутся более одного раза, с пометкой «оставить / переписать / удалить».
Вопросы при работе
Можно ли запретить две катушки на один выход в среде?
Некоторые среды предупреждают при компиляции, многие - нет. Полагаться на дисциплину проекта и ревью cross-reference.
Почему на симуляторе OK, на объекте нет?
Другой порядок задач, другая версия библиотеки, force с панели, физический вход подтягивает цепь.
LD или ST для приоритетов?
Для каскада приоритетов ST читается проще; LD удобен, если команда одна финальная катушка после цепочки контактов.
