I am forced to really learn how to program a S7

Peter,

order of compilation is important.
What I would do is the the following:
1. Make manual entries in the Symbol table. For example: dbControl as DB1 or similar. Plan everything before compilation.
2. Compile everything step by step.

You can send all source files to me, to have a look. This is very interesting to me (not all this trouble with SCL, but rather logic behind this).
I wish you luck, this is going to be awesome process simulator.
 
The biggest problem in your code is that you have defined dbControl as a shared DB, with its own declaration (the declaration of dbControl also does not match fbControl).

But in the code in fbSODE, you use dbControl as an instance-DB for fbControl:
fbControl.dbControl(SP:=100.0, PV:=Y[0]);

So, you must decide what you want to do. Instance-DB, or shared DB ?

There are also some other minor errors.

I have seen nothing in the documentation that say that modules must be compiled in a certain order but that seems to be the case and even so the Simatic manager appears to not update the symbol table.
I dont know how you can have missed it. It says several places in the online help for example.

Least squares is the way to go if you want linear approximation.
Only, there is the problem with outliers being weighted too heavily.

Do you need the approximation over a wide range? That is when it gets difficult. It is best if one know around which point the approximation is going to be over. It is easy to do smoothing after the fact where there are N points before and N points after the point that is being smoothed and then the smoothing filter is moved over all the data.
In my case, I do have a reasonably well defined area. However, the measuring points can be scattered in a seemingly non-random way, i.e. they may be lumped into groups and not evenly distributed.

I provided an example of second order or quadratic AND cubic approximation last week and no one but Norm seemed to care.
[..]
There is an algoithm called Savitsky-Golay which is basically what I was trying to show last week in my movie.
You mean the "advanced rate of change" ? The header threw me off. I didnt see that it had to do with curve approximation. I started to watch the movie, but couldnt hear anything.
 
I have taken the liberty of rewriting your code, assuming you mean to use dbControl as an instance of fbControl.

I have no idea if the functionality is OK, but at least it compiles.
I had to delete the DBs a couple of times, including the symbols. It seems you have to do this if the declaration part of an FB is changed. It is irritating that SCL does not figure it out automatically.

Code:
(* CONTROL *)
 
FUNCTION_BLOCK fbControl
TITLE='fbControl'
VAR_INPUT
    SP: REAL;
    PV: REAL; 
END_VAR
VAR
   Kc:  REAL;                                   // Controller gain
   Ti:  REAL;                                   // Integrator gain
   Td:  REAL;                                   // Derivative gain
   DeltaT:  REAL := 0.01;                       // Simulation update time interval
   CO:  REAL;                                   // Control Output -100 to 100% 
   ER:  ARRAY[0..2] OF REAL;                    // Engineering units
   K:   ARRAY[0..2] OF REAL;                    // Gains
   MinCO: REAL;
   MaxCO: REAL;
END_VAR
 
IF K[0]=0.0 THEN
    K[0]:= Kc * (DeltaT / Ti + 1.0 + Td / DeltaT) ;
    K[1]:= -Kc - (2 * Td / DeltaT) ;
    K[2]:= Kc * Td / DeltaT;
END_IF;
 
ER[2]:= ER[1];
ER[1]:= ER[0];
ER[0]:= SP - PV;
CO:= CO + K[0] * ER[0] + (K[1] * ER[1]) + (K[2] * ER[2]);
CO:=LIMIT(MN:=0.0, IN:=CO, MX:=100.0);
 
//dbControl.CO:=CO; what is the original idea with this line ?
 
END_FUNCTION_BLOCK
 
 
(* define instance DB after FB *)
DATA_BLOCK dbControl  fbControl
BEGIN
END_DATA_BLOCK
 
 
(* SYSTEM OF DIFFERENTIAL EQUATIONS *)
DATA_BLOCK dbSODE
TITLE='dbSODE'
STRUCT
   K:  REAL;                                    // System gain
   A0: REAL;
   A1: REAL;
   A2: REAL;
   DeadTime: REAL;
   PVss:  REAL;                                 // ******t PV
   dydt: REAL;
END_STRUCT;
BEGIN
END_DATA_BLOCK
 
FUNCTION_BLOCK fbSODE
TITLE='fbSODE'
 
VAR_INPUT
    I: INT;
    X: REAL;
    Y: ARRAY[0..3] OF REAL;
END_VAR
 
CASE I OF
    0: "dbSODE".dydt:=Y[1];
    1: "dbSODE".dydt:=Y[2];
    2: "fbControl"."dbControl"(SP:=100.0 , PV:=Y[0] ); 
       "dbSODE".dydt:= - "dbSODE".A2 * Y[2] - "dbSODE".A1 * Y[1] + "dbSODE".A1 * "dbControl".K[0] * "dbControl".CO + "dbSODE".PVss ; 
       // in the above formula, I picked "K[0]" where you had written "K"
