Блог

В FBD сигнал теряется между блоками: Как найти место, где он стал нулем

2026-07-09 13:10
В FBD это выглядит почти обидно. На входе сети значение есть: датчик живой, флаг разрешения активен, число в онлайн-мониторинге не нулевое. Через два блока справа значение уже стало 0, FALSE или осталось старым, а механизм, расчет или признак на HMI ведет себя так, будто сигнала не было.
Плохая новость: по картинке FBD легко поверить, что сигнал «течет» слева направо сам по себе. Хорошая новость: если не прыгать сразу в правку кода, место потери обычно находится довольно быстро. Нужно идти не по всему проекту, а по короткому участку: выход предыдущего блока, вход следующего, разрешение выполнения, тип данных, состояние экземпляра и место, где эту же переменную записали повторно.
Эта статья не про то, что такое FBD и чем он отличается от других языков. Здесь разберем практическую ситуацию: значение было на входе сети, но на выходе функции или функционального блока исчезло. Задача инженера - понять, где именно оно стало нулем, что могло его заблокировать и какой просмотр подтверждает причину.

Короткий ответ

Ищите не «плохой блок», а первую точку, где значение изменилось неожиданно. Сравните онлайн-значение на входе сети, на входе подозрительного блока, на его EN, на выходе ENO, на основном выходе и на переменной, куда этот выход записывается. Если до блока значение есть, а после нет, причина чаще всего в отключенном выполнении, выборе не той ветви SEL или MUX, ограничении LIMIT, неявном преобразовании типа, внутреннем состоянии экземпляра FB или последующей перезаписи этой же переменной в другой сети.
Перед изменением логики полезно сделать снимок онлайн-мониторинга, записать цикл или режим, в котором повторяется симптом, и открыть cross-reference по переменной. В FBD сигнал может выглядеть потерянным «между блоками», хотя на самом деле он появляется на один цикл, затем стирается следующей сетью, сбрасывается аварийным участком, приходит с плохим качеством входного тега или не проходит через блок из-за EN/ENO.

Сначала найдите последнюю живую точку

Самая спокойная тактика - поставить рядом несколько наблюдаемых точек. Не только итоговый тег, а промежуточные значения: исходный входной тег, результат масштабирования, выход фильтра, выход ограничителя, выбранный вход мультиплексора, итоговый флаг разрешения. Если среда разработки позволяет смотреть значения прямо на линиях FBD, используйте это. Если линии показывают только часть данных или обновляются рывками, вынесите нужные точки во watch-окно.
На участке FBD «вход сети - первый блок» сигнал обычно теряется из-за качества исходного тега, неверного режима или неподходящего типа. Например, полевая переменная пришла с флагом Bad, а программа в таком случае подставляет ноль. На линии перед блоком вы видите уже не реальное значение, а обработанный дефолт. Подтверждает это просмотр статуса канала, диагностического бита, raw-значения или структуры качества тега, если она есть в проекте.
На участке «блок - блок» чаще виноваты условия выполнения, выбор ветви и преобразования. Поэтому фиксируйте не только основное значение, но и управляющие входы: EN, SEL, номер канала, режим Manual/Auto, флаги interlock, reset, simulation, force. В FBD ноль редко появляется мистически. Чаще он пришел по соседней линии, которая на схеме кажется второстепенной.
Хороший признак, что вы идете правильно: после каждого просмотра остается один конкретный вопрос. Не «почему не работает весь расчет», а «почему вход G у SEL сейчас ложный», «почему IN2 у MUX равен нулю», «почему ENO погас после этого блока», «почему переменная Pump_Enable снова записана ниже по проекту».

EN и ENO: блок виден, но не выполняется

