PDA

Просмотр полной версии : Как правильно эмулировать работу контроллеров?



koceg
29.09.2015, 17:56
Здравствуйте.
Недавно начал разбираться с MasterSCADA и MasterOPC - создал небольшой проект по управлению задвижкой.

Работу контроллеров, разумеется, нужно как-то эмулировать. Я попробовал сделать это в самом OPC-сервере - сделал все теги SERVER_ONLY и пытаюсь изменить их значения при помощи скриптов.

Всего у меня 4 тега - Открыта, Закрыта, Открыть и Закрыть, все дискретные. Я хочу, чтобы при выполнении команды Открыть или Закрыть, индикаторы Открыта и Закрыта сначала сбрасывались (чтобы отобразить процесс в MasterSCADA), а потом через несколько секунд устанавливался нужный индикатор. Использую вот такой код:


function sleep(s)
local ntime = os.time() + s
repeat until os.time() > ntime
end

function setOpenIndicator(v)
server.WriteTag("Насосная станция.Клапан 1.Kl1_IndO", v, OPC_QUALITY_GOOD);
end

function setClosedIndicator(v)
server.WriteTag("Насосная станция.Клапан 1.Kl1_IndC", v, OPC_QUALITY_GOOD);
end

function OnWrite()
TV, TQ, TS = server.ReadCurrentTag();

if TV then
server.Message("КЛ1: Открывается");

server.RunFunctionFromDevice("setOpenIndicator", 0, false);
server.RunFunctionFromDevice("setClosedIndicator", 0, false);

sleep(3);

server.RunFunctionFromDevice("setOpenIndicator", 0, true);

server.Message("КЛ1: Открыт");
end
end

Проблема в том, что код сброса значений (перед sleep) игнорируется - индикаторы не меняют свои значения. А вот код после sleep отрабатывает нормально. Сообщения при этом в консоль выводятся, sleep работает корректно.

В чем может быть проблема? Можно ли мою задачу решить какими-то другими способами?

SCADAMaster
29.09.2015, 19:09
1. Если хотите сделать задержку выполните команду server.Sleep
2. Если вызываете функцию в пределах одного скрипта, то она вызывается просто по имени, без RunFunctionFromDevice

koceg
29.09.2015, 19:13
1. Если хотите сделать задержку выполните команду server.Sleep
То есть проблема именно в этом или это просто общая рекомендация?


2. Если вызываете функцию в пределах одного скрипта, то она вызывается просто по имени, без RunFunctionFromDevice
Я упростил, функции лежат в разных скриптах.

UPD: Команда server.Sleep (которая, кстати, не документирована и принимает задержку в миллисекундах) проблему, к сожалению, не решила.

SCADAMaster
29.09.2015, 20:12
Приложите конфигурацию ОРС сервера

koceg
29.09.2015, 20:34
Приложите конфигурацию ОРС сервера
Готово, залил архив.

SCADAMaster
29.09.2015, 21:56
Дело в задержке - использовать ее для подобных целей нельзя, так как значения присваиваются когда завершится выполнение скрипта.
Вам нужно взводить тег, а сбрасывать его уже из скрипт после чтения - считать такты например, и по ним выключать скрипт.

koceg
01.10.2015, 12:16
А если запустить-таки симулятор и реализовать эту же логику, но не при помощи server.WriteTag, а используя функции пакета modbus? Запись в симулятор тоже будут выполняться при завершении скрипта?

SCADAMaster
01.10.2015, 13:08
Не играет роли - обновление тегов произойдет только в конце скрипта.
Но вы можете управлять тегами другого узла - поскольку это отдельный поток, то там теги будут обновляться сразу (в собственном цикле).

koceg
01.10.2015, 13:31
Не играет роли - обновление тегов произойдет только в конце скрипта.
Но вы можете управлять тегами другого узла - поскольку это отдельный поток, то там теги будут обновляться сразу (в собственном цикле).
Вынос этой логики из тегов на уровень выше, в устройство, решил проблему. Спасибо за ваши ответы, вы мне очень помогли.
Приложу работающий пример, вдруг кому-нибудь пригодится.