Variable Length Arrays
How to use VLAs in Sysmac Studio
Firstly, what is an Array?
An array is a common term used for group of variables. They are also called vectors in some programming languages. In programming, arrays are very handy, as they allow us to store many values and access them using code loops. Microsoft Excel presents data in a two dimensional array, or matrix with rows and columns. In Sysmac Studio we can define up to 3 dimensional arrays, with a maximum total number of 65535 elements. In particular, because the index of the array can be controlled using a variable, arrays are very easy to be used with loops such as a FOR loop to repeat an action through all the elements of the array. For example this code sample will loop through all 200 elements of the array "myArray" to calculate the sum.
FOR i:=0 to 199 DO
myTotal:= myTotal + myArray[i];
END_FOR;
Programming with arrays saves time, and allows more complex programs to be written much faster. It is one of the many useful programming concepts available in Sysmac Studio, and grasping the use of arrays allows a beginner programmer to take a step up in their programming career. Arrays can be one dimension, like a row in Excel, or 2 dimensions (think a square matrix) or 3 dimension (think of a cubic matrix).
The elements of an array can be a standard data type, or even a user defined structure. A machine parameter set can be represented by a Structure, and an array of this Structure could be your set of Machine parameters. Selecting one array element, you could recall a complete set of machine parameters, in just a few of lines of code.
What is a variable length Array?
A variable length array is an array in which the number of elements is not defined. Although any variable we create in Sysmac Studio has a predefined length at compile time, we can write Functions and Function Blocks which can accept arrays of different sizes. Note variable length arrays can only be used with Function or Function Blocks as In/Out type.
For example, if we wish to write a function which takes an array and computes the mathematical average of all the elements, without Variable Length Arrays, we would need to write a Function or Function Block for an array with 2 elements, 3 elements 4 elements etc. This would obviously not be very useful, it is far more effective to write a Function or Function Block which accepts any size and can adapt the processing accordingly. One note is that the number of dimensions (x,y,z) must be defined, you cant pass a double dimension array into a Function or Function Block that is expecting a single dimension!
Note : In order to use this feature, the Machine Controller and Sysmac Studio project must be set to firmware version 1.18 or greater (we are at v1.46 as at the time of writing, so all controllers shipping have had this feature for a long time). Older controllers can have the firmware updated by OMRON if required.
In, Out and InOut Variables
When working with Functions and Function blocks in Sysmac Studio, you will notice that there are three different types of IO for a function block. Understanding how these work can help you increase your controllers efficiency of processing and control your variables effectively.
Input variables
These variables allow the user to pass the value of a variable from the outside of the Function or Function Block. Below the variable on the outside of the Function or Function Block which is allocated to the Execute input is passed to the variable INSIDE the Function or Function Block named Execute. This is what is called By Value, ie the value of the variable is written to the variable on the inside of the Function or Function Block. The variable on the outside and the variable on the inside are separate, and therefore use twice as much memory. If we pass large arrays using the Input type, we will consume many CPU clicks (one per 4 bytes) to copy the values from one variable to another. An array of 1000 elements will consume many CPU operations to perform.
Function or Function Block Input and Output specifications table
Note that we are defining the names of the variables for use inside of the Function or Function Block in the above table. The variables being passed to the Function or Function Block can have different names.
Output Variables
The value of the variable INSIDE the Function or Function Block named Average is passed By Value to the variable associated with this element of the Function or Function Block on the OUTSIDE of the Function or Function Block .
When passing a value By Value, the inside of the Function or Function Block cannot change the value of the variable named Execute as we are working with a copy of the value, not the variable on the outside of the Function or Function Block . This is handy to ensure that your Function or Function Block does not change values external to the Function or Function Block.
However, each time we copy a variable from one to another, this requires CPU clicks to accomplish. If we have many values we wish to pass into the Function or Function Block then we will use many CPU operations just to pass all the values into the Function or Function Block. Also if passing an array, again we will be using a CPU operation per 4 bytes of data and a 1000 element array of REAL datatype would take 1000 CPU operations to accomplish.
The upside of the Input and Output types, is that the variable on the outside is protected from any changes by the Function or Function Block as the Function or Function Block works with a copy of the values.
In/Out variables
In/Out variables do not copy the value of the variable from the external to the internal of the Function or Function Block. They pass a pointer to the variable from the outside of the Function or Function Block to the inside, and allow the Function or Function Block to work with the variable external variable. As such, they very quickly pass a 32 bit memory address inside the Function or Function Block instead of, for instance, having to copy 1000 elements of an array from the outside to the inside. In/Out variables drastically decrease wasted CPU operations, however they allow the Function or Function Block to operate on the actual variable. This may be very handy, for instance if you wish to sort an array of data from smallest to largest. Here is a comparison on the two methods using a large array (say 1000 REAL values)
Using Input and Output types
The array of 1000 REAL values (each 4 bytes in length) are copied from the external array to a copy inside the Function or Function Block. Many CPU operations later, the values are copied into another array inside the Function or Function Block. The code inside the Function or Function Block is then executed and the code sorts the numbers from smallest to largest. The sorted array is then copied element by element to another copy of a 1000 element array as the values are Output from the Function or Function Block. One array of 1000 REALS exist on the outside and are passed into the Function or Function Block , an array of 1000 REALS exists inside the Function or Function Block and another array of 1000 REALS exist as the array the results are passed to. 3000 REAL data types are used when programming like this.
Using In/Out types
The memory pointer is passed into the Function or Function Block. The code inside the Function or Function Block executes and sorts the values from smallest to largest. This is sorting the actual variable (an array in this case). When the code is complete, the Function or Function Block can exit as there is no need to pass the values to another variable. A single array of 1000 REALS exists.
This is every useful when we do want the Function or Function Block to act on the data. For instance if sorting the data, we are reading and writing the actual array of data. If computing the average, we are only reading the values. The programmer must be mindful that the original data can be changed when using this method.
External Variables
As a side note, External Variables are useful for global items that will exist in every program, for instance _CurrentTime is the controllers DateTime. There is no need to pass such a variable into the Function or Function Block as a variable. Using _CurrentTime in your code will automatically place this element into the External Variable Table. Other examples are status flags etc.
Internal Variables
These are "private" or internal variables used in your code, for instance if computing the average, you would sum the values first. The variable Sum would be an Internal Variable. These variables cannot be influenced by the external code (hence are private), as you would expect. Otherwise external code could ruin the internal calculations!
Variable Length Arrays must be In/Out types
Because we are using memory pointers with In/Out types, memory does not need to be allocated to the Function or Function Block at compile time. Therefore we can write a Function or Function Block which does not define the size of the array. Above we can see the syntax for this in the table which defines our Function or Function Block IO variables, the Datatype specification in the Function or Function Block is ARRAY[*] OF {datatype}. Note the Datatype can even be a structure if desired. What if the user passes ARRAY[When processign entries of an array there are two instructions that are essential. Note the Datatype can even be a structure if desired.
What if the user passes an array starting at element 3 and ending at element 11(ie ARRAY[3..11] OF REAL) into our Function or Function Block? When working with elements of an array there are two instructions that are essential. These are LOWER_BOUND and UPPER_BOUND and return the lowest and highest element of the array. These instructions consist of two operands (values we pass it), the array variable, and the dimension we wish to query (range 1 to 3). For instance if passing this variable into our Function or Function Block:
LOWER_BOUND(ARR:=Data, DIM:=1) will return the value of 3 and UPPER_BOUND(ARR:=Data, DIM:=1) will return the value of 11.
Both instructions return the value as a DINT (double signed integer) type. Note also we defiend the variable on the inside as Data. Referring to the variable "Data" in the inside is the same as the variable named "myArray" on the outside.
Below is an example of a Bubble Sorting algorithm, inputting a two dimensional variable length matrix as a worked example.This algorithm is very useful in data analysis.
(* 2D Bubble Sort Algorithm
In/out an m x n matrix and sort by bubble method
Note this is best executed in a periodic task if the array is large
Author : Toby Kilroy March 2020
*)
(*-----------------------------------------------Initial Variable Values--------------------------------------------------------*)
//Determine upper and lower bounds of the in out matrix
rowUprBnd:= UPPER_BOUND(SortMatrix,1);
rowLwrBnd:= LOWER_BOUND(SortMatrix,1);
colUprBnd:= UPPER_BOUND(SortMatrix,2);
colLwrBnd:= LOWER_BOUND(SortMatrix,2);
rowCount:= rowUprBnd-rowLwrBnd+1;
columnCount:= colUprBnd-colLwrBnd+1;
ii:= 0;
(*------------------------------------------------------Algorithm--------------------------------------------------------------*)
ii:= 0;
While (ii < RowCount) And Not isSorted Do
isSorted:=True;
ii:= ii + 1;
For jj:= 1 To RowCount - ii DO
If SortMatrix[jj, 1] > SortMatrix[jj + 1, 1] Then
FOR bb:= 1 To ColumnCount DO
Temp[bb]:= SortMatrix[jj + 1, bb];
SortMatrix[jj + 1, bb]:= SortMatrix[jj, bb];
SortMatrix[jj, bb]:= Temp[bb];
END_FOR;
isSorted:=False;
END_IF;
END_FOR;
END_WHILE;