EN/ENO - одна из самых частых причин, когда на входе блока значение есть, а на выходе ничего полезного нет. В онлайн-картинке блок стоит на месте, линии нарисованы, входные значения могут отображаться, но сам вызов отключен. Тогда выход остается прежним, сбрасывается в значение по умолчанию или ведет себя по правилам конкретной среды и библиотеки.
Участок FBD здесь простой: значение приходит на вход функции, но вход EN ложный или пропадает на один цикл. Что может заблокировать сигнал? Режим ручного управления, общий флаг готовности, аварийный сброс, межблокировка, отсутствие связи с модулем, запрет от HMI, состояние шага автомата. Подтверждает причину онлайн-просмотр EN, ENO и всех сигналов, из которых собран EN. Если EN ложный, дальнейший спор про математику внутри блока бессмысленен: блок в этот цикл не обязан выдавать новый результат.
Особенно неприятны случаи, когда EN включается не постоянно, а импульсом. В watch-окне кажется, что он «иногда зеленый», но расчет нужен каждый цикл. Тогда выход может обновляться редко, а между обновлениями другой участок программы успевает сбросить его. Для подтверждения лучше использовать trace или счетчик вызовов: простая переменная, увеличивающаяся внутри участка, быстро показывает, реально ли блок исполняется с нужной периодичностью.
ENO тоже не декоративный хвост. У части библиотечных функций он показывает ошибку выполнения, выход за допустимые параметры, невалидный вход или внутренний запрет. Если основной выход стал нулем, а ENO ложный, стоит смотреть не правую часть схемы, а входные условия конкретного блока: диапазоны, указатели на экземпляр, корректность параметров, доступность данных.

Тип данных может съесть значение без громкой аварии

Следующий участок - преобразование между блоками. На входе сети есть число, после преобразования оно стало нулем, FALSE или странной ступенькой. В FBD такие места иногда выглядят невинно: маленький блок REAL_TO_INT, WORD_TO_BOOL, деление с целочисленным результатом, упаковка битов, преобразование из UINT в INT, масштабирование перед сравнением.
Что может обнулить сигнал? Дробное значение меньше единицы при переводе в целое, переполнение диапазона, неверная знаковость, обрезка старших битов, преобразование NaN или недопустимого значения в ноль по правилам платформы. Иногда сама среда честно показывает предупреждение, но в старом проекте предупреждения давно стали фоном, и на них перестали смотреть.
Подтверждение - сравнить исходное значение, тип переменной, тип входа блока и тип выхода после преобразования. Не по названию тега, а по объявлению. Если вход называется Pressure_REAL, это еще не гарантия, что он действительно REAL на всем пути. В онлайн-просмотре полезно добавить одну и ту же величину в разных представлениях: инженерное значение, raw, тип после масштабирования, результат сравнения. Если число 0.4 после преобразования ожидаемо стало 0, FBD не потерял сигнал. Он сделал ровно то, что ему приказали.
Отдельная ловушка - неявные преобразования на входах библиотечных блоков. Визуально линия подключена, значит «должно работать». Но блок может принимать INT, а до него приходит REAL; может требовать беззнаковое значение, а вы подаете отрицательное; может ожидать проценты 0-100, а получает долю 0-1. Подтверждает причину документация на блок и просмотр фактических значений прямо на его входах, а не только до предыдущего блока.

LIMIT: значение не исчезло, его прижали к границе

LIMIT часто подозревают поздно, потому что блок вроде бы безопасный. Он же не ломает сигнал, он защищает диапазон. Но если после него всегда ноль, то для следующего участка программы разницы нет: сигнал потерян.
Типовой участок: на вход IN приходит нормальное значение, а на выходе OUT постоянно 0. Что могло случиться? Нижняя граница MN равна нулю, вход ниже минимума, верхняя и нижняя границы перепутаны, границы пришли из уставок HMI и одна из них сброшена, масштабирование перед LIMIT перевело величину в другой диапазон. Иногда LIMIT стоит после фильтра, а фильтр при плохом качестве входа сам отдает ноль, и ограничитель только закрепляет картину.
Подтверждение простое: смотреть одновременно IN, MN, MX и OUT. Если IN ниже MN, выходной ноль не является неисправностью блока. Если MN и MX выглядят странно, нужно идти к источнику уставок. Если вход до LIMIT нормальный в инженерных единицах, но границы заданы в raw-единицах, причина не в FBD-линиях, а в несогласованных масштабах.
Хорошая привычка - проверять LIMIT не только по факту нуля, но и по «слишком правильному» значению. Когда выход всегда ровно 0, 100, 27648 или другая красивая граница, это не похоже на шум датчика. Это похоже на ограничение, замену дефолтом или выбор другого источника.

