Step7: Passing data & timers

MartyW

Member
Join Date
Nov 2009
Location
New Jersey
Posts
23
I am setting up the structure on a project that uses 6 identical manifolds. Each manifold has I/O, HMI events, timers , recipe steps, etc.

I would like to program a single set of FB's/FC's and use for all the manifolds.

I have currently set up a UDT that defines most of the data for a given manifold, placed the UDT into DB and made copies of the DB for each manifold.

I have a function block representing the generic manifold which takes the UDT type as and IN/OUT parameter. I have also configured the various timers needed for the process as IN parameters (only way to get a timer in).

I would like to define a series of FC's/FB's that break up the process into logical parts and call these from the generic Manifold FB.

My problem is that I cannot seem to pass on parameters passed into the Manifold FB into FC's/FB's that are called from the Manifold FB. This is true for my UDT<xx> and timers. I can pass on boolean data types.

Is there a way to get these complex data types into the sub-FB/FC's? Let me know if this is not comprehensible.

Thanks,

Marty
 
I agree with what LD said about the timers. When you place the SFB4 (for example) into your code, just right click and select "Change to Multiple Instance Call" then give it any name. You can then just pass the parameter of a time setpoint as data type "Time" (eg T#3s = 3 seconds) if necessary.

But as far as the UDT goes, I have found that using instance DBs essentially creates a sort-of UDT. Once you get the hang its way more simple IMHO.

Step 1: Create a FB for your generic manifold operation with appropriate inputs, outputs, in/outs, etc... For this example we'll say its FB10 named "Manifold".

Step 2: Create a second FB (FB11) Called "Manifold_Calls" that will contain 6 calls to FB10. When you drop FB10 into your ladder, again right click and select "Change to Multiple Instance Call" You can the give it a name like Manifold1. Keep dropping FB10s into your ladder until you have 6. Manifold1 thru Manifold6 for sake of argument.

Look at your "stat" declaration area in this FB now and you will see something like Manifold1.Open Manifold1.Pressure or whatever the parameters you defined in FB10. Cool huh? You have just built the structure. Next comes the really cool part.

Step 3. In your OB1 (or whatever is your main OB), put a call to FB11 "Manifold_Calls" and it will prompt you for a DB to assign to this call. Use any unused DB, DB11 for example (I often pair the instance DB# to be the same as the block I'm calling for easy reference). It will then "Generate" an instance DB for the call.

Step 4. Go name your new DB11 to something like MANIFOLD_PARAMS

Your done. Open up DB11 and you have a completely contained DB of all your tags. Browsing tags becomes very easy this way from both Step7 and in WinCC Flex.

MAKE SURE: Right click on your blocks folder and select properties. Under the address priority tab make sure the bottom right hand selection for symbolic addressing is checked. Otherwise things can really go to hell if you decide to add or subtract something from your instance DB later and all your refs are coded to an address :( ...

<Edit - notice that I strayed from your question somewhat, sorry, hopefully some useful info for you anyways>
 
Last edited:
kludgy - but it works

you have to do a little kludginess to pass a udt onto other functions - pass the udt as an IN in the primary Function Block then use SFC20 to copy this UDT into STAT memory
In the secondary functions use the UDT as an IN/OUT and pass in the Stat UDT at the end of the primary FB use SFC20 to copy the STAT UDT to an OUT UDT it would be the same DB address as the in.... I am sure there is a more elegant solution with less block copies, but it does work... source file below... a
"PumpStuff" = UDT1
"Sub_PumpFB" = FB2
"Overall_PumpFB" = FB1


TYPE "PumpStuff"
VERSION : 0.1

STRUCT
Start : BOOL ;
Stop : BOOL ;
DelayTime : TIME := T#5S;
alarm : BOOL ;
speed : INT ;
etc : STRING [20 ];
run : BOOL ;
running : BOOL ;
END_STRUCT ;
END_TYPE
FUNCTION_BLOCK "Sub_PumpFB"
TITLE =
VERSION : 0.1

VAR_IN_OUT
statpump : "PumpStuff";
END_VAR
VAR
timer1 : "TON";
END_VAR
BEGIN
NETWORK
TITLE =start pump after a delay
A( ;
A #statpump.Start;
AN #statpump.Stop;
= L 0.0;
BLD 103;
CALL #timer1 (
IN := L 0.0,
PT := #statpump.DelayTime,
Q := #timer1.Q,
ET := #timer1.ET);
A BR;
) ;
A #timer1.Q;
S #statpump.run;
NETWORK
TITLE =stop pump running
A #statpump.run;
A #statpump.Stop;
R #statpump.run;
END_FUNCTION_BLOCK
FUNCTION_BLOCK "Overall_PumpFB"
TITLE =
VERSION : 0.1

VAR_INPUT
pumpin : "PumpStuff" ;
END_VAR
VAR_OUTPUT
pumpout : "PumpStuff";
END_VAR
VAR
pump : "PumpStuff";
subroutine : "Sub_PumpFB";
END_VAR
VAR_TEMP
sfc20_error : INT ;
END_VAR
BEGIN
NETWORK
TITLE =
CALL "BLKMOV" (
SRCBLK := #pumpin,
RET_VAL := #sfc20_error,
DSTBLK := #pump);
NOP 0;
NETWORK
TITLE =
CALL #subroutine (
statpump := #pump);
NOP 0;
NETWORK
TITLE =
CALL "BLKMOV" (
SRCBLK := #pump,
RET_VAL := #sfc20_error,
DSTBLK := #pumpout);
NOP 0;
NETWORK
TITLE =
NETWORK
TITLE =
NETWORK
TITLE =
CALL "BLKMOV" (
SRCBLK := #pumpin,
RET_VAL := #sfc20_error,
DSTBLK := #pump);
NOP 0;
END_FUNCTION_BLOCK
 
Thanks for the feedback

Some comments on the feedback:

I will look into the IEC timers but I can't address all my ignorance in one project. Right now, I see how to pass a type "timer" into an FB (which I assume is an S5 timer).

On the more general structure issue, I seem to be running into a fundamental restriction in Step7 on passing complex data types between FB's (and FC's). They can only be passed IN to IN or OUT to OUT. You cannot pass complex data types from IN/OUT to IN/OUT. Yet this is precisely the functionality I need. Included is a page from a manual describing this restriction. Sylent's suggestion seems to be a way around this restriction. However, I am going to pass on it for now. Others may have to support this code and this quasi-object oriented structure is already a stretch without adding a layer of kludge (and non-ladder logic programming to implement the kludge?).

I think I understand lakesideBC's suggestion. However, my data set for each manifold has about 80 elements. This method would seem to require large parameter assignment lists for the FB's with a lot of assignment work in addition to the coding work.

My plan now is to flatten my structure. Instead of having OB1 call a Manifold which, in turn, calls 10-15 FB/FC's which break up the work into logical units, I will have OB1 call the 10-15 FB/FC's directly, passing the data sets for the respective manifolds. This will allow me to pass the respective data sets for each manifold as an IN/OUT parameter. For any sub-FB/FC's (there will still be some), I will have to break up the data set and pass the individual elements needed. Hopefully none of these sub-FB/FC's will require large parameter lists.

Instead of 6 calls to a "Manifold" FB from OB1, I will have 60-90 calls. Not as inherently easy to follow but there will still be a single data set for each manifold that should be easy to understand and reference from the HMI.

Let me know if you think I am on the wrong track. Up until now, finding these roadblocks has been time consuming and frustrating but haven't required me throwing away much code. If I run into a new roadblock after developing a lot of process code that may need to be scrapped, I'll have to consider a mental institution.
 

Similar Topics

This is the first time I am working with Simatic Manager Step7 as I started my siemens journey with TIA which is pretty easy and do a lot of stuff...
Replies
3
Views
144
When you download a DB, the values get overwritten by what is in the "actual" column in offline DB. Does this happen at the start of the PLC...
Replies
6
Views
142
Hello Inside a FB, I´m trying to transfer a string from a DB to a IN_OUT var that was define as a UDT. The problem is that i can´t determine the...
Replies
4
Views
128
Hi all, I am trying to convert RSLogix 5000 program to Step7. I need to bit shift left my array of double integers for tracking the product on...
Replies
2
Views
520
I have a word in some DB which I want to load to AR1 and use as a pointer. In order to do this I need to write L DBxy.DBW xy SLD 3 LAR1 I...
Replies
3
Views
533
Back
Top Bottom