I am forced to really learn how to program a S7

Could s7guys method for passing shared db for function blocks be converted to scl code? Is there thing as uc of stl in scl?
http://www.plctalk.net/qanda/showpost.php?p=69112&postcount=31
That is what I suggested in post # 24:
The most obvious is to declare the structure in a UDT.
Then make a shared DB with variables dfined by the same UDT.
In the FC you make one input-output "pin" which is also defined by the UDT.
What happens with that approach is that a pointer is passed to the FC. Only, it is transparant to you, and you just use the variables as defined in the UDT.
Actually, it is the same that happens with an FB+IDB. Only with an FC+UDT+Shared DB you can fiddle even more with the structure of the data.
 
So how is it going ?

Anyway, before we discussed about declaring a UDT with all the necessary data for a PID controller. And then we need to modify each PIDs parameters.
I suggested to do it in a couple of ways in code, or from an HMI.

It just dawned on me, that it is possible to "individualise" the data declaration in SCL, in a way that it is not possible in STL, LAD or FBD.

A small example:
Code:
TYPE myUDT
    STRUCT
        // setting default values
        in1 : INT := 1 ; 
        in2 : INT := 2 ; 
        r1 : REAL := 1.1 ;
        r2 : REAL := 2.2 ;
    END_STRUCT
END_TYPE
 
DATA_BLOCK MyData
    STRUCT
        group1 : MyUDT ;
        group2 : MyUDT ;
        group3 : MyUDT ;
        group4 : MyUDT ;
    END_STRUCT
BEGIN
    // tweaking initial values of select variables:
    group1.in1 := 3 ;
    group2.r2 := 4.4 ;
END_DATA_BLOCK

So, it is also possible in this way. And I think this is what Peter complained about in post # 23.
 
OK, I am back at it again. Note that this time it is in STL

I started with something simple, a random number generator. It works. If no one finds any improvements I will post it in my
http://www.deltamotion.com/peter/S7/
directory

See:
http://www.codeproject.com/KB/recipes/SimpleRNG.aspx
The C version of the function has been tested against other programs that test for randomness. I am concerned that the constant 1/2^32 is not represented to enough digits but that is all that can be done with 32 bit reals.

Code:
FUNCTION_BLOCK "fbRNG"
TITLE =SimpleRNG.STL
//See
//http://www.codeproject.com/KB/recipes/SimpleRNG.aspx
VERSION : 0.1


VAR_OUTPUT
  rRandom : REAL ;    
END_VAR
VAR
  m_z : DWORD  := DW#16#1;    
  m_w : DWORD ;    
END_VAR
BEGIN
NETWORK
TITLE =
//http://www.codeproject.com/KB/recipes/SimpleRNG.aspx
      L     #m_z; // m_z = 36969 * (m_z & 65535) + (m_z >> 16);
      AD    DW#16#FFFF; 
      L     L#36969; 
      *D    ; 
      L     #m_z; 
      SRD   16; 
      +D    ; 
      T     #m_z; 

      L     #m_w; //  m_w = 18000 * (m_w & 65535) + (m_w >> 16);
      AD    DW#16#FFFF; 
      L     L#18000; 
      *D    ; 
      L     #m_w; 
      SRD   16; 
      +D    ; 
      PUSH  ; 
      T     #m_w; 

      L     #m_z; // u = (m_z << 16) + m_w
      SLD   16; 
      +D    ; 
      L     L#1; // (u + 1) * 2.328306435454494e-10
      +D    ; 
      DTR   ; 
      L     2.328306e-010; // 2.328306435454494e-10
      *R    ; 
      L     5.000000e-001; // result is now -0.5 t 0.5, must add 0.5 to get 0.0 to 1.0
      +R    ; 
      T     #rRandom; 
      BEU   ; 
END_FUNCTION_BLOCK
More to come as I figure out more things.
 
Last edited:
As there is no initial value for m_w, the default value of zero is used and hence m_w stays at zero.

How did you test this routine to say that it works ?

The PUSH and BEU instructions are redundant.
 
Last edited:
I had edited the initial values directly in the DB or so I thought. Perhaps I was only editing the current values.
I wasn't really that concerned because my intention is to read the system clock when both m_w and m_z are 0 and initialize the values from the system clock. This will be my call a function from a function test.
I will try with out the push and beu