MUX и SEL: выбран не тот вход

Если в FBD есть SEL, MUX, выбор режима, ручной дублер или подстановка аварийного значения, сигнал может теряться не потому, что он плохой. Его просто не выбрали.
На участке SEL вход IN1 живой, но на выходе ноль из IN0. Причина - управляющий вход находится не в том состоянии. Например, режим Auto не включен, ручной режим оставил задание равным нулю, флаг simulation активен, аварийная подстановка включилась после квитирования, или бит выбора берется из старой переменной HMI. Подтверждает это просмотр обоих входов SEL, управляющего входа и источника этого управляющего сигнала.
С MUX похожая история, только неприятнее. Номер выбранного входа может быть вычисляемым: номер рецепта, индекс канала, состояние шага, выбранный датчик. Если индекс выходит за диапазон или сдвинут на единицу, блок берет не тот вход. На экране видно, что «значение перед MUX есть», но это не тот вход, который сейчас выбран. Подтверждение - онлайн-просмотр индекса, всех соседних входов и результата при ручной проверке в безопасном режиме моделирования или на стенде, если проект это допускает.
Здесь важно не менять сразу константу выбора. Сначала надо понять, кто ее формирует. Если SEL ушел в ручной источник из-за аварийного режима, правка самого SEL только замаскирует причину. Если MUX берет нулевой канал из-за индекса, который приходит из рецепта, надо проверять рецепт, валидацию индекса и начальные значения при старте.

Экземпляр функционального блока помнит больше, чем видно на линии

Функциональный блок не равен обычной функции. У него есть экземпляр и внутреннее состояние: таймеры, защелки, прошлые значения, признаки инициализации, диагностические флаги. Поэтому участок «вход FB - выход FB» нельзя читать только по внешним линиям.
На вход FB приходит TRUE или нормальное число, но выход остается FALSE или 0. Что может удерживать его внутри? Внутренний Reset, незавершенная инициализация, таймер задержки, старый аварийный флаг, блокировка после ошибки, требование фронта вместо уровня, неактивный режим, внутренний фильтр качества. Внешний FBD-лист показывает только контракт блока, а не все его внутренние решения.
Подтверждение - открыть онлайн-просмотр экземпляра. Не исходный шаблон FB, а именно тот экземпляр, который вызван в этой сети: его внутренние переменные, таймеры, состояния, диагностический код, счетчик вызовов. Если в проекте несколько одинаковых экземпляров, легко смотреть не тот. Название экземпляра, путь POU и место вызова должны совпадать.
Отдельная ошибка - один и тот же экземпляр FB вызван в двух местах. Тогда внутреннее состояние перетирается между вызовами, и выход может выглядеть случайным. Подтверждает это cross-reference по имени экземпляра и поиск всех вызовов. Если экземпляр должен быть один на объект, второй вызов часто объясняет странное поведение лучше, чем любая гипотеза про «неправильный блок».

Порядок выполнения сетей важнее, чем расположение на экране

В FBD легко смотреть глазами слева направо и сверху вниз, но фактический порядок выполнения задается проектом: POU, task, порядок сетей, порядок вызовов программ, приоритет задач, иногда настройки компилятора или среды. Поэтому сигнал может появляться в одной сети, а потом сбрасываться в другой, которая выполняется позже в том же цикле.
Участок «выход блока - итоговая переменная» особенно показателен. Вы видите, что выход блока стал TRUE, но итоговая переменная в watch-окне остается FALSE. Что может быть не так? Вы смотрите выход локальной линии, а переменная после этого перезаписывается. Или сеть с расчетом вызывается после сети, где это значение уже использовали. Или быстрый task обновляет переменную, а медленный task потом кладет старое состояние поверх.
Подтверждает причину cross-reference по записи переменной: все места, где ей присваивают значение, а не только где ее читают. Полезно смотреть временную последовательность: значение на выходе блока, значение переменной сразу после присваивания, значение в конце цикла, значение в HMI. Если среда поддерживает trace, он быстро показывает импульс «поднялось и тут же упало». Если trace нет, можно временно вывести диагностический счетчик или внутренний флаг в watch, но такие изменения делают только по принятому порядку отладки и с пониманием риска.
Для темы цикла ПЛК это ключевой момент: экран онлайн-мониторинга не всегда показывает каждое мгновение выполнения. Он показывает срез, обновленный с собственной частотой. Поэтому короткий ноль или короткая единица может не попадать в картинку. Смотрите не только «горит сейчас», а то, в каком task выполняется логика, как часто обновляется входной тег и где переменная используется дальше.

