BEGIN
NEW_FLANK:= NEW AND (NOT MEM_NEW);
DEL_FLANK:= DEL AND (NOT MEM_DEL);
ACT_FLANK:= ACT AND (NOT MEM_ACT);
IF NEW_FLANK THEN // HANDLING NEW BUILDED BATCH
FOR i:= 1 TO 99 DO
LIST [101-i]:= LIST[100-i];
END_FOR;
FOR j:= 1 TO 4 DO
LIST [6-j]:= BUILD[5-j];
END_FOR;
BATCHES_IN_LIST:= BATCHES_IN_LIST + 5
END_IF;
IF ACT_FLANK THEN // HANDLING ACTIVATION OF A BATCH
FOR k:= 1 TO 5 DO
ACTIVE [6-k]:= LIST[BATCHES_IN_LIST+k];
END_FOR;
FOR k:= 1 TO 5 DO
LIST[BATCHES_IN_LIST+k]:= 0;
END_FOR;
BATCHES_IN_LIST:= BATCHES_IN_LIST - 5
END_IF;
MEM_NEW:= NEW;
MEM_DEL:= DEL;
MEM_ACT:= ACT;
END_FUNCTION_BLOCK
JesperMP said:Oh, by the way.
In case that the problem is that you cannot get STEP7 to accept that you remove the square brackets, then the reason is that the input_output of the FC and the DB list is formatted differently.
If succesful, "BATCH_LIST".LIST will be accepted, and you can see that it is really a pointer, not an ANY pointer. So STEP7 seems to check both data types and length.
FUNCTION_BLOCK FB80
VAR_INPUT
NEW: BOOL;
DEL: BOOL;
ACT: BOOL;
END_VAR
VAR_IN_OUT
ACTIVE: ARRAY[1..5] OF DINT; // ACTIVE BATCH
LIST: ARRAY[1..100] OF DINT; // FIFO BATCHLIST
BUILD: ARRAY[1..5] OF DINT; // BUILD BATCH
END_VAR
VAR // MEMORY
MEM_NEW: BOOL;
MEM_DEL: BOOL;
MEM_ACT: BOOL;
BATCHES_IN_LIST: INT;
END_VAR
VAR_TEMP
NEW_FLANK: BOOL; // TEMP MEMORY
DEL_FLANK: BOOL;
ACT_FLANK: BOOL;
i: INT;
j: INT;
k: INT;
END_VAR
BEGIN
NEW_FLANK:= NEW AND (NOT MEM_NEW);
DEL_FLANK:= DEL AND (NOT MEM_DEL);
ACT_FLANK:= ACT AND (NOT MEM_ACT);
IF NEW_FLANK THEN // HANDLING NEW BUILDED BATCH
FOR i:= 1 TO 95 DO
LIST [101 - i]:= LIST[96 - i];
END_FOR;
FOR j:= 1 TO 5 DO
LIST [6 - j]:= BUILD[6 - j];
END_FOR;
BATCHES_IN_LIST:= BATCHES_IN_LIST + 5;
END_IF;
IF ACT_FLANK THEN // HANDLING ACTIVATION OF A BATCH
FOR k:= 1 TO 5 DO
ACTIVE [6 - k]:= LIST[BATCHES_IN_LIST + k];
END_FOR;
FOR k:= 1 TO 5 DO
LIST[BATCHES_IN_LIST + k]:= 0;
END_FOR;
BATCHES_IN_LIST:= BATCHES_IN_LIST - 5;
END_IF;
MEM_NEW:= NEW;
MEM_DEL:= DEL;
MEM_ACT:= ACT;
END_FUNCTION_BLOCK
FOR index:= NoOfListEntries TO 2 BY -1 DO
"BATCH".List[index].Number := "BATCH".LIST[index-1].Number ;
"BATCH".List[index].Length := "BATCH".LIST[index-1].Length ;
"BATCH".List[index].Width := "BATCH".LIST[index-1].Width ;
END_FOR;
JesperMP said:Hi combo.
I am not ging to try and understand your code.
I dont have the time, and even if I had, I think you have some bad coding habits that makes your code almost unreadable.
First, please dont write variables with capitals only !
And somehow I think there is some structure behind that you have different code for different areas of the arrays, but it is impossible to know for an outsider. I would create the structure that matches these differencs, and not hide it behind some constants you need to know.
For example, to push the list one step forward, I would do:
FOR index:= NoOfListEntries TO 2 BY -1 DO
"BATCH".List[index].Number := "BATCH".LIST[index-1].Number ;
"BATCH".List[index].Length := "BATCH".LIST[index-1].Length ;
"BATCH".List[index].Width := "BATCH".LIST[index-1].Width ;
END_FOR;
This is simpler and much more readable.
It is also more maintainable. If you change the structure, by adding a new parameter for example, the code only has to be modified by adding the new parameter, and you dont have to know how to change some constants to some other constants.
FOR i:= 1 TO 95 DO
LIST [101 - i]:= LIST[96 - i];
END_FOR;
FOR j:= 1 TO 5 DO
LIST [6 - j]:= BUILD[6 - j];
END_FOR;
JesperMP said:With the FOR loop you can specify the start, end and step.
So assuming you want to do something with the last entry and move backwards to the start, you have to step one entry backwards for each loop. That accounts for the "-1". The rest I think you can figure out easily.
edit: In your own code there is some nasty programming that does the same I think:
FOR i:= 1 TO 95 DO
LIST [101 - i]:= LIST[96 - i];
END_FOR;
FOR j:= 1 TO 5 DO
LIST [6 - j]:= BUILD[6 - j];
END_FOR;
.Number, .length and .width are just examples on the structure you can manipulate.
My code assumes that you have made a DB with a UDT like we described before.
Example:
UDT "List_entry" is
.Number DINT
.Length REAL
.Width REAL
DB "BATCH" is
.EDIT "List_entry"
.ACTIVE "List_entry"
.REPORT "List_entry"
.LIST ARRAY[1..99] of "List_entry".
My point is that the code gets more readable if you define structures symbolically.
edit: My code is not an exact solution to your problem. It is merely an example of handling datas in SCL. But I think you can get the idea to write easily understandable code that does what you want.
// You have to assign following symbols to blocks of your choise.
// UDT "JOB_ENTRY", DB "BATCH", FC "LIST_PUSH".
// Only then can you compile this SCL code.
TYPE JOB_ENTRY
STRUCT
Number : DINT := L#0 ;
Length : REAL := 0.0 ;
Width : REAL := 0.0 ;
END_STRUCT
END_TYPE
DATA_BLOCK BATCH
STRUCT
EDIT : JOB_ENTRY ;
ACTIVE : JOB_ENTRY ;
REPORT : JOB_ENTRY ;
LIST : ARRAY[1..99] OF JOB_ENTRY ;
END_STRUCT
BEGIN
// no assignments made
END_DATA_BLOCK
FUNCTION LIST_PUSH : INT
CONST
NoOfListEntries := 99 ;
END_CONST
VAR_IN_OUT
biPUSH : BOOL ;
END_VAR
VAR_TEMP
index : INT ;
END_VAR
IF biPUSH THEN
FOR Index:= NoOfListEntries TO 2 BY -1 DO
BATCH.List[index].Number := BATCH.LIST[index-1].Number ;
BATCH.List[index].Length := BATCH.LIST[index-1].Length ;
BATCH.List[index].Width := BATCH.LIST[index-1].Width ;
END_FOR;
BATCH.List[1].Number := 0 ;
BATCH.List[1].Length := 0.0 ;
BATCH.List[1].Width := 0.0 ;
END_IF ;
biPUSH := FALSE ;
// just a sample on how to simply access the data.
index := 2 ;
BATCH.ACTIVE.Length := BATCH.LIST[index].Length ;
LIST_PUSH := 100 ;
END_FUNCTION
JesperMP said:SFC20 BLKMOV is not really useful to manipulate lists, because "The source and destination areas must not overlap" as it says.
S7Guy said:This applies to arrays of udts as well, so life can be a lot simpler if things like that are taken into consideration at the beginning. And, paramterizing the required ANY pointers dynamically is pretty easy too as long as the code is well organized.