## Array and Enumeration in Structured Text

What is an array:

An array can be defined as an ordered collection of items indexed by contiguous integers. An array is a data structure that can store a number of variables of the same data type in sequence. These similar elements could be of type int, float, double, char,  Function Block, etc.

Arrays are used when there is a need to use many variables of the same type. It can be defined as a sequence of objects which are of the same data type. It is used to store a collection of data, and it is more useful to think of an array as a collection of variables of the same type. Arrays can be declared and used. A programmer has to specify the types of elements and the number of elements that are required by an array. This is called a single-dimensional array. The array size should be an integer constant and greater than zero.

One-, two-, and three-dimensional fields (arrays) are supported as elementary data types. Arrays can be defined both in the declaration part of a POU and in the global variable lists.

In the following statement, we declare an array of 5 integers and initialized them with 1, 2, 3, 4, and 5 respectively.

`ArrayInt : ARRAY [1..5] OF INT := [1,2,3,4,5];`

Look at the syntax ARRAY[lower..upper] OF allows us to define any lower or upper bounds. As compared to C#, our lower bound doesnâ€™t have to be zero. The total number of elements in the array is upper – lower + 1. We could have declared the above statement as the following as well

`ArrayInt : ARRAY [2..6] OF INT := [1,2,3,4,5];`

In this case, we have accessed first number by  by the following way.

`firstOne := ArrayInt[2]; // 1`

Now we shall describe, how we can declare an array of FUNCTION_BLOCK

Sample function block

```FUNCTION_BLOCK MotorAC
VAR_INPUT
machineName : WSTRING :="Type A";
END_VAR

VAR_OUTPUT
machineAlarm : BOOL := FALSE;
END_VAR
VAR
maxRotationValue : REAL := 0.0;
rotationPerSeconds : INT := 0;
myTimer : TON ;
startMachine : BOOL := FALSE;
END_VAR```

We declare and initialize those array of 3 instances in the following way.

```ArrayMotorAc : ARRAY [1..3] OF MotorAC := [
(machineName:= "Motor_one"),
(machineName:= "Motor_two"),
(machineName:= "Motor_three")
];
```

Initialization can be done in the following way.

`FOR index := 1 TO number_of_motor DO    ArrayMotorAc[index].InitMachine();		END_FOR;`

## Arrays with variable length

We can pass pointer of data to a method and calculate the index as shown in the following example.

`FUNCTION FuncArrayTestByPointer : INTVAR_INPUTÂ  pDataÂ  Â  Â  Â  Â  Â : POINTER TO INT;Â  nSizeÂ  Â  Â  Â  Â  Â : UDINT;END_VARVARÂ  pIndexÂ  Â  Â  : POINTER TO INT;Â  nUpperIndexÂ  Â  Â : UDINT;Â  nIndexÂ  Â  Â  Â  Â  : UDINT;END_VAR`
`FuncArrayTestByPointer := 0;nUpperIndex := nSize / SIZEOF(pIndex^);IF (nUpperIndex > 0) THENÂ  FOR nIndex := 0 TO (nUpperIndex - 1) DOÂ  Â  pIndex := pData + (nIndex * SIZEOF(pIndex^));Â  Â  FuncArrayTestByPointer := FuncArrayTestByPointer + pIndex^;Â  Â Â  END_FOREND_IF`

Â

Example usage

`arrayÂ  Â  : ARRAY[2..6] OF INT := [16, 34, 4, 43, 35];SumÂ  Â  : INT;Sum := FuncArrayTestByPointer(ADR(array), SIZEOF(array));`

Â

Newer way use the variable array as defined inÂ 3rd Edition of IEC 61131-3

In function blocks, functions or methods, arrays with variable length can be declared in the declaration section VAR_IN_OUT. The operators LOWER_BOUND and UPPER_BOUND can be used to determine the index limits of the array that is actually used at runtime. LOWER_BOUND returns the lower limit, UPPER_BOUND returns the upper limit.

Â

`FUNCTION FuncArrayTestByPointerNewWay : INTVAR_IN_OUTÂ  arrDataÂ  Â  : ARRAY[*] OF INT;END_VARVARÂ  nIndexÂ  Â  Â : DINT;END_VARFuncArrayTestByPointerNewWay := 0;FOR nIndex := LOWER_BOUND(arrData, 1) TO UPPER_BOUND(arrData, 1) DOÂ  FuncArrayTestByPointerNewWay := FuncArrayTestByPointerNewWay + arrData[nIndex];END_FORExample usagearrayÂ  Â : ARRAY[2..8] OF INT := [36, 34, 4, 43, 35, 2, 65];SumÂ  Â  : INT;Sum := FuncArrayTestByPointerNewWay(array);`

Â

## PLC Array index and HMI array index

We declare an array like the following.

`ArrayInt : ARRAY [5..9] OF INT := [10,2,3,4,5];myvar : INT := -1;END_VAR//bodymyvar := ArrayInt[5];`

We have mapped those variables and want to display the ArrayInt and myvar on the HMI, see the mapping in the following picture.

Figure 01: ArrayInt[5] is mapped as ArrayInt[0] in HMI

As we see in the HMI it is mapped from 0 to 4 and in the PLC it is declared as 5 to 0. This is the default behavior. We can read the first item by the following code. Note that we are using ArrayInt[0] not 5

`async function asyncFunctionCall() {try {Â  Â  const myvar = await ReadPLCVariable('%s%PLC1.MAIN.ArrayInt[0]%/s%');Â  Â  var myTextBlockControl = TcHmi.Controls.get('TcHmiTextblock_1');Â  Â  myTextBlockControl.setText(myvar);}catch(error) {Â  Â  console.log(`ErrorCode = \${error.ErrorCode}`);Â  Â  console.log(`ErrorText = \${error.ErrorText}`);Â  }}asyncFunctionCall();`

Figure 02: Second text block shows the number as read by the above code

## Tips

=> Changing index in HMI

Index in PLC can have any index, we can adjust the index HMI in the following way.

Some info related to variable length in array.

LOWER_BOUND(arrData, 1) returns as lower bound of the supplied array, and its type is DINT. We can know the number of items by substracting lower bound from the upper bound.

## References:

Next, letâ€™s try to understand PLC data type atÂ https://www.hemelix.com/plc/data-type-used-in-plc-programming/

Ask questions related to Hemelix sample code and design at Google groupÂ https://groups.google.com/g/hemelix