I. Разработка программы
MetaGen

9. Аварии и предупреждения в программе ПЛК

Настройки у нас уже находятся в Conf, а команды и данные для отображения — в View. Исходные переменные и рабочие состояния при этом остаются в GVL и экземплярах блоков. Кроме этих данных MetaGen отдельно создаёт код обработки аварий, предупреждений и сообщений — функциональный блок Alarms.

В этой главе разберём только программу ПЛК: откуда берутся сигналы, как включить лампу и звук, квитировать звук и сбросить запомненную аварию. Генерацию артефактов для Weintek и WinCC покажем позднее, в главах про HMI.

1. Укажите, какое значение означает срабатывание

В Data есть три столбца:

Столбец Назначение
Flt Авария. Участвует в общей аварийной сигнализации.
Wrn Предупреждение. Участвует в общей предупредительной сигнализации.
Alm Отдельное сообщение. Его состояние формируется, но в сводные выходы аварий и предупреждений не входит.

В ячейке задаётся значение исходной переменной, при котором сигнал активен. Например, TRUE — срабатывание при включённом BOOL, FALSE — при выключенном. Для числового состояния можно задать конкретное число.

Генератор сравнивает источник с содержимым выбранной ячейки. Источником может быть как готовый сигнал, так и выражение ST — отдельную BOOL-переменную для каждого условия создавать необязательно.

Пустая ячейка означает отсутствие условия. Ноль — полноценное значение срабатывания, а не отключённый флажок. В одной строке заполняют только один из трёх столбцов.

Для примера возьмём три уже подготовленных логических сигнала. Это небольшой самостоятельный пример; менять алгоритм коррекции температуры из предыдущих глав не требуется.

В глобальной таблице они могут быть объявлены так:

st
bSensorFault : BOOL := FALSE;
bPressureOK : BOOL := TRUE;
bServiceActive : BOOL := FALSE;

В Data для всех трёх строк задайте Type = BOOL, Mode = global. Area и Value оставьте пустыми. Ниже показаны заполняемые столбцы в их обычном порядке; остальные в этом примере пусты:

Tag Comment Flt Wrn Alm
bSensorFault Неисправность датчика TRUE — —
bPressureOK Давление вне нормы — FALSE —
bServiceActive Сервисный режим включён — — TRUE

Publish исходной строки для самой обработки сигнализации не требуется. Например, bSensorFault может не иметь отдельной опубликованной копии, но его аварийное состояние будет обработано.

Выражение прямо в строке сигнализации

Например, для превышения температуры задайте:

Type Mode Area Tag Flt
BOOL global — (fRaw1 > 80.0) TRUE

fRaw1 — уже объявленная глобальная переменная температуры. Type = BOOL здесь соответствует результату сравнения. Area, Value и Publish оставьте пустыми; в Comment напишите «Высокая температура».

В Alarms.st для первого события получится:

st
bAlarm_0_0 := ((fRaw1 > 80.0) = TRUE);

Условие вычисляется при каждом вызове Alarms в ПЛК. Это обычное выражение ST, а не %...% встроенного интерпретатора, который работает до генерации кода.

Publish у такой строки оставляем выключенным: выражение в Tag не является именем отдельного публикуемого тега. Для события генератор сам создаст именованный BOOL и его копию в View, как показано ниже.

2. Посмотрите, какой код создала MetaPlatform

Для MetaCore найдите следующие файлы:

Файл Что в нём появится
FunctionBlocks/Alarms.st Проверки условий, отдельные сигналы и сводные выходы
GVL/Inst.st Экземпляр Alarms_Inst
FunctionBlocks/_MetaGen_Main.st Вызов Alarms_Inst после проектных компонентов
Types/_View.st Команда сброса, состояния сигнализации и отдельные сигналы
Functions/makeView.st Копирование состояний из Alarms_Inst в View

Alarms собирает условия из компонентов всего проекта. Отдельный экземпляр для каждого датчика добавлять в Instances не нужно.

В основном блоке уже будет вызов:

