Step 7 Classic: Array 0..19, Real, Instruction to shift the values.

AutomationTechBrian

Lifetime Supporting Member
Join Date
Jul 2013
Location
St. Cloud, MN
Posts
669
I'm still a little remedial with my Step 7 classic knowledge. I'm working on in Simatic Manager 5.5, SP4, and I need a little insight of how to accomplish a simple shift of values through an array.

My idea: I would create a data block, create an Array [0..19]. When a trigger bit is high, a Real value would be moved into the [0] address from a Load Cell Input (after going through a scale block). When another bit is high, I need the values of the array to shift to the next position, with the [19] value to be discarded. To be clear, the [0] value would then be 0 until the trigger bit moves a new Real value into that cell. What is the command to shift the array values?

These values will used in a graph to give the operator a visual trend of batches of cement.
 
there is probably a block move instruction, but it might only work here by shifting [1..19] to [0..18], and then you write the new Real value in to [19]. So the oldest value will be in [0], and the newest in [19]; does the order matter? If order does matter, you can do it with a separate array BUFFER[0..18] i.e. block move array[0..18] to BUFFER[0..18], then block move BUFFER[0..18] to array[1..19].


Edit: there does not seem to be a size parameter with the BLKMOV instruction, so this may not work.
 
Last edited:
Could do it in a loop using pointers i.e. create two pointers & load them with the address of array[19] & array[18] (call them pointer 1 & 2
transfer indirectly array[pointer 2] to array[pointer 1]
decrement the pointer
& loop back until pointer 2 = 0
L D[AR2,P#0.0] will put you right on this or perhaps he knows a simpler way, long time since I used S7.
 
1. If you have SCL, such a task would be simple in a FOR loop, looping backwards from Buffer[19] to Buffer[1] and setting Buffer[0]:=0

2. Use the canned function FC85 "FIFO" from the standard library under TI/S7 Converting Blocks.
edit: I see that the value that you want to buffer is a REAL. The canned function works with word-sized data.
If you convert the REAL to an INT, if only for the visualization, then you can use the FC85 "FIFO" function.

3. Use SFC20 "BLKMOV". The source and destinations are specified as ANY pointers.
Since you will be moving only part of the array, i.e. Buffer[0..18] to Buffer[1..19] the ANY pointers must be specified absolutely, i.e. as P#DB1.DBX2.0 BYTE 38, and not symbolically (*).
Also the source and destinations cannot overlap, so you would have to 1st copy to an intermediary array, and then again to the actual buffer array.
*: In SCL you can have multiple "view" of the same data, aka "AT" views, and then you can setup multiple declarations that covers different part of the same array, and thus you can program symbolically. But on the other hand, in SCL a FOR loop is easier still.
 
Last edited:
Hi everyone,
You may use Blkmov , e.g: where srcblk= P#DB605.DBX0.0 BYTE 18, and dstblk= P#DB605.DBX1.0 BYTE 18.

P#DB605.DBX0.0 = pointer
BYTE 18 = length

I hope this will be helpful to you.
 
@CMOlivira.

From the online help for SFC20 BLKMOV:


Also, a REAL is 4 Bytes.
@JesperMP
my bad, you are absolutely right.

to use blkmov, one option is to use a second auxiliary array and make two block move, but isn't a good thing to do. with few data don't have problem, but with large arrays, will be a waste of resources.
 
As LD pointed out a little messy but instead of using a loop & there is only 20 shifts then you could do it longhand.
Just do them on a one shot.
i.e.
on oneshot
AND oneshot (move Array[18] array[19])
move (array[17] to array[18)]
do this until move array[0] to array[1] then stick the new value in array[0]
 
https://support.industry.siemens.com/tf/ww/en/posts/fifo-for-s7-300/49258/?page=0&pageSize=10

?

Also, if S7 Classic can use pointers or indirect addressing, you can do it without a loop or twenty individual moves (indirect addressing form shown; pointers would be similar):

  • Two arrays of Reals, and one Real scalar:
    • circular_buffer[0..19]
    • trend_array[0..19] - the array to use for the HMI trend
    • new_scaled_value - i.e. the Load Cell value after scaling
  • Three integers:
    • next_buffer_index - initialize to 0
    • trend_index - initialize to 0
    • shifted_index
  • Two booleans:
    • insert_new_scaled_value_trigger
    • shift_buffer_trigger
  • On each scan
    • If one-shot shift_buffer_trigger is 1, then
      • decrement next_index_buffer by 1
      • If next_buffer_index is less than 0, then
        • Assign 19 to the value of next_buffer_index
      • Assign 0.0 to the value of circular_buffer[next_buffer_index]
    • If one-shot insert_new_scaled_value_trigger is 1, then
      • Assign the value of new_scaled_value to the value of circular_buffer[next_buffer_index]
    • Add next_buffer_index to trend_index, assign sum result to shifted_index
    • If shifted_index is greater than 19, then
      • Decrement shifted_index by 20
        • I.e. subtract 20 from shifted_index, put result in shifted_index
    • Assign value of circular_buffer[shifted_index] to value of trend_array[trend_index]
    • Increment trend_index by 1
    • If trend_index is greater than 20, then
      • Decrement trend_index by 20
Caveats

  • This uses scans as passes through a loop to load the HMI-displayed trend_array[0..19] continuously. It will take up to 20 scans for the trend array to catch up with either trigger event, but that should be a barely noticeable blip
  • Shifting and writing a 0.0 to the new location may not be necessary, unless you want the trend to show the 0.0 and the two triggers are indeed separate events to be tracked.
  • By the time you figure out what I am suggesting here, the longhand twenty individual moves will seem elegant by comparison ;)
 
Last edited:
I'll be working with this later today. I have a simple project with a simulated PLC that I'll use to play with ideas. It's a project I built from a YouTube Boiler program tutorial. It's handy because it has a "Real" value output that can be used, and a slider on the PLCSim for changing the thermocouple input. Someone may want to play with this, too, so I attached it to this post. I haven't added anything for this problem yet. The arrays in the DB were part of the tutorial.

I've got some things to accomplish this morning. I'll come back to this later this afternoon.
 

Similar Topics

I really struggle with STL in Siemens Step 7 Classic. I'll learn chunks, but then I don't use it enough to retain and build on the knowledge. When...
Replies
17
Views
3,144
I've been working for a customer with Siemens Step 7 (classic) PLC automation, using a Siemens Field Service Laptop, and V5.6 of Simatic Manager...
Replies
5
Views
2,942
I'm trying to figure out how to read the actual speed reference value from the move blocks, writing to a DB that is being sent to the VFD. For...
Replies
5
Views
2,618
Had to do my first live troubleshooting under pressure today with Siemens Step 7 Classic (v5.6). There was a contactor that wasn't pulling in and...
Replies
9
Views
2,481
I have for the longest time avoided using the S7-1500 because everyone warned me that TIA portal was a stinking pile of garbage to be avoided at...
Replies
25
Views
12,060
Back
Top Bottom