PDA

Просмотр полной версии : Маскарадное программирование ПЛК %)



Yegor
04.04.2013, 11:54
Смарите посоны чо я выдумал...


Вместо подписывания в конфигурации каждого выхода берём их всех как битовую маску D_OUTS.
В разделе глобальных констант делаем ещё кучу масок для всех выходов отдельно или для их комбинаций. Например, DO3: DWORD := 4 (единичка в третьем разряде).
Теперь вместо DO1 := DO2 := DO3 := TRUE можно писать D_OUTS := DO1 + DO2 + DO3.
Само по себе не намного короче, но это здорово облегчает код когда в автоматическом режиме комбинации выходов на разных шагах сильно меняются. Фишка в том, что на очередном шаге уже не надо сбрасывать то, что включилось на предыдущем. То есть как оно раньше было:
Step1:
DO1 := DO2 := TRUE;

Step2:
DO1 := FALSE;
DO3 := TRUE;А масочным способом можно так:
Step1:
D_OUTS := DO1 + DO2;

Step2:
D_OUTS := DO2 + DO3;Но это ещё цветочки. Вот когда надо постоянно включать-выключать одни и те же комбинации по каким-то условиям, то получается супер-пупер-лаконично и семантично:
Step1:
D_OUTS :=
STEAMER * BOOL_TO_DWORD(temp < 40) +
COOLER * BOOL_TO_DWORD(temp > 60);

Step2:
D_OUTS :=
DECONDENS * BOOL_TO_DWORD(timer.ET < timer.PT);, где STEAMER, COOLER и DECONDENS — маски для двух и более клапанов или иных узлов, работающих по логическим сигналам.

Если ещё ввести примитивную функцию и писать, например, when вместо громоздкого BOOL_TO_DWORD, то совсем лепота:
Step1:
D_OUTS :=
STEAMER * when(temp < 40) +
COOLER * when(temp > 60);

Step2:
D_OUTS :=
DECONDENS * when(timer.ET < timer.PT);Сам в шоке. Код для ПЛК на человеческом английском O_o

Для сравнения этот же по смыслу код в традиционном исполнении:
Step1:
STEAM_IN := STEAM_OUT := temp < 40;
COOLANT_IN := COOLANT_OUT := temp > 60;

Step2:
STEAM_IN := STEAM_OUT :=
COOLANT_IN := COOLANT_OUT := FALSE;
DECOND_OUT := timer.ET < timer.PT;Я уж молчу про «веточный» подход, где многие стали бы огород городить:
Step1:
IF temp < 40 THEN
STEAM_IN := TRUE;
STEAM_OUT := TRUE;
ELSE
STEAM_IN := FALSE;
STEAM_OUT := FALSE;
[...]

Конечно, в масочном подходе свои минусы. Например, трудно выяснять состояние выхода за пределами блока, где он переключается — приходится обращаться к конкретному биту D_OUTS операциями сдвига или вводить ещё кучу констант для нумерации битов. И код становится уродливым если используется более 32 дискретных выходов. Но пригодиться этот метод вполне может. Мне уже пригодился в одном проекте.

Спасибо за внимание.

SBER
04.04.2013, 14:15
Странно куды такое можно на практике применить.
Вот аттракцион с одним циклическим таймером на всех очень добротен, спасибо.
Может какую отдельную тему под такое завести?

Sergey666
06.04.2013, 22:28
Да здравствует Yegor!
Великий изобретатель велосипеда!
Там еще надо писать типа Mask_out.Do0:= ...; .Только если флажок Replace constant в настройках КДС не поставить компилятор заругается.
Реально использовать для передачи битовых адресов на Слэйв(Панель ,ПК).

Yegor
07.04.2013, 06:31
Я вообще-то про возможность писать mask_out := do1, а не mask_out.do1 := ...; Замена констант не требуется.

Sergey666
07.04.2013, 12:22
Ну да,правильно.
Прогрессия 1-2-4-8-16-...
Для включения 16ти выходов надо записать 65535.
Для выключения выхода надо присвоить соотв. DoX:=0 ;
В принципе прикольно ... надо попробовать , если проект надо кому-то отдавать - пусть у него мозги взорвутся.:D
Молодесь ! Yegor. Ти красаучик.