Сброс в другом участке программы

Самая раздражающая причина - сброс в соседнем месте. В FBD все на вид чисто: вход есть, блок выдал результат, линия дошла до переменной. Но через пару миллисекунд другой участок программы пишет туда FALSE, 0 или значение по умолчанию.
Что может сбрасывать сигнал? Общий аварийный reset, начальная инициализация при потере связи, ручной режим, межблокировка, блок «безопасное состояние», обработка плохого качества, логика остановки линии, старый участок кода после модернизации. Такие места обычно писались не как ошибка. Они были правильными для прежней версии объекта, а после доработки стали сильнее нового расчета.
Подтверждение - не спорить с картинкой FBD, а открыть все записи переменной. Ищите не только точное имя, но и структуру, массив, alias, mapping, глобальную переменную, поле экземпляра. Если переменная называется Cmd_Start, проверьте, не записывается ли Unit.Cmd.Start, HMI.CmdStart, OutMap.Start или промежуточный тег, который потом копируется в нее.
Очень полезен вопрос: «Кто последний записал это значение в цикле?» Если ответ найден, причина почти всегда становится приземленной. Например, расчет разрешения выдает TRUE, но сеть аварийного сброса ниже по проекту всегда обнуляет команду, потому что старый флаг DoorClosed давно не обновляется. Тогда проблема не в FBD-связи между блоками, а в логике приоритета.

Качество входного тега: ноль может быть заменой, а не измерением

Если вход сети связан с физическим каналом, OPC-тегом, Modbus-регистром, HMI-переменной или внешним блоком, значение может стать нулем еще до FBD-участка. При этом на экране оно выглядит как обычный 0, если качество не выведено рядом.
На участке «входной тег - первый расчет» сигнал может обнулиться из-за плохого качества, потери связи, ошибки диапазона, неподтвержденной диагностики канала, неверной привязки адреса или начального значения после старта. В проектах с аккуратной обработкой качества это хорошо видно: вместе со значением идет статус Good/Bad/Uncertain, диагностический бит или код ошибки. В проектах попроще плохое качество часто превращают в ноль «чтобы расчет не падал». Для эксплуатации это опасно: ноль начинает выглядеть как реальный технологический ноль.
Подтверждает причину просмотр raw-значения, статуса канала, диагностического слова модуля, флага связи и времени последнего обновления. Если raw стоит на месте, статус плохой, а FBD получает ноль, дальше по схеме искать нечего. Сначала надо понять, почему входной тег не является достоверным.
Это особенно важно для аналоговых значений. Ноль после масштабирования может означать реальный ноль процесса, обрыв, ошибку диапазона, плохую связь, ручную подстановку, начальное значение при старте или результат фильтра. Без статуса качества FBD превращается в красивую картинку, где разные причины выглядят одинаково.

Онлайн-мониторинг: смотрите срез, а не кино

