Array of struct

dahnuguy

Member
Join Date
Mar 2007
Location
SC
Posts
720
Using Step 7 5.5
400 PLC

I had an idea recently of putting some data in an array.

There can be several devices, like a Drive for a motor for example.

Let's say 5 for now.

Each device has about 10 pieces of data. All in a UDT.

I was thinking of putting them all in one array of UDTs and then retrieve the data I want based on which motor I want to update or control.

Something like this:

Data.MotorDrv [2]

Now I realize I can do this much, but here comes the tricky bit.

L 3
T MW3

Data.MotorDrv [MW3]

Using sfc20

I can do this in STL with any pointers and AR1 etc, that is not the solution I am looking for. I want to symbolically address the array and return some element in it.

I kicked it around last week and thought it might work in SCL as I was able to return the Data [MW3] in SCL but only in an array of INT or WORD, not an array of UDTs.

I am a complete novice in SCL.

My current alternative is leaving the UDTs in the stat area and symbolically addressing them there.

I think an array of UDT or STRUCT would be more interesting AND it will allow additional devices to be added later to the end of the array with no ill effects on the existing code.

Like next week when they want to add 3 drives to the existing 5.

I could extend the array and change a few variables.

I realize there is only a small difference between the ideas, I am exploring what is possible here.
Is there a way to return ARRAY.UDT[MW3] where the position of the udt in the array is only known at runtime?
 
Can you give a concrete example by attaching the SCL code of what you wish to do - I am not clear where your array of UDT's is being declared/processed.

E.g. array is declared in a global db and the SCL is accessing the global DBs directly or,
array is declared in a global db and is passed as a parameter to an FB or you are copying the global data to the stat area of an FB and processing them there?
 
Here is an example of accessing an array of UDTs in SCL. It's a utility that reads data from an array of UDT's and sets up a block transfer between two locations. SFB20 didn't handle the block numbers involved in this application so I wrote my own version.

Code:
FUNCTION DBs_Move : INT
// Block Parameters
VAR_INPUT
    // Input Parameters
Source_List : ARRAY [0..19] OF tDB_Spec;   // Block List
Dest_List : ARRAY [0..19] OF tDB_Spec;   // Block List
bDirection : BOOL; // 1=Send to S5 0= Fetch from S5
iOffset : dINT;  // Offset between S5 and S7
iM_Buffer : INT; // Address for M area buffer
END_VAR
VAR_TEMP
    // Temporary Variables
iSize : INT ; // Size in Bytes
iSource_DB : INT ; // Source DB Number
iDest_DB : INT ; // Destination DB Number
iCount : INT ; // Counter
iLast : INT ; // Last block processed
END_VAR
    // Statement Section
    iCount:= 0;
    iLast:=0;
    FOR icount:= 0 TO 19 BY 1 DO
        // Statement Section
    isource_db:= source_list[icount].Block_no;
    iSize:= source_list[icount].Length; 
    iDest_db:= Dest_list[icount].Block_no;

    IF isource_db > 1 AND isize > 1 THEN
        // Statement Section_IF
        ;
        iLast:=iCount;
        
fcCopyDB_V2(iS5DBNumber :=  isource_db// IN: INT
            ,iS7DBNumber := idest_db // IN: INT
            ,bSendFetch :=  bDirection// IN: BOOL
            ,diOffset :=  ioffset// IN: DINT
            ,iSize :=  isize// IN: INT
            ,iM_Buffer := im_buffer // IN: INT
            ); // VOID
 
    END_IF;
        ;
    END_FOR;
  
    ;
    DBs_Move := iLast;
END_FUNCTION

N.B. Last time I checked, you cannot pass an array to a function in ladder. Maybe this has been corrected.

Nick
 
ARRAY of UDTs in a global DB. FB or FC uses an INT to point to a UDT in the ARRAY

Can you give a concrete example by attaching the SCL code of what you wish to do - I am not clear where your array of UDT's is being declared/processed.

E.g. array is declared in a global db and the SCL is accessing the global DBs directly or,
array is declared in a global db and is passed as a parameter to an FB or you are copying the global data to the stat area of an FB and processing them there?

Thanks for your interest.

Currently I have no SCL example as I have no idea how to write this in SCL. I am certain this will not work in LAD and any solution in STL that I am aware of, uses methods I do not want to use such as offsets to point to where the data should be.

I was successful at writing one function in SCL that does almost what I want, but the function I wrote only works with an array of simple data types. Like an array of INT.

I passed an INT into the interface of the FC and a pointer to the array, then the FC returned the value of the Array[n] to the output of that block.

That I understand and it works.

I failed to get the array of UDTs to work, so no code for that.

The Array of UDT will be declared in the STAT area of an FB or a global DB.


I want to pass an integer into a different FB and have it look at the correct set of data in the array. A pointer to the ARRAY will also be passed in the same interface as an input.

I want the destination FB to use the INT to determine which UDT in the ARRAY to look at.

Drive 3 will look at the data in the third UDT of the the ARRAY of UDTs.

I will use the same method to populate data from the drives back to the same DB.