Thanks

New updated version. This should be good. I had wanted the initial values of m_w and m_z to be 0. Hopefully Step7 initializes variables to 0 by default. Also, shouldn't the return value be in the accum1 after the call to "TIME_TCK". Normally one doesn't need to store a return value from a function before using it.
Code:
FUNCTION_BLOCK "fbRNG"
TITLE =SimpleRNG.STL
//See
//http://www.codeproject.com/KB/recipes/SimpleRNG.aspx
VERSION : 0.1


VAR_OUTPUT
  rRandom : REAL ;    
END_VAR
VAR
  m_z : DWORD ;    
  m_w : DWORD ;    
END_VAR
VAR_TEMP
  SysTick : TIME ;    
END_VAR
BEGIN
NETWORK
TITLE =
//http://www.codeproject.com/KB/recipes/SimpleRNG.aspx
      L     #m_w; 
      L     #m_z; 
      OD    ; 
      JN    NOTZ; 
      CALL "TIME_TCK" (
           RET_VAL                  := #SysTick);
      L     #SysTick; 
      T     #m_w; 
      T     #m_z; 
NOTZ: L     #m_z; // m_z = 36969 * (m_z & 65535) + (m_z >> 16);
      AD    DW#16#FFFF; 
      L     L#36969; 
      *D    ; 
      L     #m_z; 
      SRD   16; 
      +D    ; 
      T     #m_z; 

      L     #m_w; //  m_w = 18000 * (m_w & 65535) + (m_w >> 16);
      AD    DW#16#FFFF; 
      L     L#18000; 
      *D    ; 
      L     #m_w; 
      SRD   16; 
      +D    ; 
      T     #m_w; 

      L     #m_z; // u = (m_z << 16) + m_w
      SLD   16; 
      +D    ; 
      L     L#1; // (u + 1) * 2.328306435454494e-10
      +D    ; 
      DTR   ; 
      L     2.328306e-010; // 2.328306435454494e-10
      *R    ; 
      L     5.000000e-001; // result is now -0.5 t 0.5, must add 0.5 to get 0.0 to 1.0
      +R    ; 
      T     #rRandom; 
END_FUNCTION_BLOCK
 
Last edited:
Passing DB and offset to a function

I have written a GRI or Get Real Indexed function that requires that the DB and offset of of the real array be passed as two integers and an index as a 3. The function works no problem BUT, it is awkward to use because I must pass the DB number of the array and the offset within the DB to the base of the array. Isn't there a way of passing just the DB of a symbolic name and just the offset of the array within the DB? I hate hard coding ANYTHING if I don't need to.

I would have prefered to pass an ANY pointer to the FC but I can't do anything with an ANY pointer in the input area. Passing the array as an ANY pointer would have made this simple because the length and data type are built in and I could use a JL instruction using the data type to determine how many times the index register must be shifted. Then I would need only one Load Indexed and one Store Indexed instead of having one for every data type.

Isn't there an easy way to append rungs at the bottom of the program. I only see an insert rungs.
 
Last edited:
Symbolic address priority + SCL has almost relieved me from any absolute addressing.

Here is a sample SCL code for passing an array symbolically, and then working with the data almost completely symbolicaly.
Only non-symbolic code is the size of the array for the FOR loop. There ought to be a "sizeof" language element. Or global constants. Or both.

Code:
(* First define the basic type to work with *)
TYPE UDT_array
    STRUCT
        rVals : ARRAY[1..20] OF REAL ;
    END_STRUCT
END_TYPE
 
(* Create the data that is defined by the type *)
DATA_BLOCK myDB
    STRUCT
        somedata : UDT_array ;
        moredata : UDT_array ;
    END_STRUCT
BEGIN
END_DATA_BLOCK
 
(* A block that does something with the array data *)
FUNCTION  fc_array_test: VOID
 
VAR_INPUT
    indata: UDT_array ;
    rTestVal : REAL ;
END_VAR
VAR_OUTPUT
    outdata: UDT_array ;
END_VAR
VAR_TEMP
    i : INT ;
END_VAR
 
FOR i:=1 TO 20 BY 1 DO
    IF indata.rVals[i] > rTestVal THEN
        outdata.rVals[i] := indata.rVals[i] ;
    END_IF ;
END_FOR ;
 
END_FUNCTION
 
(* Running it all from OB1 *)
ORGANIZATION_BLOCK OB1
fc_array_test(indata:=myDB.somedata , rTestVal:=12.34 , outdata:=myDB.moredata);
 
END_ORGANIZATION_BLOCK

This is just an example. It would bring some other advantages to use an FB in stead of an FC for example.

I am finding myself rewriting some of my older code to SCL because it is easier to maintain.
 
Yep, that is what I wanted to do.

Peter - have a look at the following example. You can use an any pointer as an input and perform whatever processing you like.

http://www.plctalk.net/qanda/showpost.php?p=230568&postcount=3
I had tried
L P##AnySrc
and that didn't work for me for some reason. I tried your example and it worked. I had seen other cases where it worked with TEMP variables so I knew that P##pointer was the trick.

I noticed that you hard coded all your offsets. There isn't a way to define a UDT for the ANY pointer fields and use them instead of hard coded offsets is there?

You have done almost all the work. You should package this code. Now I can must make a LDI Load Indexed and Store Indexed that will do the trick instead having a Load and Store for each type.

Thanks again.
 
Last edited:
Thanks LD.

I think that your example works for basic elements. But what if it is an array of STRUCTs or UDTs ?
I tinkered myself with a sizeof function in SCL. However, it is not so simple, because you must make checks for that the data is plausible, i.e. if it fits within the given dataset, if it is a multiple of the given dataset etc.

Also, it would require that you get the sizeof value at runtime. What I am really after is that SCL calculates the value at compiletime. I cannot see why it is not possible. SCL calculates all the other sizes and addresses, so why not also the size of an array in number of array elements ?
 
Peter, you can use ctrl-R to append rungs. I know the description says "insert", but it actually appends.
I wonder if that is configurable some where. ctrl-R definitely inserts for me and if ctrl-R appends then how do you insert?

Right now ctrl-R inserts for me. I must click on the word Network and do the cut and paste to get the rung where I want it.

L D[AR2,P#0.0], I ran into another road block when trying to make a generic Load Index using an any pointer and a index as parameters. At first I tried to declare RET_VAL as ANY but that doesn't really make sense as then RET_VAL is a pointer to where? Making RET_VAL and seems to be only useful for building an ANY pointer but not for returning an element that can be of any type. One must pass a destination any pointer to where the result is going to be written and then the function looks a lot like yours only the destination would be just one element long. I could add extra code to let one select N elements out of an array.

The indexing feature would be easier to do in SCL. SCL also seems to support the equivalent of unions or 'views' as SCL puts it whereas STL does not. However, you should see the RNG,random number generator, function block written in SCL. Half the text is converting numbers from DWORDs TO DINTs and back then REALs and no code is generated for that.

I think that your example works for basic elements. But what if it is an array of STRUCTs or UDTs ?
I tinkered myself with a sizeof function in SCL. However, it is not so simple, because you must make checks for that the data is plausible, i.e. if it fits within the given dataset, if it is a multiple of the given dataset etc.
The compiler should make this easy it is in any real language.
I want our compiler writer to add a last(array), length(array) and sizeof(structure or array) functions to our product. The compiler should see sizeof(structure) and replace it with a constant and not all the code that L D [AR2,P#0.0] created.

Next week I will start on the Ethernet interface to our controller using the T blocks. Today we have our open house.
 

Similar Topics

is it possible to external read the Forced_value list from a PLC using UnityPRO? I need to get this data. It could be via modbus, ops... or even...
Replies
5
Views
2,444
So View SE 10 was the last to support HMI alarm tags. View SE 11 says you must migrate them to Alarm and Events. The View SE alarm summary will...
Replies
0
Views
1,895
I'm using an L33 PLC with an Ethernet I/P Point IO 1734-VHSC24 high speed counter to read in from an encoder, then calculating the counts per...
Replies
5
Views
1,750
So I have a dryer project that connects to the PLC and says "equal". When I connect it shows there are forced bits, but when I double-click on the...
Replies
3
Views
2,186
Hello All, I am using Allen Bradley Control Logix system, from the machine supplier I got the controller program developed in RS Logix 5000...
Replies
2
Views
2,033
Back
Top Bottom