Вопросы по скриптам в Simple-Scada 2

Автор Simple-Scada, 29 января 2016, 15:19:20

st-legal

Добрый день уважаемые форумчане. У меня такой вопрос: связал Simple Scada с модулем МК110-8ДН.4Р через Овен ОРС сервер для приборов модбас. В проекте создал 4 кнопки для управления выходами модуля. Вопрос в следующем. При нажатии кнопок с некоторой задержкой все отрабатывает нормально, но стоит нажать 2 кнопки без паузы, отрабатывает только тот выход, кнопка которого была нажата последней. Кнопки привязаны к одному тегу, но через разные биты. В чем может быть проблема? И вопрос номер два, помогите с написанием скрипта для одновременного активирования всех 4 выходов от одной кнопки. За ранее спасибо

Teodor

Есть такая штука с блокированием переменной до получения ответа от сервера. Я ее поборол, но объяснить будет сложно и наверно есть пути попроще. :)
Суть мысли. При нажатии кнопки устанавливается бит ВНУТРЕННЕЙ переменной и ставитя в TRUE еще одна ВН. переменная(флаг обновления данных). Дальше секундный скрипт проверяет состояние второй переменной. Если она TRUE, и значение ВН. переменной отличается от внешней, то значение внутренней присваивается внешней, если они равны, то флаг скидывается.

Если вы ткнете быстро 1 кнопку, то вн. переменная примет значение 1(0х0001), и отдаст это значение внешней. Потом вы жмете 2 и 3... Вн. переменная уже равна 7 (0х0111), а внешней присвоить пока не удается и она еще равна 1, значит флаг еще висит и через секунду опять пытаемся записать, и так пока не удасться и флаг не скинется.

Как-то так.  :-\

st-legal

Спасибо большое, для меня пока сложновато это все переварить... Буду копать дальше..

st-legal

#348
Ув. Teodor, а можно Вас попросить кусочек скрипта который вы описали?

Teodor

#349
Цитата: st-legal от 08 июня 2017, 15:34:38Спасибо большое, для меня пока сложновато это все переварить... Буду копать дальше..
Например, пишем по 2 температуры в 1 регистр(DW). Но с учетом того, что они могут изменится и снаружи, потому есть еще одна "лишняя" переменная. Процедурой т.к. там этих строк еще много есть, а процедура одна на всех.
Надеюсь поможет.
Код: pascal
procedure WriteTemp(VarOPC, VarIn, VarOut, Temp1, Temp2, Change :TM_Variable);
  begin
  if VarOPC.IsGoodQuality = true then begin
    VarIn.Value := VarOPC.Value;
  end;
  if (VarIn.AsInt <> VarOut.AsInt ) and (Change.AsBool = false) then
  begin
    Temp1.Value:= (VarIn.Value and 8191);
    Temp2.Value:= ((VarIn.Value shr 16) and 8191);
  end;

  if (VarIn.AsInt  <> VarOut.AsInt ) and (Change.AsBool  = True) then
  VarOPC.Value := VarOut.Value;

  if (VarIn.AsInt = VarOut.AsInt) and (Change.AsBool = True) then
  Change.Value  := false;
end;

begin
WriteTemp(TempSet2_1 ,SetTempBathIn1 ,SetTempBathOut1 ,SetBathTemp_1 ,SetTambourTemp_1,Change2_1 );      
...........
а тут скрипт для кнопки. Тег у каждой свой, чтобі не писать 100500 скриптов просто перебирам в кейсе кто именно обратился.
Код: pascal
begin
case Sender.Tag of
1:  begin
       SetTempBathOut1.Value := SetBathTemp_1.Value*10 + (SetTambourTemp_1.Value SHL 16)*10;
       Change2_1.Value  := True;
      end;
.....
end;
end.    
вам, наверно от него можно просто оставить:
Код: pascal
begin
  ChangeХХ.Value  := True;
end.
т.к. значение переменной изменяется самой кнопкой.

st-legal

#350
Спасибо Вам огромное, буду пробовать...

Teodor

#351
Цитата: st-legal от 08 июня 2017, 16:00:08Спасибо Вам огромное, буду пробовать...
Не надо!!!
Все намного проще :) Например Секундный скрипт:
Код: pascal
if IntVar1.Value <> ExtVar.Value then
  ExtVar1.Value := IntVar.Value;
Тогда скада раз в секунду будет проверять есть ли расхождения, и если есть, то пробовать писать.

По кнопке с несколькими выходами просто подцепляете скрипт на клик и делаете ее НЕ фиксируемой:
Код: pascal
  IntVar.Value := 15; (* 0х00001111 или какие там у вас биты*)

st-legal

#352
Спасибо, ув. Teodor, все работает как часы... ;D

Simple-Scada

#353
st-legal, Teodor, извините, но вы сделали какой-то переполох на ровном месте и просто усложнили. Можно обойтись без секундного скрипта и лишних проверок.

