There are many things to improve in your code. For instance:
IF REQUEST_DEVICES_ARR[COUNT] = TRUE THEN
DEVICES_TO_ON := DEVICES_TO_ON + 1;
END_IF;
Это бессмысленно, потому что сразу после него вы переопределяете DEVICES_TO_ON
и не используете его. Так зачем ты это установил?
Или вы делаете это
IF POWER_REQUEST > NUM_DEV_ON THEN
DEVICES_TO_ON := POWER_REQUEST-NUM_DEV_ON;
DEVICES_TO_OFF := 0;
END_IF;
Но нигде, прежде чем установить NUM_DEV_ON
.
Или у вас есть входная переменная NUMBER_DEVICES
, но нигде в коде она не используется.
Но, как правило, вы выбрали неправильный подход к проблеме.
Итак, прежде всего, вы должны создать тип
TYPE MY_DEVICE: STRUCT
Available: BOOL; (* If a device is available *)
State: BOOL; (* Current device state *)
Queue: BOOL; (* What to do with device *)
END_STRUCT
END_TYPE
Затем установите глобальные переменные
VAR_GLOBAL
garDevices: ARARY[1.._DEVICE_NUM] OF MY_DEVICE; (* Comment *)
END_VAR
VAR_GLOBAL CONSTANT
_DEVICE_NUM: USINT := 6; (* Comment *)
END_VAR
Таким образом, вы можете изменить количество устройств, просто изменив _DEVICE_NUM
константу без изменения остальной части кода.
Теперь ваша функция
FUNCTION QUEUE_DEVICES: BOOL
VAR_INPUT
ENABLE : BOOL;
POWER_REQUEST : USINT;
END_VAR
VAR
iDeviceOnOff: INT;
usiCount: USINT;
usiCountOnDevices: USINT;
END_VAR
(* If not enabled, set all devices to turn off and quite function *)
IF NOT ENABLE THEN
FOR usiCount TO _DEVICE_NUM DO
garDevices[usiCount].Queue := FALSE;
END_FOR;
RETURN;
END_IF;
(* Count how many devices is on already *)
usiCountOnDevices := 0;
FOR usiCount := 1 TO _DEVICE_NUM DO
IF garDevices[usiCount].State THEN
usiCountOnDevices := usiCountOnDevices + 1;
END_IF;
END_FOR;
(* Find the difference between power request and power on.
Might be negative or positive *)
iDeviceOnOff := POWER_REQUEST - usiCountOnDevices;
FOR usiCount := 1 TO _DEVICE_NUM DO
(* If device is not available for turning on or off
continue to the other device *)
IF garDevices[usiCount].Available THEN
(* if iDeviceOnOff is positive, then we have to turn on devices *)
IF iDeviceOnOff > 0 AND NOT garDevices[usiCount].Queue THEN
garDevices[usiCount].Queue := TRUE;
iDeviceOnOff := iDeviceOnOff - 1;
END_IF;
(* if iDeviceOnOff is negative we have to turn OFF devices *)
IF iDeviceOnOff < 0 AND garDevices[usiCount].Queue THEN
garDevices[usiCount].Queue := FALSE;
iDeviceOnOff := iDeviceOnOff + 1;
END_IF;
(* If iDeviceOnOff is 0 means balance is reached *)
IF iDeviceOnOff = 0 THEN
EXIT;
END_IF;
END_IF;
END_FOR;
END_FUNCTION
Затем вы можете добавить некоторые другие тесты в конце функции. Например.
IF iDeviceOnOff > 0 THEN
_ERROR: = 'More power requested than available devices';
END_IF;
IF iDeviceOnOff < 0 THEN
_ERROR: = 'There is a power excess';
END_IF;