Array Question

My Name

Member
Join Date
Apr 2004
Location
Drenthe
Posts
19
Hi people,

I have a problem; well it’s a question actually. I want to program an array what isn’t that difficult but now I want to call a variable in that array by the value of a counter.

Example:
Normally you call a variable by typing the array name and index number like “array[1]”. Now I want the index number variable like “array[“counter value”] where counter value stand for an index number.

Is this possible?..?..
I’m programming in S5/S7 für Windows (something like S5, S7 from Siemens) by the developer “IBH softec”.
 
You cannot access an ARRAY inderectly simply using something like IntArray[index]. In S7 you have to use POINTERS.

You have to look up "pointer" and "indirect addressing" yourself in the online help, or the Hans Berger book "Automating with STEP7 in STL and SCL".
You will find that there are many variants that you have to "master".

Using the IBH software should not matter. The code should be the same.

I have made an example to give you a good start (warning, untested!):
Its for accessing an ARRAY from the same FB where it is declared.
[attachment]

indadrarray.gif
 
I think what 'My Name' is asking about is variable indexed addressing of an array, not indirect addressing. It's not quite correct to say that you can not use variable indexed arrays in 'S7' - it depends entirely on the programming language.

I don't know about IBH Softec but in Siemens' own STEP7 software variable array addressing is not possible in STL but is possible in SCL (IEC Structured Text). So you can have statements like -

WHILE n < 20 DO
LIST[n] := LIST[n + 1];
n := n + 1;
END_WHILE;

LIST[20] := InputVal;

The array index can be a literal value, a variable, or an expression. Unfortunately in STL, you're restricted to a literal index.

SCL : good
STL : bad
PLC : not relevant

Regards

Ken.
 
I think that only STL, LAD and FBD is available in S5/S7 for Windows .

edit:
If he needs a variable "index" with an offset to the ARRAY, then he can do something like this:


L "index"
SLW 4 //fit to pointer format for words
L P##IntArray
+D
LAR1
L W [AR1, P0.0] //same as L #IntArray["index"]
etc.

 
Last edited:
step7 indirect array indexing trouble..

Hi. I think I`m trying to do the same thing as "My name" .

I`ve created a program in FBD which is supposed to get a value from an analog input and store its value in an array[0 to 9000] of REAL.
(One sample stored to the array for each ob1 cycle...array(i+1)).

I just discovered that the indexed adressing method only is possible in STL source or SCL, and I`m not too familiar with any of these languages.
The STL code must get its index-pointer from the FBD program I`ve already created so I dont have to change the program too much..
Does anyone have a simple solution to this problem?

Can anyone tell me what the "T" and "D+" means in the code above this post?

Edit: Is there a "special" way to do this in FBD?

--snoop
 
Last edited:
Hi snoop,

you have stumpled upon one of the annoyances with STEP7. Indirect or indexed addressing simply isnt possible in FBD or LAD. Go with the above example, or one of the others in the Hans Berger books, or search on the forum for further examples.

"T" means Transfer (normally from AKKU1 to the address specified).
Edit: Hey ! There is no T instruction in the code example above.
However there are several "L" (Load from address specified into AKKU1) instructions.
"+D" means Add the doublewords contained in AKKU1 and AKKU2 together and store the result in AKKU1.
Doublewords because a pointer needs two words storage space.

Tip: Even if you normally program in FBD, you can insert one or more STL networks, and still keep the rest of the rungs in FBD.
Insert an empty rung. Switch to STL. Enter the STL code. Switch back to FBD (or LAD). The new STL rung will stay in STL (*).

*: There is a slight possibility that the STL code can be viewed as FBD or LAD. But in the above example this will not happen.
 
Last edited:
variables:
I :INTEGER //arrayindexer from FBD
sampledata:REAL //the sampled data from PIW128
realarray[0..9000] of REAL
(array is located in DB100 which is used by OB1)
-----------
Do you have a suggestion for a piece of code to accomplish this?:

-Write "sampledata" to RealArray at position

