TIA 15.1 Shifting Array Of a udt

kevilay

Member
Join Date
Feb 2009
Location
Ontario
Posts
174
Hello Guys,

I think I need to use SCL for the following task but am very weak using SCL in tia portal.

I have results history data block. It is an array[0..32] of 'udtLeakTestResult" my custom datatype containing a bunch of data. In the old siemens I had a block copy instruction i could use a pointer and just do a gross copy. However the PLC I am using doesnt allow STL. I am trying to shift the history. Basically Copy Elements 0-31 to 1-32. Then I will manually copy the new part data into 0.

Does anyone have a suggestion as to how ot do this? I wasnt able to use a BLK copy because of the datatype. I can use a single move instruction but then I would need 32 of them.

Thanks,
Kevin
 
Ask The Google about For-Next loops in structured text to shift an array. I would be surprised if there was not a YouTube example doing exactly what you want
 
Block move is a good option, however, I seem to think the Siemens block move does not like moving inside of the same boundaries, i.e. effectively move them by one register, however, I do know it works on some other platforms.
 
The block move doesnt work because it wants an actual datatype. It would work with an array of integers but since the array is a udt structure it wont accept it as a parameter.

I ended up with this after watching some videos. I haven't tested it yet.

Code:
IF "Machine DB".Sequence.Step16 THEN
    ;
    
    //Define Variables
    #i := 0;
    #j := 32;
    
    FOR #i := 1 TO 32 DO
        "ResultsHistory".History[#j] := "ResultsHistory".History[#j - 1];
        #j := (#j - 1);
    END_FOR;
END_IF;
 
Last edited:
The block move doesnt work because it wants an actual datatype. It would work with an array of integers but since the array is a udt structure it wont accept it as a parameter.

I ended up with this after watching some videos. I haven't tested it yet.

Code:
IF "Machine DB".Sequence.Step16 THEN
    ;
    
    //Define Variables
    #i := 0;
    #j := 32;
    
    FOR #i := 1 TO 32 DO
        "ResultsHistory".History[#j] := "ResultsHistory".History[#j - 1];
        #j := (#j - 1);
    END_FOR;
END_IF;




I think that you can build FC and inside it commands serialize and desrialize with pos offset (2bytes).



Siemens sample for copying with zero offset.

https://support.industry.siemens.co...d-data-in-step-7-(tia-portal)-?dti=0&lc=en-WW
 
The serialize/deserialize method can definitely work.
But I think it is not the best since it is not so obvious how it works.
Serialize/deserialize is mainly used for copying data between structures with different declarations.

When you have an array of the same declaration, in this case of a datatype udtLeakTestResult, then it is simple and easy to program a FOR loop, and it is pretty obvious how it works. keep-it-simple.

Some will complain that a FOR loop is slightly less efficient than copying the whole area as a block, but with todays PLCs that is irrelevant. keep-it-simple beats performance considerations 99.9% of the time.
If you absolutely must copy the data as a block, look into declaring the data multiple times by the AT view. Then you can specify the source and destination symbolically by the different views.
It will only work for data declared within an FB an either as non-optimized or with the data retention set to "set in IDB".

NB. In the FOR loop you can just increment in reverse. So you can omit the #j counter. This simplifies and makes the code easier to read.
edit:
FOR #i:=32 TO 1 BY -1 DO

edit edit: nit-picking here. It is good that you initialize counters at the beginning, but in the case of a FOR loop it is actually not necessary. The initialization #i:=1 (or #i:=32) is already part of the FOR statement.
 
Last edited:
NB. In the FOR loop you can just increment in reverse. So you can omit the #j counter. This simplifies and makes the code easier to read.
edit:
FOR #i:=32 TO 1 BY -1 DO

@kevilay please pay particular attention to this!

The code you posted will copy only the value of element 0 to all other elements. On the first pass through the loop, the value in element 0 (j-1) will be assigned as the value of element 1 (j) ; on the second pass through the loop, the value in element 1 (j-1) will be assigned as the value of element 2 (j), but that element 1 was assigned the value of element 0 on the previous pass, so element 2 now has the same value a elements 0 & 1; and so on for all subsequent passes of the loop.

The solution is the FOR statement provided by @JesperMP.
 
I think that you can build FC and inside it commands serialize and desrialize with pos offset (2bytes).



Siemens sample for copying with zero offset.

https://support.industry.siemens.co...d-data-in-step-7-(tia-portal)-?dti=0&lc=en-WW

The serialize/deserialize method can definitely work.
But I think it is not the best since it is not so obvious how it works.
Serialize/deserialize is mainly used for copying data between structures with different declarations.

When you have an array of the same declaration, in this case of a datatype udtLeakTestResult, then it is simple and easy to program a FOR loop, and it is pretty obvious how it works. keep-it-simple.

Some will complain that a FOR loop is slightly less efficient than copying the whole area as a block, but with todays PLCs that is irrelevant. keep-it-simple beats performance considerations 99.9% of the time.
If you absolutely must copy the data as a block, look into declaring the data multiple times by the AT view. Then you can specify the source and destination symbolically by the different views.
It will only work for data declared within an FB an either as non-optimized or with the data retention set to "set in IDB".

NB. In the FOR loop you can just increment in reverse. So you can omit the #j counter. This simplifies and makes the code easier to read.
edit:
FOR #i:=32 TO 1 BY -1 DO

edit edit: nit-picking here. It is good that you initialize counters at the beginning, but in the case of a FOR loop it is actually not necessary. The initialization #i:=1 (or #i:=32) is already part of the FOR statement.

This is perfect. Great suggestion!
 
The block copy (if you can get it to work in TIA) copies in reverse so will not zero everything.
The for next works well, but you do need the by statement just remember in both cases that the Array[0] will maintain the value that has been copied to array[1] so depending what you are doing with the array, either zero it after the move or The for next or populate it with the new data before calling either function again.
 
Last edited:
I'm on the "use SCL" side of the fence. It's simpler, cleaner, and I don't think there will be a huge performance loss. If you're not experienced in STL, you'll get lost easily.


In the 1500, SCL actually has way better performance than STL, becuase they can compile the SCL directly, whereas for STL they need to emulate the old 300 chip architecture.
 
In the 1500, SCL actually has way better performance than STL, becuase they can compile the SCL directly, whereas for STL they need to emulate the old 300 chip architecture.


Have you got any examples that demonstrate the SCL is better - in my experience the STL ends up being similar/slightly better than the SCL (example below)


(Tag_8 is MD300, LOOPCOUNT is 30000)



Code:
     SET
      R     #bSTL

      A     #bSTL
      JCN   skip
      L     #LOOPCOUNT
loop: T     #i
      L     "Tag_8"
      L     1
      +D
      T     "Tag_8"
      L     "Tag_8"
      L     1
      +D
      T     "Tag_8"
      L     "Tag_8"
      L     1
      +D
      T     "Tag_8"
      L     "Tag_8"
      L     1
      +D
      T     "Tag_8"
      L     "Tag_8"
      L     1
      +D
      T     "Tag_8"
      L     "Tag_8"
      L     1
      +D
      T     "Tag_8"
      L     "Tag_8"
      L     1
      +D
      T     "Tag_8"
      L     "Tag_8"
      L     1
      +D
      T     "Tag_8"
      L     "Tag_8"
      L     1
      +D
      T     "Tag_8"
      L     "Tag_8"
      L     1
      +D
      T     "Tag_8"
      L     "Tag_8"
      L     1
      +D
      T     "Tag_8"
      L     "Tag_8"
      L     1
      +D
      T     "Tag_8"
      L     "Tag_8"
      L     1
      +D
      T     "Tag_8"
      L     "Tag_8"
      L     1
      +D
      T     "Tag_8"
      L     "Tag_8"
      L     1
      +D
      T     "Tag_8"
      L     "Tag_8"
      L     1
      +D
      T     "Tag_8"
      L     "Tag_8"
      L     1
      +D
      T     "Tag_8"
      L     "Tag_8"
      L     1
      +D
      T     "Tag_8"
      L     "Tag_8"
      L     1
      +D
      T     "Tag_8"
      L     "Tag_8"
      L     1
      +D
      T     "Tag_8"
      L     #i
      LOOP  loop
skip: NOP 0
vs



Code:
IF NOT #bSTL THEN
    FOR #i := 1 TO #LOOPCOUNT DO
        "Tag_8" += 1;
        "Tag_8" += 1;
        "Tag_8" += 1;
        "Tag_8" += 1;
        "Tag_8" += 1;
        "Tag_8" += 1;
        "Tag_8" += 1;
        "Tag_8" += 1;
        "Tag_8" += 1;
        "Tag_8" += 1;
        "Tag_8" += 1;
        "Tag_8" += 1;
        "Tag_8" += 1;
        "Tag_8" += 1;
        "Tag_8" += 1;
        "Tag_8" += 1;
        "Tag_8" += 1;
        "Tag_8" += 1;
        "Tag_8" += 1;
        "Tag_8" += 1;
    END_FOR;
END_IF;
 
Not absolutely sure but like S5 the code is compiled into MC5/MC7, this is the binary that is sent to the PLC, as far as I can gather, SCL, LAD & FBD build almost the same code as ST in the binaries, there may be differences due to the way it is compiled, take for example FBD, there you can use some functions in series, not like ladder, this is due to the abillity of the EN & ENO pins of the functions what these are is like an equivelent of RLO so they probably use temps to store the RLO. You will probably find that the functions actually use MC7 code so a block move is just a for next loop in MC7.
S5 was the same, those protected blocks that you could buy are just the same as you write your own, I know that in S5, Siemens claimed these blocks were compiled, that was rubbish I opened one, they used a symbolic un conditional jump from the first segment to the next, that is illegal in S5 (you can jump round segments but that requires fixed reletive jumps i.e. JU HA0B5) but that is only as far as the IDE is concerned, if you opened the block all you got was segment 1
it contained
JU=M001
***
I removed the segment end & put a NOP0 in there with a hex editor, it then opened up the block which was standard STL however, there were some operands that do not seem to be documented. ( I worked with an ex Siemens engineer from Germany, so that is how they did the protected blocks & some MC7 Instructions) you paid huge sums for.
I do not have any idea about S7 but because Siemens mention MC7 code I bet there are similar structure in S7.
 

Similar Topics

Hi guys , I'm new with Allen Bradley, but I have experience with Tia portal (s7 1200 ,s7 1500) I want to convert my project from Tia portal to...
Replies
1
Views
95
Hi, I have had problem with upgrading some projects from v16 to v18. I tried it on 3 diffrent computers. I want to post this so that anyone that...
Replies
3
Views
116
Hello gentlemen, Im working on a small project on TIA Portal, about establishing a Modbus TCP connection between my ET200SP plc and a socomec...
Replies
11
Views
255
I am currently am in a PLC class and need urgent help on how the ladder logic would be laid out. I understand how to get the traffic lights to...
Replies
19
Views
413
Hello, If the date on the license manager of tia Portal has expired, can I still work with it? or is this just to keep the program up to date...
Replies
7
Views
196
Back
Top Bottom