Онлайн-мониторинг помогает, но его легко переоценить. Он обновляется реже, чем выполняется программа, может показывать усредненный или поздний срез, а в больших проектах часть значений подтягивается с задержкой. Если сигнал теряется между блоками на один цикл, обычный онлайн-режим может его не поймать.
Что подтверждает причину лучше статичной картинки? Trace по нескольким точкам, диагностический счетчик, журнал смены состояния, просмотр task load, временная метка обновления тега, счетчик вызовов FB, список force-значений, список активных simulation-переменных. Не надо включать все сразу. Достаточно выбрать две-три точки вокруг подозрительного участка: до блока, после блока, после записи итоговой переменной.
Плохой сценарий отладки - начать двигать линии, менять типы и отключать блокировки «чтобы проверить». После этого вы уже не знаете, какую проблему ловите: исходную или созданную в процессе. Нормальный сценарий проще: зафиксировали исходные значения, нашли первую точку потери, подтвердили управляющий сигнал или запись, только потом сделали правку в копии проекта, на стенде или по регламенту изменения.
Если есть симулятор ПЛК или тестовый стенд, спорный участок лучше воспроизвести там. Для FBD это удобно: можно задать входные значения, переключить SEL, прогнать LIMIT, проверить экземпляр FB и увидеть, как меняется выход без давления объекта и без риска случайно остановить линию. На рабочем оборудовании диагностика должна идти в рамках принятого регламента, особенно если затронуты блокировки, команды механизмов и аварийные состояния.

Частые ошибки при поиске

Смотреть только итоговый выход. Если переменная в конце равна нулю, это еще не говорит, где она стала нулем. Нужны промежуточные точки вокруг каждого блока, иначе диагностика превращается в угадывание.
Игнорировать управляющие входы. У SEL, MUX, LIMIT, таймеров и FB важны не только основные данные. Один ложный EN, неверный индекс или нулевая граница меняют результат сильнее, чем само входное значение.
Верить имени переменной больше, чем типу. Название TempReal не гарантирует REAL, а AlarmBool не гарантирует, что это чистый флаг без промежуточного слова, маски или инверсии.
Смотреть не тот экземпляр FB. В проекте может быть десять одинаковых блоков. Если путь экземпляра не совпал, вы анализируете чужое состояние и будете чинить не ту цепочку.
Не проверять повторные записи. В FBD часто видно место, где переменная стала правильной. Но если ее потом перезаписали, итоговое поведение определяет последняя запись, а не самая красивая сеть.
Путать ноль процесса и ноль по умолчанию. Если качество входа плохое, связь потеряна или канал не обновляется, ноль может быть подстановкой. Без статуса качества выводы по FBD будут шаткими.

Что фиксировать после обнаружения причины

Если причина найдена, не стоит оставлять ее только в памяти инженера. Зафиксируйте скриншот онлайн-мониторинга с видимыми точками до и после проблемного блока, путь POU и имя экземпляра, текущий режим объекта, значения управляющих входов, статус качества тега, список мест записи переменной и вывод: где именно сигнал стал нулем.
Если это ошибка логики, дальше нужен обычный маршрут изменения проекта: заявка, ревизия, проверка на стенде или в симуляторе, согласование, обновление as-built и резерв проекта. Если это плохое качество входного тега или связь с физическим каналом, передайте данные тому, кто отвечает за шкаф, сеть или прибор: не «FBD не работает», а «до блока приходит ноль из-за Bad quality канала AI-3, raw не обновляется, расчет ниже только повторяет дефолт».
Такая формулировка экономит часы. Электрик, КИП, программист ПЛК и оператор видят не общую жалобу, а точку разрыва: участок FBD, что именно заблокировало или обнулило сигнал, и какой просмотр это подтвердил.

На практике

Когда в FBD значение исчезает между блоками, полезно думать короткой фразой: «последняя живая точка - первый неправильный выход - кто управляет этим переходом». Если на входе LIMIT было 23.4, а на выходе 0, смотрите границы. Если перед SEL живой сигнал, а после ноль, смотрите выбранную ветку. Если FB получил вход, но не выдал результат, смотрите EN/ENO и внутреннее состояние экземпляра. Если выход стал правильным, но итоговая переменная опять ноль, смотрите порядок выполнения и повторные записи.
FBD удобен тем, что визуально показывает путь сигнала. Но диагностировать нужно не картинку, а выполнение: типы, управляющие входы, состояние экземпляра, качество данных и цикл программы. Тогда «сигнал потерялся» превращается в конкретный дефект, который можно передать в работу без гадания и без опасных правок на объекте.