would be simple in a higher level programming language but I`m having troble understanding the STL language.. (the accumulator confuses me the most..)

would this work?

L "I" //load pointer to accumulator?
L "SampleData" //load sampledata to accumulator?
L P##RealArray //load array to accumulator?
LAR1
L W(rite)? [Sampledata,I]//write sampledata to pos in array?
T Realarray DB100 //transfer array back to DB100?
 
Here is my go at it:

Initialise: 
L P#RealArray
T #ArrayPointer //"I" is reserved for inputs I think.

For every scan:
L #ArrayPointer // Increment the index one variable per time.
+32
T #ArrayPointer

L #ArrayPointer // Point to the current array address
LAR1
L "SampleData" // Load the new values
T D [AR1, P#0.0] // Writes the data to the DOUBLEWORD address of the REAL variable.



edit: I am a bit unsure if it should be +16 or +32 when it is a double word address.
 
Last edited:
I've got this sort of thing running as well Jesper and while I do it using the Shift Left command rather adding 32 (because I'm actual getting a module number as a parameter) and for REALS I'm doing SLD 5, which is indeed 32. The addressing in S7 is allways Byte.Bit oriented.
 
I have worked on something like this and I'm still not quite there. I wanted a simple indexed array move like I find in most other PLC's. You can find the THREAD HERE I think I should be able to refing it more and use SCF20 for the actual move but I can't figure out how to get the pointers correct.
 
For array processing I use the following function (FC596) to determine the size of each element of the array and the number of elements in the array. I use the number of elements as the loop counter and the size of each element to increment AR1.

FUNCTION FC 1000 : VOID
TITLE =

VAR_TEMP
dwSizeOfElemnt : DWORD ;
INoOfElements : INT ;
END_VAR
BEGIN
NETWORK
TITLE
=size of array test
CALL FC596 (
pFirst := "dbData".data[0],
pSecond := "dbData".data[1],
pLast := "dbData".data[9000],
dwElementSize := #dwSizeOfElemnt,
iNoOfArrayElements := #INoOfElements);
NOP 0;
END_FUNCTION

FUNCTION 596 : VOID
TITLE =Calc size of an array and its elements
//calc element size (pointer format, i.e. bits) from (second -first)
//calc array size from (last - first)/element size
//
VERSION : 0.0

VAR_INPUT
pFirst : POINTER ; //pointer to first element
pSecond : POINTER ; //pointer to second element
pLast : POINTER ; //pointer to last element
END_VAR
VAR_OUTPUT
dwElementSize : DWORD ; //element size in S7 pointer format
iNoOfArrayElements : INT ; //no of elements in the array
END_VAR
VAR_TEMP
dwSize : DWORD ;
dwFirst : DWORD ;
dwSecond : DWORD ;
dwLast : DWORD ;
END_VAR
BEGIN
NETWORK
TITLE
=first,second and last
L P##pFirst;
LAR1 ;
L D [AR1,P#2.0];
T #dwFirst;
L P##pSecond;
LAR1 ;
L D [AR1,P#2.0];
T #dwSecond;
L P##pLast;
LAR1 ;
L D [AR1,P#2.0];
T #dwLast;
NETWORK
TITLE
=calc size of element
L #dwSecond;
L #dwFirst;
-D ;
T #dwElementSize; //bytes
T #dwSize;
NETWORK
TITLE
=calc size of array
L #dwLast;
L #dwFirst;
-D ;
L #dwSize;
/D ;
+ 1;
T #iNoOfArrayElements;
END_FUNCTION
 
Simon, there is another way to do the same thing with far fewer instructions. All you need to do is pass in two ANY pointers, one of them pointing to one of the individual elements in the array, and the other pointing to the entire array. For instance, if I create a DB that has an array of 150 Motor UDTs (each consisting of 6 bytes), this is what the block call will look like (the DB is called “DB Motor”, and the Motors are called Motor[1], Motor[2], etc):


Code:
[/font]
[font=Arial]	 CALL FC	 2
	 MotorArray:="DB Motor".Motor
	 Motor	 :="DB Motor".Motor[1]





Inside the call, all I have to do is look at the repetition part of the ANY variable to get the length of the entire array and the individual UDT. If the array happened to be in the middle of the DB, then I could also look at the pointer part and create an offset. I can even drill down deeper if I want to find individual elements of a UDT by adding another input variable. I change the size and structure of my DBs all the time, and I use this to recalculate the location and size of my data on startup so I don’t have to change any code.

Code:
[/font]
[font=Arial]	 L	 P##Motor
	 LAR1 
	 L	 W [AR1,P#2.0]
	 T	 #MotorLength[/font]
[font=Arial]	 [/font]
[font=Arial]	 L	 P##MotorArray
	 LAR1 
	 L	 W [AR1,P#2.0]
	 L	 #MotorLength
	 /I	
	 T	 #NumberOfMotors
 
JesperMP said:
Here is my go at it:

Initialise: 
L P#RealArray
T #ArrayPointer //"I" is reserved for inputs I think.

For every scan:
L #ArrayPointer // Increment the index one variable per time.
+32
T #ArrayPointer

L #ArrayPointer // Point to the current array address
LAR1
L "SampleData" // Load the new values
T D [AR1, P#0.0] // Writes the data to the DOUBLEWORD address of the REAL variable.



edit: I am a bit unsure if it should be +16 or +32 when it is a double word address.

Hi.. thx for the code.. The incrementing of the arraypointer is alredy being performed in the FBD program so the "inc section " of your code is not needed..
I`ll try this code without the increment part..
Thanks so far..(I`ll most likely be back with more questions if I cant get the code working)

edit; If the pointer[int] is incremented by ONE for each OB1 cycle, do I still need the "+32" in STL to be sure it points to the correct address?(Will the Integer pointer from the FDB automatically point to the correct position in the array?)

Word i 16bit so Dword should be 32 bits
 
Last edited:
There should be
Code:
+ L#32
instead of
Code:
+ 32
in JasperMP's code. Otherwise it will fail for addresses over 8188.0
BTW, don't use INC instruction for incrementing in such a code it will fail much faster.
 
Last edited:

Similar Topics

Hello, When you want compare values of an array to a range of numbers is it a right way to do that? FUNCTION ADD VAR_IN_OUT A:ARRAY[1..50]...
Replies
5
Views
2,062
Hi all, I'm trying to access a variable address in a shift register. I have used BSL with an array DINT[20]. Now I wan't to access...
Replies
4
Views
1,516
Hi all, I am using RSLogix5000 version 7 to modify a program on a 1756-L1 controller. We have installed 5 more drives on a conveyor system. The...
Replies
2
Views
2,683
** EDIT - UPDATE ** ** After a bit of searching on here I've found an excellent example from LD... so I think I can utilise that to get...
Replies
3
Views
1,726
Hello, I need some ideas on how to sort an array. I have 3 1d arrays in a udt with a length of 101. Lets call them XAxis[0-100],YAxis[0-100],and...
Replies
3
Views
5,220
Back
Top Bottom