Assigning an ARRAY of an UDT DATALIST (S7)

userxyz

Member
Join Date
May 2002
Location
any
Posts
2,768
Not much to explain, see the pictures below,

Anyone who knows how to connect the list to the array ?

fsdgf1.jpg


ghfjhgf2.jpg


hbvgkhj3.jpg
 
Hello Combo.

Simply remove the square brackets so that it becomes "BATCH_LIST".LIST in stead of "BATCH_LIST".LIST[..].
But I must ask "why".
You machine is not going to handle several batch queues, or .. ?
Do yourself a favor and keep it simple. Address the DB and the ARRAY directly in SCL code. You will get the job finished
in no time.
You can simply write
"BATCH_LIST".ACTIVE.LENGTE := "BATCH_LIST".LIST[index].LENGTE
etc.

When you have it up and running like this, you can start modifying it to be "reusable", if you need it.
 
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.
Batchlist.GIF
 
hey

I have some code, Donno if it works, I will compile it and test in a few minuts, but I wanna explain it allready so that you can see what I'm doing right now.

This is the code I have untill now:

Code:
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


I made Arrays instead of UDT.

BATCHES_IN_LIST is an INT that I use to determine where the oldest batch (the first to execute) is located in the list...


What do you think Jesper ?




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.
Batchlist.GIF
 
code

Update of my code after testing the shifting thingy:

Code:
 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
 
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.
 
Habits

Jesper,

First of all, I'm an STL/LAD/GRAPH programmer.

I used SCL once, and I wrote it also with the help of this forum, also you I think.

My point is, I'm not a spcialist in SCL. I bought the book STL/SCL but didn't receive it yet. I know a little, and the little knowledge is what I'm using to write the batching thing.
That I have bad habits may be true, and I'm glad that you can advice me with better methods.

Okay, about you code, I really wanna use it, but I don't understand it... Number, Length, Width... ? And then Doing 2 by -1 ??

Can you explain what you're doing here ?

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.
 
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.
 
Last edited:
hmm

Call me stupid jesper, but I don't understand the adressing, I tried, but didn't succeeded.

Another thing is, I understand, DO 1 TO 5.

But: FOR index:= NoOfListEntries TO 2 BY -1 DO
I don't understand this one...


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.
 
With a FOR loop you specify the start, the end condition, and the step for each loop.
So, if NoOfListEntries is 99, start becomes 99.
End is 2.
Step is -1.
So the FOR loop starts with Index = 99 and continues to count down until Index = 2.

Here is a complete sample for how to push a list one step forward:
Code:
// 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
I think you can get the general idea on how to create SCL code to manipulate your batch list.
 
It is no wonder JesperMP gets the PMs

However, I would do this as shown. I would call SFC20 BLKMOV or write a FC in STL that copies the array. If I were writing this in C I would use the memmove function which is very efficient.

I cringe when I see the code and imagine the inefficient STL code that it generates.
 
If you must use a canned function then consider FC85 FIFO in the TI-S7 Converting library. SFC20 BLKMOV is not really useful to manipulate lists, because "The source and destination areas must not overlap" as it says.

I dont think the code that SCL generates is that inefficient.
The advantage is that you get code that is maintainable, and you can really tailor the code to suit your needs. Dont we ever return to these the same arguments ?
 
JesperMP said:
SFC20 BLKMOV is not really useful to manipulate lists, because "The source and destination areas must not overlap" as it says.

But, proper design ahead of time removes that restriction. For instance, if I have a 1000 dint list in DB100, and want to use it as a shift register, I would need an intermediate storage area if I wanted to shift upwards, i.e.:

CALL "BLKMOV"
SRCBLK :=P#DB100.DBX0.0 BYTE 3996
RET_VAL:=MW100
DSTBLK :=P#DB100.DBX4.0 BYTE 3996

But, if I designed the shift register so that my source value was at the other end of the DB (or actually, anywhere in the DB), I could do this without an intermediate step:

CALL "BLKMOV"
SRCBLK :=P#DB100.DBX4.0 BYTE 3996
RET_VAL:=MW100
DSTBLK :=P#DB100.DBX0.0 BYTE 3996

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.

That said, there is a point where SFC20 is less efficient than a raw load/transfer or loop. It has a fixed overhead, and doesn't make sense for just a few variables (assuming scan time is an issue; if not, who cares).
 
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.

Good thinking S7Guy. I always used an intermediate storage place in the past now i wont have to do that any more.
 
Yes, it is correct, BLKMOV can be used that way. I just made a test, and you can indeed have overlapping memory areas, reagrdles of what the help text says.

But you have to address that pointer the hard way. Not a big deal, but I think that in the code that I posted you can see immediately what is happening, and it automatically updates because it is 99% symbolical. A pointer does not offer that. I guess some well placed comments could counter this problem.

I dont think that scan time is an issue in any case. The list shall update upon event, which happens only when the operator decides to input a new batch job.
 

Similar Topics

I can't seem to figure out how to add descriptors to I/O points on an RMC using PCCU. Say, for example, I want to use "Valve_1" as a descriptor...
Replies
0
Views
67
Hello all. A little ashamed of myself that I can't remember how to do this but..... I have a 1734-AENT that I set the wheels to "888" applied...
Replies
9
Views
3,984
Hey everyone I'm working on a PLC project for a series of 4 vacuum pumps. I need to be able to rotate each pump into a different priority based on...
Replies
18
Views
6,458
Hi all, I am in the throes of commissioning a single S7-1517 cpu and I'm utilising both ethernet ports, X1 and X2, with individual IP addresses...
Replies
2
Views
1,702
With FactoryTalk ME is it possible to use a single Trend object and list of pens being displayed using macros? Would like to have one Trend object...
Replies
2
Views
1,755
Back
Top Bottom