Чтобы отправить новое значение слейву. Если использовать только одну переменную, то значение, которое получим от слейва, может затереть то значение, которое ввёл оператор.
Ещё конкретнее. Прямо совсем конкретно. Температура там, скорость.
У вас панели оператора или СПК? В панелях оператора, с которыми я работал, эта сихронизация выполняется на системном уровне. СПК -- это не панель оператора.
С СПК110 я работал.
А вот с этим поподробнее, пожалуйста! Как отследить завершение ввода нового значения с помощью Slider'а, Checkbox'а, Potentiometr'a и т.п. Я ведь не зря написал "В общем случае". Даже поймать закрытие диалога недостаточно, если обмен выполняется в параллельной задаче.
Тут я немного сдамся. Дело в том, что я избегаю таких элементов на главных экранах. Любые реальные действия — только через диалоги. На экранах только навигация и вызов диалогов. Ну, подробнее так подробнее...
Вот экранчик на СПК110 в конструкторе и при исполнении:
desginer.png manual_overview2.png
Там есть вот эти поля:
input.png
Это температурная уставка. Её текущее значение всегда и постоянно берётся со слейва (ПЛК110) без дополнительных условий. Переменная heaterSetpoint это просто результат разбора содержимого регистров слейва:
heaterSetpoint.png
В событиях этого поля ввода творится следующее:
ondialogclosed.png
То есть при вызове диалога запоминается команда «Установить температуру». При закрытии диалога эта команда передаётся на ПЛК вместе с уставкой. Ну то есть как передаётся... У меня первые три регистра отведены под команду: соответственно, код команды, аргумент 1 и аргумент 2. Остальные регистры отведены на передачу показаний с контроллера-слейва на панели. Тут тоже ничего хитрого — контроллер натыкается на команду «установить температуру», меняет какие-то свои внутренние переменные и заодно выставляет новое значение регистра, из которого СПК показывает значение уставки.
А главная хитрость в том, что значение из диалога пишется не в ту переменную, которая идёт от слейва, а в другую:
another_var.png
То есть результат ввода запоминается для отправки, потом отправляется вместе с так же запомненной командой и в считанные миллисекунды актуальное значение оказывается в переменной heaterSetpoint обеих панелей.
SendPlcCmd вот:
Код:
FUNCTION SendPlcCmd : BOOL
VAR_INPUT
Cmd: SCommand;
Arg0, Arg1: WORD;
END_VAR
IF CMD_CTRL.cmdCount < 51 THEN
CMD_CTRL.cmdQueue[CMD_CTRL.cmdCount][0] := Cmd;
CMD_CTRL.cmdQueue[CMD_CTRL.cmdCount][1] := Arg0;
CMD_CTRL.cmdQueue[CMD_CTRL.cmdCount][2] := Arg1;
CMD_CTRL.cmdCount := CMD_CTRL.cmdCount + 1;
END_IF
CMD_CTRL вот:
Код:
PROGRAM CMD_CTRL (* Sends commands to the PLC *)
VAR_INPUT
Cmd, Arg0, Arg1: WORD;
cmdQueue: ARRAY[0..50] OF ARRAY [0..2] OF WORD;
cmdCount: INT;
END_VAR
VAR
Checksum: WORD;
Pulse: TON := (PT := T#300MS);
tx: BOOL;
cmdIdx: INT;
edge: R_TRIG;
END_VAR
(* Command conveyor, up to 50 commands in queue *)
tx := FALSE;
edge(CLK := cmdCount > 0);
Pulse(IN := NOT Pulse.Q AND cmdCount > 0);
IF (Pulse.Q OR edge.Q) AND cmdIdx < cmdCount THEN
Cmd := cmdQueue[cmdIdx][0];
Arg0 := cmdQueue[cmdIdx][1];
Arg1 := cmdQueue[cmdIdx][2];
Checksum := Cmd + Arg0 + Arg1;
tx := TRUE;
cmdIdx := cmdIdx + 1;
ELSIF Pulse.Q THEN
Cmd := 0;
cmdIdx := cmdCount := 0;
END_IF
В конфигурации ничего хитрого:
cmd0.png cmd1.png