END_CASE;
 
END_FUNCTION_BLOCK
 
Hi Jesper,

my experience is that one needs to write symbolic names first in Symbol table (assuming blocks doesn't exists yet). Otherwise, compile problems are almost certain.
 
Hi Pandiani.

You can define symbolic names first, or set SCL to select block numbers automatically.

Instance DBS are more finicky than other blocks.
I usually have to clear the symbol completely from the symbol list if an FB declaration has changed.

The fastest when you are doing the brunt of the programming, is to always delete all instance DBs from the Manager (with the "delete symbol" ticked), and then setup SCL to select DB numbers automatically.
Later, when you dont want to goof things up on a running program, you switch to managing the symbols in a more controlled manner.

edit: My complaint with SCL is that since both FB declaration and instance DB are programmed in the SCL code, the compiler ought to automatically figure out the steps that I now have to do manually.
 
Hi Jesper,
my experience is that one needs to write symbolic names first in Symbol table (assuming blocks doesn't exists yet). Otherwise, compile problems are almost certain.
I have dbControl and fbControl in the symbol table but the problem is that I get an error that say the definitions don't match. I deleted the fbControl and dbControl, recompiled and then downloaded again so the fbControl and dbControl showed in the symbol table. These new definitions should match my code. I don't see the dbControl.CO defined in the symbol table. I can't see any of the fields defined in the symbol table. Just one line for dbControl itself, but not any of the fields inside.

Pandiani, you can see I split my code into three blocks now, Control, SODE, and RK4, just so that I could have a control over the order the symbols are defined. Obviously there is still no luck. I wonder if SCL is capable of executing a FB calling a FB that calls yet another FB.

Every time I program a S7 it is a struggle and what is worse is that most of my customers are more clueless about the magic sequence that must be done than I am. Most just use LAD and that is all and they expect me to write the block that gets called from LAD in OB1.
 
I don't see the dbControl.CO defined in the symbol table. I can't see any of the fields defined in the symbol table. Just one line for dbControl itself, but not any of the fields inside.
Yes. The symbol list that we mere mortas are allowed to see, does not display the underlying innards of the DBs.
I think you want it to be possible to pick the symbols from the symbol list when editing the SCL code. A reasonable assumption one should think.
This is one of the deficiencies of SCL. In the STL/LAD/BD editor, you will get symbol suggestions when you edit your code. Not so in SCL. I hope this will be a feature of the next generation STEP7/SCL.

Obviously there is still no luck.
How does the problem manifest itself ? Did you try to compile the code I wrote ? It compiles OK on my PC.

I wonder if SCL is capable of executing a FB calling a FB that calls yet another FB.
You 'merely' have to observe the order of the variable declarations stricly.
Variables that inherit declartions from UDTs or FBs must follow these UDTs and FBs. And that also goes for if the inheriting is nested.

I hope you soon get to the stage where the framework is finished, and the code tweaking can begin.
 
JesperMP said:
How does the problem manifest itself ?
The stupid ID will not even let me cut and paste and error message. I must copy the text by hand. It says:
E Ln 000029 Symbol table entry for instance DB or DB of type UDT does not match the called FB or UDT.
E L 00028 C 0000018 Data block not available.
W: L 29 C 00081 The time stamps of the blocks do not match

The second error is the fbControl.dbControl call.

Did you try to compile the code I wrote ? It compiles OK on my PC.
Yes, I cut and pasted it just as you have it and it didn't compile.

I saw you removed the dbControl variables and put them in the fbControl itself. That part I could get to compile but there is a problem with this approach. How do I change the static variables?

At first I was thinking of having a db that my 'methods' could access. These 'methods' would be functions. However, I couldn't find a way of passing a DB to a function. How lame. I can pass a structure to a function in C. Then I tried the FB approach where the DB is 'passed' to the FB by putting the .DB after the FB.

Honesly FBs are a pain an I wouldn't use them if I could pass a DB number a FC. I haven't see how one does that.


My gut tells me that if I use your example of fbControl I would need to declare an instance of it just like one must for F_TRIG and R_TRIG. That would be OK but I must have the ability to access the static variables from more than just one function so a shared DB is a must.

If there were only more examples........

You 'merely' have to observe the order of the variable declarations stricly.
Done that.

Variables that inherit declartions from UDTs or FBs must follow these UDTs and FBs. And that also goes for if the inheriting is nested.
Ancient programmer here. I know all about that.

I hope you soon get to the stage where the framework is finished, and the code tweaking can begin.
Me too. I have working C and Java versions of this code.

I am going to try MUCH simpler examples.
 
Last edited:
Yes, I cut and pasted it just as you have it and it didn't compile.
Put it all into one SCL source block.
Set block numbers to be selected automatically (Opions.. Customize..).
Delete all blocks in the Blocks folder.
edit: Important: When deleting the blocks in the Blocks folder, be sure to select to delete Symbols as well !
If it does not compile then, I'll be damned.

I saw you removed the dbControl variables and put them in the fbControl itself. That part I could get to compile but there is a problem with this approach. How do I change the static variables?
You mean you want make small modifications to each instance ?
It will be the same if you define everything as an UDT and pass it to an FC, as using FBs + IDBs.
The declaration of the core FB or UDT will decide the contents of the derived data, and you cannot break that dependency.
One approach is to split into a dependant part and freely definable part.
Another approach is to simply initialise the variables in code. That's what I do. In my code 95% if the variables just use the initial values. So it is a small task to go in an set the few variables that are 'special'.

At first I was thinking of having a db that my 'methods' could access. These 'methods' would be functions. However, I couldn't find a way of passing a DB to a function. How lame. I can pass a structure to a function in C. Then I tried the FB approach where the DB is 'passed' to the FB by putting the .DB after the FB.

Honesly FBs are a pain an I wouldn't use them if I could pass a DB number a FC. I haven't see how one does that.
There are several ways.
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.
 
Last edited:
JesperMP said:
Put it all into one SCL source block.
Set block numbers to be selected automatically (Opions.. Customize..).
Delete all blocks in the Blocks folder.
That is a kludge, not a solution. I shouldn't need to do that.

edit: Important: When deleting the blocks in the Blocks folder, be sure to select to delete Symbols as well !
If it does not compile then, I'll be damned.
It doesn't compile.

You mean you want make small modifications to each instance ?
Do you expect every PID to have the same parameters. I could pass all the parameters like Siemens does but that gets messy and is poor technique.

It will be the same if you define everything as an UDT and pass it to an FC, as using FBs + IDBs.
The declaration of the core FB or UDT will decide the contents of the derived data, and you cannot break that dependency.
One approach is to split into a dependant part and freely definable part.
Another approach is to simply initialise the variables in code. That's what I do. In my code 95% if the variables just use the initial values. So it is a small task to go in an set the few variables that are 'special'.

There are several ways.
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.
I will investigate that.

Meanwhile I am having troubles with even the basics. How does one monitor variables? I made a variable table. I have some variables in M memory but it only allows me to display the data in HEX or as a bool even though I declared it to REAL or INT. What ****.

I couldn't get the data to update in the variable table.
I am about to say f--- it and forget about it. I don't see how you guys can use this junk.

Just for sh!ts and gr!ns I think I will try writing a socket based Ethernet interface to our controller in java just to see how long it takes. Mean while I have a trade show to go to and will not get back to this until next week.
 
Peter, for variable table,
HEX is default. Just do right click (on HEX field) and choose type. You need to go "Online " to see updated values. Click on "glasses" (Monitor variables) icon to do that.

All these posts about SCL code compilation begins to worry me. I always made some simple blocks and didn't have a clue what it can turn to if something even a bit more complicated is tried.
 
Last edited:
Peter,
that is not completely true. You have a column named "Symbol" in your variable table. In that field you should type symbolic name and it will recognize address. You can also type symbolic name in the addrerss field. That works OK with M, I and Q variables. If you type address (DB1.DBX0.0), symbolic name will be automatically adeed to VAT. I have tried in other direction. I typed symbolic name ("block".input1) and it worked. You need to use "" with symbolic names for Dbs. I didn't experience any problems with VATs.
 
JesperMP said:
Put it all into one SCL source block.
Set block numbers to be selected automatically (Opions.. Customize..).
Delete all blocks in the Blocks folder.
That is a kludge, not a solution. I shouldn't need to do that.
We dont disagree.

It doesn't compile.
Something is wrong that we cannot see by just posting back and forth like this. That code, if you pasted into your program it as it was, compiles without problems on my PC. I'll offer to give your code a walk-through. Check your PM.

JesperMP said:
You mean you want make small modifications to each instance ?
Do you expect every PID to have the same parameters. I could pass all the parameters like Siemens does but that gets messy and is poor technique.
If it is the end-user that shall modify the PID parameters, then there will be a HMI that is linked to said parameters. If it shall be done in code, then there are two straightforward methods.
Assigning i/o pins to the block with all the relevant parameters.
Or, accessing the parameters in code.
 

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,446
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,758
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,034
Back
Top Bottom