пятница, 8 июня 2012 г.

Использование Global Scripts для изменения тегов в WinCC

С помощью Global Scripts выполняются задачи, которые не зависят от того какой из экранов отображается в данный момент и отображается ли вообще какой-либо экран. Также Global Scripts используются для хранения глобальных функций и подпрограмм, доступных для вызова из других скриптов, как глобальных, так и привязанных к экранам.
Рассмотрим использование Global Scripts на примере задачи проверки наличия связи с PLC.

Включение Global Scripts

Для того чтобы Global Scripts работали необходимо активировать Global Scripts Runtime в списке задач проекта. Чтобы это сделать:
  •  выбираем в дереве проекта Computer;
  •  в списке компьютеров с помощью контекстного меню компьютера вызываем окно Computer Properties;
  • на вкладке Startup окна  Computer Properties отмечаем пункт Global Script Runtime.

Создание Action

Функции выполняемые WinCC при срабатывании определенных триггеров называются Actions. Для решения нашей задачи создадим глобальный C-Action, вызываемый периодически с интервалом, например, 1 секунду: 
  • в дереве проекта выбираем Global Script и двойным кликом по C-Editor открываем Global Script C-Editor;
  • с помощью пункта меню File->New Action (Alt-A) создаем Action:
Созданный Action содержит уже некоторый текст, часть которого, включая имя функции, изменить нельзя. Имя нашему Action'у мы дадим при его сохранении. 
Закомментированный текст используется WinCC для создания списка перекрестных ссылок на теги и экраны. Так как в нашей задаче изменять состояние экранов не требуется, соответствующую секцию кода мы удалим. 

Метод 1: Проверка состояния тега

Состояние связи с ПЛК будем определять по состоянию любого тега, участвующего в обмене с контроллером. 

#include "apdefap.h"

int gscAction( void )
{
// WINCC:TAGNAME_SECTION_START
// syntax: #define TagNameInAction "DMTagName"
// next TagID : 1
#define someTag "bkd_mode"
#define PLC_online "PLC_online"
// WINCC:TAGNAME_SECTION_END
    DWORD state;
    GetTagBitState(someTag, &state);    
    SetTagBit(PLC_online, !state);
    return 0; 
}

В данном примере мне попался под руку дискретный тег с именем "bkd_mode".
Состояние дискретного тега можно узнать с помощью внутренней функции GetTagBitState. Эта функция с помощью второго аргумента возвращает 0 при наличии связи и 1 при отсутствии. Само значение тега в данном случае нас не интересует. 
Состояние связи с контроллером  (0 - связь отсутствует, 1 - присутствует) сохраняем в предварительно созданном теге "PLC_online" c помощью функции SetTagBit.
Теперь зададим триггер для вызова нашего Action. Делается это в окне, вызываемом с помощью кнопки Info/Trigger (на ней изображен будильник) на панели инструментов редактора. На вкладке Trigger выбираем Cyclic и с помощью кнопки Add добавляем триггер 1s:
Компилируем скрипт с помощью кнопки Compile (справа от будильника) на панели инструментов редактора и сохраняем его. На предупреждение выданное в результате компиляции не обращаем внимания. 
В данный момент, если проект был активным, наш скрипт уже выполняется. В противном случае проект нужно активировать.
Испытав скрипт на практике приходим к следующим выводам:
  • данный способ работоспособен (были сомнения), и при этом не требует вносить изменения в программу ПЛК;
  • время обнаружения потери связи в случае проблем с оборудованием  компьютера (я отключал сетевую карту) составляет несколько секунд, что вполне приемлемо;
  • время же обнаружения потери связи при выключении контроллера в моем случае (ПЛК Quantum, протокол связи Modbus TCP) составило 25 секунд - хотелось бы поменьше.

Метод 2: Проверка изменения значения тега

Попробуем другой подход, для реализации которого придется внести изменения в программу контроллера. Создадим в контроллере числовую переменную, которую будем изменять достаточно быстро (я увеличивал значение переменной на единицу каждый скан), а в скрипте будем проверять изменилась ли она за прошедшее с предыдущего вызова скрипта время.

#include "apdefap.h"

int gscAction( void )
{
// WINCC:TAGNAME_SECTION_START
// syntax: #define TagNameInAction "DMTagName"
// next TagID : 1
#define PLC_tics "PLC_tics"
#define PLC_online "PLC_online"
// WINCC:TAGNAME_SECTION_END
    static int oldTics;
    int curTics = GetTagWord(PLC_tics);
    if(oldTics == curTics) SetTagBit(PLC_online, 0);
    else{
        SetTagBit(PLC_online, 1);
        oldTics = curTics;
    }
    return 0; 
}

Тег, значение которого мы проверяем, я назвал "PLC_tics", тип его - 16-битное целое число со знаком. Значение этого тега мы получаем с помощью функции GetTagWord.
Предыдущее значение тега хранится в статической переменной oldTics (статические переменные не изменяют своего значения между вызовами функции, в которой они определены). 
Сравнивая работу данного скрипта с предыдущим можно заметить:
  • время обнаружения проблем со связью со стороны контроллера стало значительно меньше и составляет 2-3 секунды;
  • для его работы необходимо изменение программы устройства, что не всегда возможно;
  • для проверки наличия связи необходимо,  чтобы контроллер не был остановлен, иначе скрипт просигнализирует об отсутствии связи, что, строго говоря, не всегда верно;
  • при увеличении интервала обновления тегов коммуникационной подсистемой WinCC возможны ложные срабатывания (лечится увеличением периода вызова скрипта).
WinCC V7.0+SP3

Комментариев нет:

Отправить комментарий