ЦитироватьВопрос в следующем. При нажатии кнопок с некоторой задержкой все отрабатывает нормально, но стоит нажать 2 кнопки без паузы, отрабатывает только тот выход, кнопка которого была нажата последней. Кнопки привязаны к одному тегу, но через разные биты. В чем может быть проблема?
В данной ситуации нет никакого блокирования переменных и дело только в работе с битами одной и той же переменной. Всё очень просто. Присвоение внешних переменных происходит не моментально, а с какой-то задержкой. Вот последовательность шагов:
  • переменная равна нулю;
  • пользователь нажал кнопку;
  • скада посылает OPC-серверу запрос на запись в тег единицы;
  • OPC-сервер выполняет присвоение;
  • скада получает результат (единицу).
Начиная с шага 2, до шага 5 сервер скады будет думать, что переменная равна нулю. И только на 5 шаге сервер получит значение, равное 1. Вот и всё.

Теперь конкретнее про биты. Есть две кнопки. Обе связаны с переменной vrBit. Первая кнопка работает с нулевым битом. Вторая кнопка - с первым. Тогда, если быстро кликнуть первую и вторую кнопку, может произойти следующая ситуация:
  • сначала переменная vrBit, равна нулю (x0000);
  • пользователь нажал кнопку 1. Скада берёт текущее значение vrBit, т.е. 0 (x0000), меняет в нём нулевой бит на 1 (x0001) и отправляет полученное значение на OPC-сервер, для присвоения. Сервер скады всё ещё хранит в vrBit значение 0 (x0000);
  • пользователь нажал кнопку 2. Скада берёт текущее значение vrBit, т.е. 0 (x0000), меняет в нём первый бит на 1 (x0010) и отправляет полученное значение на OPC-сервер, для присвоения. Сервер скады всё ещё хранит в vrBit значение 0 (x0000);
  • OPC-сервер получил два запроса, первый на присвоение x0001, второй на присвоение x0010. Он выполняет их последовательно и в переменной оказывается значение x0010, которое в результате передается скаде.

Для решения этого вопроса можно сделать синхронизацию через внутреннюю переменную. Т.е., дано: наша внешняя переменная в которой нужно менять биты. Она называется vrMy. Мы создаем ещё одну внутреннюю переменную с именем vrSync. Связываем обе кнопки с переменной vrSync. Также у этих кнопок в качестве доп. переменной выбираем vrMy. Пишем следующий универсальный скрипт:

Код: pascal
begin
  if not (Sender is TM_Object) then Exit;
  with Sender as TM_Object do
    if (Variable <> nil) and (VariableEx <> nil) then 
      VariableEx.Value := Value;
end.

Теперь ставим данный скрипт на событие OnDataChange у наших кнопок (причем этот скрипт подойдет для всех подобных кнопок в проекте). Готово. Теперь кнопки работают с внутренней переменной и присвоения выполняются моментально, поэтому проблемы с битами нет. При этом все изменения отправляются во внешнюю переменную.

st-legal

#354
Спасибо уважаемые разработчики за столь развернутый ответ и помощь!!

Teodor

#355
Не, ну я ж предупреждал что, возножно, я не прав и есть способы попроще. Под блокировкой имел в виду именно то что переменная приобретет заданное значение только после подтверждения от ОРС.

А можете теперь все то-же расписать, но с условием, что ExtVar может измениться "с той стороны"? Например есть еще один сервер работающий с тем-же регистром и нам надо переключить кнопки в актуальное положение? При том что щелкать по ним могут фактически одновременно. :-\

xrusteg

#356
Добрый день, только начала разбираться со скадой, возник такой вопрос. Необходимо проверять связь с контроллером. Делаю это таким способом:
Код: pascal
begin
  if sysUpTime_0.IsGoodQuality = False then
    AddMessage(Now, mkAlarm, 'Потеря связи с контроллером!', True, True);
end.
Но проблема в том, что не знаю к какому событию привязать данный скрипт, если привязать к посекундному, то каждую секунду будут появляться сообщения, что неправильно. К чему еще можно привязать данный скрипт?

Teodor

А если сделать булевую переменную, привязанную к кнопке(без флага "Доступно") "OnLine"

Oдин скрипт секундный для проверки качества и установки переменной, второй привязан к ОнЧенж кнопки уже показывает сообщение если флаг в Тrue?

xrusteg

Спасибо за ответ. Работает, но костыльно и, получается, каждый раз после срабатывания нужно нажимать кнопку. Кстати, а как сделать, чтобы при появлении связи сообщение автоматически убиралось?

st-legal

Добрый день, ув. форумчане. Помогите разобраться с таблицами. Есть переменная (счетчик), которая записывается в базу данных mysql. Стоит задача: вывести значение счетчика накопленное за час и общее количество за сутки. Т.е. в таблице 24 строки (для каждого часа) и столбец со значением счетчика. значение счетчика передается из контроллера в формате word. И еще как организовать перезапись данных в таблице, значения, полученного в этом же часу но днем раньше??? За ранее спасибо