Strange problem with Step7 timers/FCs

Pandiani

Lifetime Supporting Member
Join Date
Apr 2005
Location
Tz
Posts
718
Hello guys,
I have another, very weird problem with Step 7 functions.
In the attachments, you can find sorces for OB1 and two functions. Both functions have only one input and one output.
They use temp variables.
1. Do temp variables preserver values between function calls?
2.Are temp variables local to the function in which they're defined? Until this moment I thought so.

Problem is like I'm having interference between local variables of two different functions.
I use PLCSIM. Every time I press I0.0 (input to FC2), local temp variable Step2 inside FC1 is changing value, thus changing execution of FC1.
How this is possible?
Is this maybe a PLCSIM bug? I don't thinki so.
It seems that when I press I0.0, tmp2 variable inside FC 2 is set. Address of inside of FC2 tmp2 is same (bool 0.1) as address of temp variable "Step2" inside of FC1.

I'm asking these questions because I'm preparing to modify a PLC program which was not written by me, and I need to use timers. If this is work this way on real PLC, I'm going to mess up.

Please, execute this code and let me know if you're experiencing the sam problem.

P.S. When you compile source choose View->Lad (but you all probably know that :) )

Thanks
 
Last edited:
1. Do temp variables preserver values between function calls?
No.
2.Are temp variables local to the function in which they're defined? Until this moment I thought so.
You're right. Temp variables are local to the function.
So far, so good. But. There's only one memory range for all local variables and it isn't cleared between function calls. The same memory location is used over and over again. Therefor, at the start of a block, you cannot be sure what the state of a temp variable is. Always initialise temp variables before you use them.

Kind regards,
 
Hmm, that's OK, but I still don't understand why every change in I0.0 (tmp2) inside FC2 changes local varibale "Step1" inside FC1. That shouldn't be the case.
 
Hmm, that's OK, but I still don't understand why every change in I0.0 (tmp2) inside FC2 changes local varibale "Step1" inside FC1. That shouldn't be the case.
Maybe it should. I have yet to see any documentation which tells us what happens with the temp memory storage in between block calls. There are two ways to void this kind of behavior:
  • use IN/OUT type variables in stead of TEMP types in FC1 and assign M-bit to these
  • use a FB in stead of FC1 and use STAT variables in stead of TEMP
In any case, using uninitiated TEMP variables always means an insecure outcome.

Kind regards,
 
Here is one more example.
FC 3 has one input, one output and one temp.
FC 4 has one temp and output.
When input to FC3 is changing, its output is changing and also output of FC4 is changing in the same way.
So conclusion is that temporary variables inside functions are not local. Instead, for example tmp1 (bool 0.1) in FCn is exactly the same as tmp1 (bool 0.1) in FCm.

Didn't know that until now...
Temp variables are evil. They shoudn't be used unless you pay special attention.
 
Last edited:
Temp variables are evil. They shoudn't be used unless you pay special attention.
A little bit harsh on the wording, but correct. Always be careful when using temp variables.

Kind regards,
 
The L area is a stack. Local data is allocated from the stack as each block is called. As OB1 is at the top of the calling hierarchy, the local data used by OB1 is remembered(*) each time OB1 runs. As each block is called, a new section of the L stack is allocated.

If OB1 calls two functions (say FC1 and FC2 one after another) that both have the same Local data allocation, the two FC's are actually refering to exactly the same memory locations when referencing local data variables.

Depending on the call structure it is possible that the L area will remember the values in local data between block calls - a change to the call structure may then stop this behaviour.


(*) Beware that with indirect addressing using the V area, the local data area of a preceding block can be modifed by the block that is called. In the example above, FC1 is able to modify the local data associated with OB1
 
As has already been stated TEMP's are shared.

When you use a TEMP you MUST ALWAYS condition the TEMP BEFORE you use it.

This does not mean that you need to turn every TEMP to ZERO at the start, it just means before you use the TEMP variable you must have conditioned it in your logic.

In your first block FC1 for example

Code:
NETWORK
TITLE =

      A     #Input; 
      L     S5T#10S; 
      SD    T      1; 
      A     #Step2; 
      R     T      1; 
      NOP   0; 
      NOP   0; 
      A     T      1; 
      =     #Step1; 
NETWORK

You put A #Step2 ???? where is #Step2 conditioned, the answer is well after this point!

Therefore at the point you examine its state in netwrok 1, you realistically have no idea what state #Step2 is in, it could be anything.

If you wanted to do this then you should as suggested use a IN_OUT to remember the state between calls.

An FC is called a block WITHOUT memory for a reason.
 
Ok, I understand and I don't like that.
I though it is like local stack in case of function calles in C/C++ programming languages.
Here it's obvious that same memory is shared by two functions. It's easier to see this in second example FC3 and FC4.
Input FC3 | TmpFC3 | Output FC3 | TmpFC4 | Output FC4
Code:
   1        1          1      1        1
   0        0          0      0        0
Each time Input to FC3 is changed, both outputs (FC3 and FC4) are changed in the same way.
I though that with every function call, a new memory stack (which is LOCAL to that particular function) is created. But now, I know that's not te case. They use exactly the same temp memory.
One way to fix this besides using FBs and STAT or IN_OUT woud be to make sure tmp variables are not using same addresses. For example if tmp1 in FC3 is bool 0.1 then, temp variable inside FC4 shoul be bool 0.2. This way they won't use same address. I think that people with C/C++ background will make bug code. Now, with this new information I need to do revision of my last project changes. It works OK, but probably it can cause undefined and undesired behavior.
I'll try to avoid using temporary memory in functions in the future. I used to program in C and C++ before I learned STEP7 so I make some assumptions and use things for granted.

I was hoping PLCSIM is lying to me, but that's not the case.
 
Last edited:
Local stack for that block... your describing STAT variables in FB's.

TEMP is a replacement for scratch flags, where in S5 it was common practice to used flags above 250 as multiple use scratch flags. I you had Siemens standard blocks in S5 you had to be wary as Siemens used flagbytes above 250 as scratch in their blocks.

TEMP is the same thing, but has the added advantages that they allow scratch flags that don't eat into your internal flag allocation (as they did with S5) and allows you to name the scratch flag, so when you use them you know what their purpose is.
 

Similar Topics

We have an OPC server getting data from a Compactlogix PLC. The PLC also communicates with a Panelview and a couple VFDs via Ethernet/IP...
Replies
3
Views
1,165
I had a customer call about a machine counter not working. We checked hardware, determined the input was correctly functioning. In tracing...
Replies
9
Views
2,715
Hi Friends, I have a strange situation at hand. I wrote a Logic for Tank Over fill (5 Tanks). When Level switch senses level, it triggers Alarm...
Replies
10
Views
2,914
I have 3 identical CompactLogix L33ER's running in a factory and have always sent out automatic emails successfully. However, our company now has...
Replies
14
Views
6,090
Hi guys, So I added a routine in a L71, and as is my nature, I selected all of the rungs and pasted them into Notepad++ and then re-imported them...
Replies
9
Views
3,718
Back
Top Bottom