I am currently using the known offset in the DB with some simple math to feed a pointer and load the data. As long as nothing changes, and "drive 1" starts at DBB 456 and each drive's UDT is the same number of bytes, and I know this is the Nth drive, then I know to point to DBB 456 plus some offset.

But things will change, I know this and I don't like this approach.

Instead of using offsets and integers to build a pointer to a static location, I would prefer to declare an array of UDT in a DB. This will take advantage of symbolic addressing.


Drive 3 then will point to the data in the third element of the array of UDT where all the data for all the drives is kept.

I tried using my code that works with an array of INTs, by replacing the INTs with UDTs, but I didn't get it to work.

I am wanting to know if this is even possible before I burn a couple days writing and debugging.


I can post some code later today to help clarify if this does not answer the question.
 
I was successful at writing one function in SCL that does almost what I want, but the function I wrote only works with an array of simple data types. Like an array of INT.

I passed an INT into the interface of the FC and a pointer to the array, then the FC returned the value of the Array[n] to the output of that block.

That I understand and it works.

Please post this code.
 
Code to address ARRAY element using SCL

Please post this code.

This works in the simulator and is easy enough to follow. I only made this block to learn a little SCL and to test the idea one step at a time. I know it should work with ARRAY of INT so I write something that works with INT, then I think about how to make it work with an ARRAY of UDT.


FUNCTION FC2015 : void
(*********************************************************
This function returns the value of an array element specified by the integer input.
***********************************************************)
CONST
Step := 10;
END_CONST
VAR_INPUT
value : INT;
Test : ARRAY[0..Step] OF INT;
END_VAR
VAR_OUTPUT
ValueOut : INT;
END_VAR
BEGIN
IF value <= Step THEN
ValueOut := test[value];
ELSE
ValueOut := 0;
END_IF;
END_FUNCTION


Now if I could do this:

FUNCTION FC2015 : void
(*********************************************************
This function returns the value of an array element specified by the integer input.
***********************************************************)
CONST
Step := 10;
END_CONST
VAR_INPUT
value : INT;
Test : ARRAY[0..Step] OF UDT 600; // or some struct
END_VAR
VAR_OUTPUT
ValueOut : INT;
END_VAR
BEGIN
IF value <= Step THEN
ValueOut := test[value]; this would need to be a UDT with the same structure as UDT600.
ELSE
ValueOut := 0;
END_IF;
END_FUNCTION

And of course the "value out" has to change to a UDT that matches.

Then I do some logic with the data.

I would be moving the data from a DB into the TEMP area of the calling block.
 
You could make an FB with the UDT as an input. Assign UDT[0] (I hope is is legal?). From inside the FB you can dechiper the UDT input and find the UDT byte length and the start address (format = anypointer). Then you need an integer input to select the array number. Use it to multiply the UDT byte length and add it to the start address.

Kalle
 
Last edited:
Post the code you have written that does not "work" - it will be much quicker that way.

My Fc compiles ok but with warnings from screwy chars in the source.

Code:
TYPE udt600
STRUCT
Colour:INT;
END_STRUCT;
END_TYPE;
FUNCTION FC2015 : VOID
CONST
Step := 10;
END_CONST
VAR_INPUT
value : INT;
Test : ARRAY[0..Step] OF udt600;
END_VAR
VAR_OUTPUT
ValueOut : udt600;
END_VAR
BEGIN
IF value <= Step THEN
ValueOut := test[value]; 
END_IF;
END_FUNCTION
 
I got it debugged.

At first I wanted to use structs in an array, but that can't work.

When I tried an array of UDT it also did not work, but I think it was from a mistake somewhere. I over looked something. Probably due to looking at the screen for too long.

I now have exactly what I wanted. No errors, no warnings.

FUNCTION FC2015 : void
(*********************************************************
Output value of an array element specified by the integer input.
***********************************************************)
CONST
Step := 10;
END_CONST

VAR_INPUT
value : INT;
ARRY_IN : ARRAY[0..Step] OF udt605;

END_VAR

VAR_OUTPUT
ValueOut : udt605;
END_VAR

BEGIN

IF value <= Step THEN
ValueOut := ARRY_IN [value];

END_IF;

END_FUNCTION


It is so simple in SCL.
 
Thanks L D[AR2,P#0.0]

now I wish I had checked back here about 6 hours ago.

I was waiting for an email notification that a new response was posted and I never got an update. Probably have to log in to get a new update.



The only thing more fun than SCL is opening the block and reading through the STL version of the SCL commands.
 

Similar Topics

Hi there, I have an array of 44 words that contain the two parts of a set of real numbers. I want to copy these words over to my Struct which...
Replies
12
Views
3,479
I have an Array of Struct which contains 49 pairs of DWord points. How can I convert this entire array to Dint or Real numbers?
Replies
3
Views
2,874
Hi, I would like to know what good applications are for an array, struct, string and UDT? I pretty much know how to use them (moving the data...
Replies
2
Views
2,707
Hi. I try to implement an array of struct in IEC61131-3 ST language. I use a beckhoff PLC. The C code look like this: Struct BDD { Unsigned...
Replies
6
Views
5,157
Hi, I'm having an issue in crimson 3.0 when I create a programme using a case statement referencing a fault word that each bit needs to change the...
Replies
1
Views
75
Back
Top Bottom