В последнее время большое распространение в АСУТП получили HMI панели Weintek. Я хочу рассказать о создании динамических окон в программных проектах для этих панелей.
Динамические окна - нужный инструмент для работы с большим количеством однотипного оборудования.
Предположим, у вас на установке 10 одинаковых насосов и вам нужно вызывать для работы с ними окно с кнопками и индикаторами.
Можно сделать 10 одинаковых окон.
Но если потребуется что-то в них изменить (и не один раз), то время работы над проектом возрастает.
На помощь приходят динамические окна - Indirect (косвенные) window, как они называются в панелях Weintek.
Способ их создания следующий.
Начальные условия:
Вы умеете работать с программой EasyBuilder Pro (в дальнейшем для краткости – EB), умеете добавлять окна, располагать на них компоненты и менять свойства у этих компонентов.
Вы знаете, что такое MODBUS TCP и как с ним бороться.
Установлена программа EasyBuilder Pro v6.06.01.446 Build 2021.10.07.
Создан проект EasyBuilder для панели типа XE Series – MT8121XE/ MT8150XE.
Предполагается, что панель соединена с ПЛК по MODBUS TCP (в дальнейшем для краткости – МТСР), а ПЛК, в свою очередь управляет двумя насосами – Р-1 и Р-2, и считывает их состояния. Управление производится одним битом – 1-включить, 0 отключить.
В проекте Weintek в ЕВ создано устройство (Local Device) MODBUS TCP/IP.
Регистры MTCP в ПЛК:
Управление Р-1 – 0х1 (Coil)
Состояние Р-1 – 0х2
Управление Р-2 – 0х3
Состояние Р-2 – 0х4.
Принцип работы с динамическим окном следующий.
Создаётся одно окно с элементами индикации и управления. В этом окне запускается макрос, который выполняет обмен между элементами индикации и управления и ПЛК по MTCP.
Но адреса, откуда читать и куда писать по MTCP, в это окно передаются разные при разных вызовах этого окна.
Передача адресов осуществляется через слова LW10 и LW11.
Теперь займёмся этим практически.
При создании нового проекта в ЕВ создаётся окно WINDOW_010. В нём и будем вызывать динамическое окно.
Одно окно у нас уже есть - WINDOW_010. Создадим ещё одно окно – PUMP_CONTROL (название значения не имеет, просто для ясности), размером 300х200. Запоминаем номер окна PUMP_CONTROL (допустим, 11).
Добавим в окно WINDOW_010 компонент «Indirect window».
Indirect window – это по сути рамка для другого существующего в проекте окна, которое будет в нём отображаться. Содержимое слова LW0 «Address» в свойствах – это номер окна. Окно с этим номером вызывается при изменении LW0.
Добавим компонент-кнопку Combo Button, для вызова окна управления насосом Р-1.
Это кнопка, которая выполняет сразу несколько функций.
В открывшемся окне свойств Combo Button добавляем 3 функции Set Word:
Local HMI LW0 = 11 (это номер окна PUMP_CONTROL),
Local HMI LW10 = 1 (адрес регистра MTCP для управления Р-1),
Local HMI LW11 = 2 (адрес регистра MTCP состояния Р-1).
Добавляем ещё одну кнопку Combo Button, для вызова окна управления насосом Р-2. Значения будут немного другими:
Local HMI LW0 = 11 (это номер всё того же окна PUMP_CONTROL),
Local HMI LW10 = 3 (адрес регистра MTCP для управления Р-2),
Local HMI LW11 = 4 (адрес регистра MTCP состояния Р-2).
Создаём в проекте макросы.
Макрос macro_LW_reset – для сброса LW0 при закрытии окна PUMP_CONTROL, чтобы его можно было открыть ещё раз.
//Сброс слова LW0 при закрытии окна "Включение/отключение блокировки"
macro_command main()
int Tag_0 = 0
SetData(Tag_0, "Local HMI", LW, 0, 1)
end macro_command
Макрос macro_MODBUS – читает и пишет по MTCP биты управления и состояния.
//Чтение состояния и управление насосом
macro_command main()
bool Lamp = 0
bool Button = 0
int Control_reg_addr = 0 //АДРЕС регистра для управления насосом
int State_reg_addr = 0 //АДРЕС регистра состояния насоса
//Управление
//Читаем АДРЕС регистра для управления насосом
GetData(Control_reg_addr, "Local HMI", LW, 10, 1)
//Считываем нажатие кнопки ПУСК или СТОП в переменную Button
GetData(Button, "Local HMI", LB, 0, 1)
//Записываем значение переменной Button в бит управления по адресу, прочитанному из LW10
SetData(Button, "MODBUS TCP/IP", 0x_single_Bit, Control_reg_addr, 1)
//Состояние
//Читаем АДРЕС регистра состояния насоса
GetData(State_reg_addr, "Local HMI", LW, 11, 1)
//Читаем в переменную Lamp бит состояния насоса по адресу, прочитанному из LW11
GetData(Lamp, "MODBUS TCP/IP", 0x_single_Bit, State_reg_addr, 1)
//Записываем значение переменной Lamp в LB1
SetData(Lamp, "Local HMI", LB, 1, 1)
end macro_command
Теперь займёмся тем окном, которое будем вызывать – PUMP_CONTROL.
Добавим кнопки ПУСК и СТОП, лампочку, показывающую состояние насоса и функциональную кнопку (Function key) для закрытия окна.
У кнопок ПУСК и СТОП один и тот же адрес – Local HMI LB0, но разные функции:
ПУСК – Set ON, СТОП – Set OFF.
У лампочки адрес Local HMI LB1.
У функциональной кнопки выберем функцию работы с окнами – Close window.
В свойствах окна назначим макросы –
Cycle – macro_MODBUS – циклическое выполнение, пока окно открыто,
Close – macro_LW_reset – выполняется при закрытии окна.
Вот, собственно, и всё.
Для проверки запускаем Online Simulation (нужно иметь какой-нибудь Modbus Slave) и проверяем, как работает.