st
Alarms_Inst(
    inout_bReset := View.Alarms_Inst_inout_bReset
);

Следом выполняется makeView(). Получается последовательность: проектные компоненты формируют состояния → Alarms обрабатывает их → makeView обновляет данные для отображения.

Проверки внутри Alarms для нашего примера сводятся к трём условиям:

st
bSensorFault = TRUE
bPressureOK = FALSE
bServiceActive = TRUE

Здесь показаны именно условия, а не отдельный код для вставки. Генератор сам записывает результаты в отдельные BOOL и упаковывает их в слова WORD.

Все события проекта: WORD и BOOL

Все события Flt, Wrn и Alm из всех проектных компонентов собираются в общий набор. Каждому событию выделяется один бит в слове WORD и отдельный сигнал BOOL с тем же состоянием.

В одном WORD помещается 16 событий: биты от 0 до 15. Следующее событие занимает бит 0 следующего слова. Нумерация слов также начинается с нуля.

Событие в общем списке Слово внутри Alarms Бит Отдельный BOOL внутри Alarms
Первое wAlarmTag0 0 bAlarm_0_0
Шестнадцатое wAlarmTag0 15 bAlarm_0_15
Семнадцатое wAlarmTag1 0 bAlarm_1_0

И слова, и отдельные BOOL имеют копии в View. Например, makeView создаёт такие присваивания:

st
View.Alarms_Inst_wAlarmTag0 := Alarms_Inst.wAlarmTag0;
View.Alarms_Inst_bAlarm_0_0 := Alarms_Inst.bAlarm_0_0;

Это два представления одних и тех же событий: несколько состояний в одном слове либо каждый сигнал отдельно. Они формируются автоматически, независимо от Publish исходной строки сигнализации.

Номера зависят от общего порядка событий при генерации. bAlarm_0_0 в примере — первое событие всего проекта, а не первое событие каждого компонента. Фактические имена и комментарии смотрите в Alarms.st и _View.st; после изменения состава или порядка событий сверяйте их заново.

3. Входы Alarms: команда квитирования

Оба входа выполняют одно действие: сбрасывают запомненные признаки новых аварий и предупреждений.

Параметр Тип Как использовать
in_bReset BOOL, вход Подать команду из программы. Блок сам этот вход не выключает; снятие команды обеспечивает вызывающий код.
inout_bReset BOOL, вход-выход Записать TRUE в связанную переменную. После обработки блок сам возвращает её в FALSE. В сгенерированном вызове это View.Alarms_Inst_inout_bReset.

Для обычной команды из проектного компонента удобно использовать уже подключённое поле View. Менять сгенерированный вызов или вызывать Alarms_Inst второй раз не нужно.

Название входа содержит Reset, но его действие важно понимать точно: он квитирует признаки новых сигналов внутри Alarms, а не сбрасывает исходные аварии механизмов.

4. Выходы Alarms: действующее и новое событие

Все выходы имеют тип BOOL.

Выход Когда включён
out_bFault Есть хотя бы одно действующее условие Flt
out_bWarning Есть хотя бы одно действующее условие Wrn
out_bSignal Есть действующая авария или предупреждение
out_bNewFault С момента квитирования появилась новая авария
out_bNewWarning С момента квитирования появилось новое предупреждение
out_bNewSignal Есть неквитированная новая авария или предупреждение

New… — не импульс на один цикл. Эти признаки запоминаются до квитирования. Они могут оставаться включёнными даже после исчезновения причины события.

При квитировании действующая авария остаётся на out_bFault, но её признак out_bNewFault сбрасывается. Если позже появится другое аварийное условие или прежнее сначала исчезнет, а затем возникнет снова, признак новой аварии включится повторно. Событие, впервые обнаруженное в том же цикле, что и команда квитирования, также может включить его.

Условия Alm не включают ни один из этих шести сводных выходов. Их отдельные состояния при этом формируются и передаются в View.

Для отображения генератор создаёт копии сводных выходов, например View.Alarms_Inst_out_bFault и View.Alarms_Inst_out_bNewSignal. В самом PLC-коде удобно обращаться непосредственно к Alarms_Inst.

