
Сообщение от
melky
Валенок да там сам принцип на смещении бит

. Еще вот
AI! делал классный макрос на 8-мь насосов (ну или оборудования любого), там несложной обвязкой можно было задавать количество, добавить аварии, сделать выбор какие должны быть в работе и т.д. Но блин макрос я перенести в CodeSys не смог. Из-за обратной связи в одном месте, на CDS она не хочет работать так, как предполагает макрос. Вот его бы адаптировать, он кучу подобных задач решает.
Если адаптировать практически "в лоб" - то вот:
Код:
FUNCTION_BLOCK Rotation
VAR_INPUT
dwAvailable : DWORD;
byNumDev: BYTE := 8;
byNeedWork : BYTE;
bRotate : BOOL;
END_VAR
VAR_OUTPUT
dwOut : DWORD;
byInWork : BYTE;
byNextStop : BYTE;
byNextStart : BYTE;
END_VAR
VAR
tx: TIME;
tn: TIME;
dwSelected : DWORD;
dwTempSelected : DWORD;
dwNextSel : DWORD;
ardwMoto : ARRAY [0..31] OF DWORD;
dwMaxMoto : DWORD;
dwMinMoto : DWORD;
dwTmpMoto : DWORD;
i : BYTE;
Q : BOOL;
init: BOOL;
bMemRotate : BOOL;
bSelected : BOOL;
END_VAR
VAR CONSTANT
uiMIN: DWORD := 2147483648;
uiMAX: DWORD := 2147483647;
END_VAR
tx := TIME();
IF NOT init THEN init := TRUE; tn := tx; END_IF;
IF tx - tn >= SEL(Q, t#1s, t#0s) THEN
tn := tn + SEL(Q, t#1s, t#0s);
Q := NOT Q;
END_IF;
dwTempSelected := dwSelected := dwNextSel AND dwAvailable;
byInWork := 0;
dwMaxMoto := 0;
dwMinMoto := uiMIN;
byNextStop := 0;
byNextStart := 0;
dwOut := 0;
IF byNumDev <= 0 THEN byNumDev := 1; END_IF;
IF byNumDev > 32 THEN byNumDev := 32; END_IF;
FOR i := 0 TO byNumDev - 1 DO
bSelected := dwTempSelected.0;
ardwMoto[i] := ardwMoto[i] + BOOL_TO_BYTE(Q AND bSelected);
byInWork := byInWork + BOOL_TO_BYTE(bSelected);
IF dwAvailable.0 THEN
IF bSelected THEN dwTmpMoto := uiMIN;
ELSE dwTmpMoto := 0;
END_IF;
ELSE
dwTmpMoto := uiMAX;
END_IF;
dwTmpMoto := dwTmpMoto OR ardwMoto[i];
IF dwTmpMoto > dwMaxMoto THEN
dwMaxMoto := dwTmpMoto;
byNextStop := i;
END_IF;
IF dwTmpMoto < dwMinMoto THEN
dwMinMoto := dwTmpMoto;
byNextStart := i;
END_IF;
dwTempSelected := SHR(dwTempSelected,1);
dwAvailable := SHR(dwAvailable,1);
END_FOR;
IF byNeedWork > byInWork OR (bRotate AND NOT bMemRotate) THEN dwNextSel := SHL(DWORD#1, byNextStart); END_IF;
bMemRotate := bRotate;
IF byInWork > byNeedWork THEN dwSelected := dwSelected AND (NOT SHL(DWORD#1, byNextStop)); END_IF;
dwOut := dwSelected;
dwNextSel := dwNextSel OR dwOut;