5. Подключите свет и звук

Пусть bAlarmLamp и bHorn — логические выходы лампы и звукового сигнализатора. Объявите их в GVL:

st
bAlarmLamp : BOOL := FALSE;
bHorn : BOOL := FALSE;

В коде проектного компонента, который управляет сигнализацией, запишите:

st
bAlarmLamp := Alarms_Inst.out_bSignal;
bHorn := Alarms_Inst.out_bNewSignal;

Лампа горит, пока действует хотя бы одна авария или предупреждение. Звук включается при новом событии и остаётся включённым до квитирования. Если нужны отдельные лампы аварии и предупреждения, используйте соответственно out_bFault и out_bWarning.

Связь логических выходов с физическими каналами выполняется маппингом. Сам Alarms не назначает адреса выходов ПЛК.

В сгенерированном основном блоке проектные компоненты вызываются перед Alarms. Поэтому приведённые присваивания используют его результаты предыдущего цикла; изменение состояния дойдёт до логических выходов на следующем цикле программы.

6. Квитируйте звук

Пусть bAcknowledgePulse — подготовленная команда от кнопки, активная один цикл. Она должна быть объявлена и сформирована в алгоритме проекта.

В проектном компоненте передайте её так:

st
IF bAcknowledgePulse THEN
    View.Alarms_Inst_inout_bReset := TRUE;
END_IF;

При следующем вызове Alarms обработает команду и сам обнулит поле. Звук выключится, а лампа продолжит показывать действующую аварию. Если причина уже исчезла, лампа будет выключена, а квитирование уберёт оставшееся напоминание звуком.

Используйте именно условную запись TRUE: безусловное присваивание FALSE в эту переменную могло бы стереть команду, записанную другим источником. Удержание команды в каждом цикле также будет постоянно квитировать сигнализацию, поэтому для кнопки здесь используется импульс.

7. Сбросьте запомненную аварию в её источнике

Квитирование звука и сброс аварии — разные действия. Если bSensorFault запомнен алгоритмом или функциональным блоком, команда в Alarms не изменит его.

Сброс направляют туда, где хранится авария. У готового блока это предусмотренный им вход сброса. В собственном алгоритме можно явно описать правило: сброс разрешён после исчезновения причины.

Например, bFaultCause — текущая причина неисправности, а bFaultResetPulse — команда сброса на один цикл. Оба сигнала объявлены и формируются в проекте. Обработка ранее объявленного bSensorFault может выглядеть так:

st
IF bFaultCause THEN
    bSensorFault := TRUE;
ELSIF bFaultResetPulse THEN
    bSensorFault := FALSE;
END_IF;

Пока причина присутствует, авария остаётся. Когда причина исчезнет, bSensorFault сохранит TRUE до команды сброса. Именно этот сигнал проверяет созданное нами условие Flt.

Если та же кнопка должна одновременно квитировать сигнализацию, дополнительно передайте её команду в Alarms:

st
IF bFaultResetPulse THEN
    View.Alarms_Inst_inout_bReset := TRUE;
END_IF;
Действие Результат
Квитировать звук Сбросить признаки New…. Причина и действующая авария сохраняются.
Устранить причину Текущее условие становится нормальным. Запомненная авария источника может ещё требовать сброса.
Сбросить аварию источника Снять её фиксацию по правилам исходного блока или алгоритма. После снятия последней причины сводный выход out_bFault выключится.

Таким образом, строки Data задают, какие состояния нужно учитывать, Alarms собирает общую сигнализацию, а алгоритм каждого механизма определяет причины и правила сброса его аварий. Отображение этих данных и генерацию артефактов HMI рассмотрим отдельно.

Предыдущая глава: ошибки генерации · Оглавление

Первая часть завершена: мы разобрали построение программы из компонента MetaGen, публикацию данных и сигнализацию. Во второй части добавим визуализацию MetaView и сценарии MetaLab, чтобы проверить проект в Runtime с MetaCore.

← 8. Ошибки генерации10. MetaView: визуализация и управление →