S7 - More trouble with Timers, or maybe not?

RMA

Member
Join Date
Sep 2004
Location
North of Hamburg, Germany
Posts
2,052
I spent the best part of a day on site last week trying to get this working, to no avail (fortunately they were so far behind with the H/W that I had plenty of time to myself!).

I'm not sure whether it's my old problem with Timers, but I have a sneaky feeling it might be something else this time, Local Data problems, perhaps?

Either way, I've got to the point where I can't see the wood for the trees now, so I'd be grateful if some of the usual suspects :D could take a look at this for me.

The file is a normal Step7 AWL source file renamed to FB3.txt so as to be able to upload it.

Code:
FUNCTION_BLOCK "INIT Module LTS"
TITLE =Initialisiere Lasttrennschalter (LST) beim RESET.
//This FB is called from FB99 with a Module Number as Input Parameter. The Block 
//then Closes the motor driven switch to short circuit the Crowbar resistors and 
//opens the switches connecting the POS and NEG Outputs of the capacitors to the 
//Kollektors.
VERSION : 0.1
 
VAR_INPUT
Module_Nr : INT ; 
END_VAR
VAR
Trigger : BOOL ; //Trigger for Timers
First_Time : BOOL ; 
Hilfsmerker : BOOL ; //Hilfsmerker für Flanke 
END_VAR
VAR_TEMP
Module_Base : INT ; 
Output_Crowbar : DWORD ; 
Output_LTS_NEG : DWORD ; 
Output_LTS_POS : DWORD ; 
END_VAR
BEGIN
NETWORK
TITLE =Init
	 U	 #First_Time; 
	 SPB strt; 
	 SET ; 
	 R	 #Trigger; //Initialise Delay timer
	 S	 #First_Time; //and set First_Time Flag
NETWORK
TITLE =Get Module Number and calaculate position of first Output
//There is nothing clever here, the pattern of the PAW Outputs repeats itself for 
//each module and each Module has 4 Bytes of Outputs. The only oddity comes from 
//the consolidation of the original two 1,44 MJ Modules, 11 and 12, to 
//one 2,88 MJ Module. As a result of this, there is a gap of four unused 
//Addresses in the Module Outputs at this point.
strt: NOP 0; 
	 L	 #Module_Nr; 
	 L	 11; //Check for Modules 12 and higher
	 >I	; 
	 SPB Top; 
	 DEC 1; //Decrement because Module 1 starts at A0.0
	 L	 4; //Each Module has 4 Bytes of Outputs
	 *I	; 
	 T	 #Module_Base; //Save as Pointer Base
	 SPA cont; //and start opening LTSs
Top: NOP 0; 
	 TAK ; //Get Module Nr. back in AKKU1
	 L	 4; //No need to subtract 1 here because of
	 *I	; //missing Module following upgrade of 
	 T	 #Module_Base; //Module 11 to 2.88 MJ (Prev. 11 & 12 combined)
NETWORK
TITLE =Form Pointer and Output "CLOSE" Crowbar LTS Pulse.
cont: NOP 0; 
	 L	 P#0.0; 
	 L	 #Module_Base; 
	 SLD 3; //Convert Base Address to Byte.Bit format
	 +D	; 
	 L	 1; //Add Bit Offset for Crowbar LTS-ZU
	 +D	; 
	 T	 #Output_Crowbar; 
	 U	 #Trigger; 
	 L	 S5T#1S; 
	 SV	"T_LTS_CROWBAR"; 
	 U	 "T_LTS_CROWBAR"; 
	 =	 A [#Output_Crowbar]; 
NETWORK
TITLE =Form Pointer and Output "OPEN" NEG LTS Pulse.
	 L	 P#0.0; 
	 L	 #Module_Base; 
	 SLD 3; //Convert Base Address to Byte.Bit format
	 +D	; 
	 L	 9; //Add Bit Offset for LTS_NEG_AUF
	 +D	; 
	 T	 #Output_LTS_NEG; 
	 U	 #Trigger; 
	 L	 S5T#1S; 
	 SV	"T_LTS_NEG"; 
	 U	 "T_LTS_NEG"; 
	 =	 A [#Output_LTS_NEG]; 
NETWORK
TITLE =Form Pointer and Output "OPEN" POS LTS Pulse.
	 L	 P#0.0; 
	 L	 #Module_Base; 
	 SLD 3; //Convert Base Address to Byte.Bit format
	 +D	; 
	 L	 7; //Add Bit Offset for LTS_POS-AUF
	 +D	; 
	 T	 #Output_LTS_POS; 
	 U	 #Trigger; 
	 L	 S5T#1S; 
	 SV	"T_LTS_POS"; 
	 U	 "T_LTS_POS"; 
	 =	 A [#Output_LTS_POS]; 
NETWORK
TITLE =Set Trigger Bit to start Timers
//Trigger is also used by calling Block, FB99, as BUSY Flag by accessing it 
//directly in the IDB for FB3.
	 NOP 0; 
	 U	 #Trigger; 
	 L	 S5T#10S; 
	 SV	"T_LTS_INIT_PERIOD"; 
	 SET ; 
	 S	 #Trigger; 
NETWORK
TITLE =
	 U	 "T_LTS_INIT_PERIOD"; 
	 FN	#Hilfsmerker; 
	 R	 #Trigger; //Clear BUSY
	 R	 #First_Time; 
END_FUNCTION_BLOCK

Edit: Hey, that's neat - automatic scrolling windows with the [ code ] command!
 
Last edited:
After a quick look, (and realising the STL is in German) it looks like you are using a hardcoded timer number SV "T_LTS_CROWBAR";

Is this block called more than once ? If so, you need to pass in the timer or indirectly address the timers or use SFB4.
 
Yes, the three LTS Timers are normal S5Timers (T508 - T510)they are only used in this Block and my intention is that on each call, FB3 runs to completion, i.e. the Timers have expired, before FB99 tries to call FB3 again. In this way I was hoping to be able to use the same Timer for each module. The fact that the complete RESET would then take > 20 seconds is not a problem at this point in the program execution because it occurs in parallel to a whole load of operator set-up input.

I even tried having a separate overall Timer of 1.1 seconds to be absolutely certain tht the LTS Timers would have expired (yes, I know it was redundant, but I was getting desperate! :) ), but that didn't make any difference.

Actually, it occurs to me that I haven't stated exactly what the problem is: The Timers actually fire OK for 1 second, but for some reason, the calling FB doesn't recognise that FB3 has completed. In the version as posted the Timers fire once and that's it. In the version where I had the separate Timer for the "Busy" signal, when I pushed its period up to ten seconds the FB3 Timers would retrigger every 10 seconds, but always on the first output. In other words FB99 was not recognising the end of the sequence and decrementing the loop counter to move on to the next module.

At this point it occurs to me that I ought to post FB99 as well, because we may be looking in the wrong place for the source of the problem!

Code:
FUNCTION_BLOCK "LTS_INIT"
TITLE =Öffnet alle motorgetriebene Schalter beim RESET.
AUTHOR : RMA
NAME : LTS_INI
VERSION : 0.1

VAR
  Modul_Nr : INT ; 
  LTS_Trigger : BOOL ; 
  First_Time : BOOL ; 
  IEC_Timer_A90_1 : "TP"; 
  IEC_Timer_A90_3 : "TP"; 
  IEC_Timer_A90_5 : "TP"; 
  IEC_Timer_A90_7 : "TP"; 
  IEC_Timer_A91_1 : "TP"; 
  IEC_Timer_A91_3 : "TP"; 
  IEC_Timer_A91_5 : "TP"; 
  IEC_Timer_A91_7 : "TP"; 
  IEC_Timer_A92_1 : "TP"; 
  IEC_Timer_A92_3 : "TP"; 
  IEC_Timer_A92_5 : "TP"; 
  IEC_Timer_A92_7 : "TP"; 
  IEC_Timer_A93_1 : "TP"; 
  IEC_Timer_A93_3 : "TP"; 
  IEC_Timer_A93_5 : "TP"; 
  IEC_Timer_A93_7 : "TP"; 
  IEC_Timer_A94_1 : "TP"; 
  IEC_Timer_A94_3 : "TP"; 
  IEC_Timer_A94_5 : "TP"; 
  IEC_Timer_A94_7 : "TP"; 
  IEC_Timer_A95_1 : "TP"; 
  IEC_Timer_A95_3 : "TP"; 
END_VAR
BEGIN
NETWORK
TITLE =
	  U	 #First_Time; //If already through first pass 
	  SPB   strt; //goto Start
	  SET   ; 
	  S	 #First_Time; //Set First Time through Flag
	  R	 #LTS_Trigger; //Trigger Bit for UV22 LTS Timers
NETWORK
TITLE =Prime Loop Counter
strt: NOP   0; 
	  U	 #First_Time; //already started?
	  SPB   next; 
	  L	 21; //Init Modul_Nr with 21
NETWORK
TITLE =Initiert Öffnung der Last-Trennschalter, nach Strom-Ausfall etc.
next: NOP   0; 
	  T	 #Modul_Nr; 
	  CALL "INIT Module LTS" , "Instanz DB für FB3" ;
	  U	 "Instanz DB für FB3".Trigger; //Check BUSY in FB3 Instanz DB
	  BEB   ; //if so exit
	  L	 #Modul_Nr; 
	  LOOP  next; 

NETWORK
TITLE =Open UV22 LSTs
	  NOP   0; 

	  CALL #IEC_Timer_A90_1 (
		   IN					   := #LTS_Trigger,
		   PT					   := T#1S,
		   Q						:= "LSK_1_AUF_Labor_14_UV-22");
	  CALL #IEC_Timer_A90_3 (
		   IN					   := #LTS_Trigger,
		   PT					   := T#1S,
		   Q						:= "LSK_1_AUF_Labor_15_UV-22");
	  CALL #IEC_Timer_A90_5 (
		   IN					   := #LTS_Trigger,
		   PT					   := T#1S,
		   Q						:= "LSK_1_AUF_Labor_16_UV-22");
	  CALL #IEC_Timer_A90_7 (
		   IN					   := #LTS_Trigger,
		   PT					   := T#1S,
		   Q						:= "LSK_2_AUF_Labor_15_UV-22");
	  CALL #IEC_Timer_A91_1 (
		   IN					   := #LTS_Trigger,
		   PT					   := T#1S,
		   Q						:= "LSK_3_AUF_Labor_14_UV-22");
	  CALL #IEC_Timer_A91_3 (
		   IN					   := #LTS_Trigger,
		   PT					   := T#1S,
		   Q						:= "LSK_3_AUF_Labor_15_UV-22");
	  CALL #IEC_Timer_A91_5 (
		   IN					   := #LTS_Trigger,
		   PT					   := T#1S,
		   Q						:= "LSK_3_AUF_Labor_16_UV-22");
	  CALL #IEC_Timer_A91_7 (
		   IN					   := #LTS_Trigger,
		   PT					   := T#1S,
		   Q						:= "LSK_4_AUF_Labor_14_UV-22");
	  CALL #IEC_Timer_A92_1 (
		   IN					   := #LTS_Trigger,
		   PT					   := T#1S,
		   Q						:= "LSK_4_AUF_Labor_15_UV-22");
	  CALL #IEC_Timer_A92_3 (
		   IN					   := #LTS_Trigger,
		   PT					   := T#1S,
		   Q						:= "LSK_4_AUF_Labor_16_UV-22");

NETWORK
TITLE =Open A/B LTS for Modules 16 - 19 Lab select for Modules 20 - 21
	  CALL #IEC_Timer_A92_5 (
		   IN					   := #LTS_Trigger,
		   PT					   := T#1S,
		   Q						:= "LSM_16_AUF_Koll_1");
	  CALL #IEC_Timer_A92_7 (
		   IN					   := #LTS_Trigger,
		   PT					   := T#1S,
		   Q						:= "LSM_16_AUF_Koll_2");
	  CALL #IEC_Timer_A93_1 (
		   IN					   := #LTS_Trigger,
		   PT					   := T#1S,
		   Q						:= "LSM_17_AUF_Koll_1");
	  CALL #IEC_Timer_A93_3 (
		   IN					   := #LTS_Trigger,
		   PT					   := T#1S,
		   Q						:= "LSM_17_AUF_Koll_2");
	  CALL #IEC_Timer_A93_5 (
		   IN					   := #LTS_Trigger,
		   PT					   := T#1S,
		   Q						:= "LSM_18_AUF_Koll_1");
	  CALL #IEC_Timer_A93_7 (
		   IN					   := #LTS_Trigger,
		   PT					   := T#1S,
		   Q						:= "LSM_18_AUF_Koll_2");
	  CALL #IEC_Timer_A94_1 (
		   IN					   := #LTS_Trigger,
		   PT					   := T#1S,
		   Q						:= "LSM_19_AUF_Koll_1");
	  CALL #IEC_Timer_A94_3 (
		   IN					   := #LTS_Trigger,
		   PT					   := T#1S,
		   Q						:= "LSM_19_AUF_Koll_2");
	  CALL #IEC_Timer_A94_5 (
		   IN					   := #LTS_Trigger,
		   PT					   := T#1S,
		   Q						:= "LSM_20_AUF_Labor_13_1");
	  CALL #IEC_Timer_A94_7 (
		   IN					   := #LTS_Trigger,
		   PT					   := T#1S,
		   Q						:= "LSM_20_AUF_Labor_13_2");
	  CALL #IEC_Timer_A95_1 (
		   IN					   := #LTS_Trigger,
		   PT					   := T#1S,
		   Q						:= "LSM_21_AUF_Labor_13_1");
	  CALL #IEC_Timer_A95_3 (
		   IN					   := #LTS_Trigger,
		   PT					   := T#1S,
		   Q						:= "LSM_21_AUF_Labor_13_2");
	  S	 #LTS_Trigger; //Set Trigger after first Time through
	  UN	#IEC_Timer_A95_3.Q; 
	  BEB   ; 
NETWORK
TITLE =
	  NOP   0; 
	  U	 "LSM_21_AUF_Labor_13_2"; 
	  BEB   ; 
	  SET   ; 
	  R	 "M_DO_LTS_RESET"; 
	  R	 #First_Time; 
END_FUNCTION_BLOCK

By the way, the IEC Timers above came later, because I ran out of normal S5 Timers. They are used to open auxiliary switches, which I didn't originally intend to include in the RESET program, but later changed my mind.
 
1. When FB99 is called for the first time, Modul_Nr gets loaded with 21
On subsequent calls, the code will jump to the label "nxt" and Modul_Nr will now be loaded with whatever is in the accumulator - probably a random number.

2. There is no parameter in the call to FB3 from FB99, but you have Modul_Nr declared in the static data area of FB99 and as a parameter of FB3 - either I'm missing something or this/these are the problem(s).
 
Just took a little time to see if something stuck out.

This code in FB3 doesnt work:

U "T_LTS_INIT_PERIOD";
FN #Hilfsmerker;
R #Trigger; //Clear BUSY
R #First_Time;

Reason is that #Trigger is defined as an INPUT_VAR, and thus doesnt have memory between scans. It should be an IN_OUT if you want that.

I dont know if it has any relevance to your problems.

edit: Actually I am thinking FC, what happens if it is an FB ?
I think that the "Trigger" input pin will overwrite the value every time FB3 is scanned.
The problem can be that the timers doesnt see an off to on transition.
 
Last edited:
1. When FB99 is called for the first time, Modul_Nr gets loaded with 21
On subsequent calls, the code will jump to the label "nxt" and Modul_Nr will now be loaded with whatever is in the accumulator - probably a random number.
Since I've got two weeks holiday coming up, it's going to be at least three weeks before I get on site to check it, but I think this may well turn out to be the main problem. I must admit, I'm not too surprised I didn't spot that one after hours of looking, definitely one of those places where after a certain time you see what you expect to see!

2. There is no parameter in the call to FB3 from FB99, but you have Modul_Nr declared in the static data area of FB99 and as a parameter of FB3 - either I'm missing something or this/these are the problem(s).
That should of course have had #Modul_Nr as its parameter and actually, it probably did have most of the time because the only available Module was Module 11 and its outputs were getting pulsed OK, but then the program stayed there and didn't move on.

I guess the parameter got lost one time after I'd made changes to FB3 and had to redo the call.

Reason is that #Trigger is defined as an INPUT_VAR, and thus doesnt have memory between scans. It should be an IN_OUT if you want that.
No, Jesper, #Trigger is a STAT, however, it still may be a part of the problem, because basically the problem is that FB99 is not moving on after the Trigger Pulse is finished. (i.e. FB99 never got to Network 4).

Edit: On second thoughts, when I was using the separate Timer at 10 secs in FB3 to provide the Busy signal for FB99, the Outputs for Module 11 were retriggering (pulsing) every ten seconds - I think that also points a bit more in the direction of Simon's suggestion Nr. 1.

I'll have to see if I can persuade enough of this to run in PLCSim, maybe I can try and test it that way.
 
Last edited:
First off, thanks to Jesper for enthusing sufficiently about PLCSim to encourage me to go back and try using it again. When I tried it with ProTool a couple of weeks ago the results were a bit mixed with several functions associated with Buttons not being executed, but for this problem it has worked perfectly - probably helped by the fact that I'm not interested in the feedback signals here, so there's no frantic clicking necessary to try to set the F/B inputs before the discrepancy timers time out! Anyway, we're nearly there. Everything is now working fine except for shutting everything down when it's finished. To recap, the problems were:

1) Simon's 1st offering, the jump to "next" without taking the value of #Modul_Nr along on the way.

2) In NW2 after doing the compare for Module Nr. > 11, I forgot to swap the AKKUs to get the Module Nr. back in AKKU1, so thereafter it was continually hitting Module 11 - unfortunate coincidence that on-site, this was the one I chose to test with!

3) I had to add a line after the LOOP command to save Modul_Nr=0 so that I could then use that to jump to the UV22 NW when the Modules were all finished.

So now the whole RESET is working fine all I need now is to shut the thing down cleanly as in NW6 by clearing "M_DO_LTS_RESET" and #First_Time.

It didn't take long to see that the way I've got it at this point at the end of NW5 isn't going to work, but everything else I can think of either involves yet more Timers (well one more anyway) or worse.

Anybody got any suggestions how to shut this down cleanly and simply once the UV22 Timers are finished - I'm assuming that I do need to keep calling FB99 until the UV22 1 sec. Timers have expired, or else they will hang - or is that a false assumption, can I just abandon FB99 once the Timers have started?
 
Well I've got it all working now, if anybody wants to take a look and tell me where I could improve it, especially as far as the shut down at the end is concerned, I'd be grateful.

One peculiar thing that I don't understand is that in the VAT, after everthing is finished, in the IDB both LTS_Trigger and UV22_Active are set. UV22_Active is clear enough and in any case it's not a problem because I clear both Bits on the first time through. But I don't understand how LTS_Trigger is getting set again after being cleared in NW6!

Code:
FUNCTION_BLOCK "LTS_INIT"
TITLE =Öffnet alle motorgetriebene Schalter beim RESET.
AUTHOR : RMA
NAME : LTS_INI
VERSION : 0.1

VAR
  Modul_Nr : INT ; 
  LTS_Trigger : BOOL ; 
  UV22_Active : BOOL ; //Used to Trigger Reset - Blocks UN #IEC_Timer_A95_3.Q Abfrage first time thru.
  First_Time : BOOL ; 
  IEC_Timer_A90_1 : "TP"; 
  IEC_Timer_A90_3 : "TP"; 
  IEC_Timer_A90_5 : "TP"; 
  IEC_Timer_A90_7 : "TP"; 
  IEC_Timer_A91_1 : "TP"; 
  IEC_Timer_A91_3 : "TP"; 
  IEC_Timer_A91_5 : "TP"; 
  IEC_Timer_A91_7 : "TP"; 
  IEC_Timer_A92_1 : "TP"; 
  IEC_Timer_A92_3 : "TP"; 
  IEC_Timer_A92_5 : "TP"; 
  IEC_Timer_A92_7 : "TP"; 
  IEC_Timer_A93_1 : "TP"; 
  IEC_Timer_A93_3 : "TP"; 
  IEC_Timer_A93_5 : "TP"; 
  IEC_Timer_A93_7 : "TP"; 
  IEC_Timer_A94_1 : "TP"; 
  IEC_Timer_A94_3 : "TP"; 
  IEC_Timer_A94_5 : "TP"; 
  IEC_Timer_A94_7 : "TP"; 
  IEC_Timer_A95_1 : "TP"; 
  IEC_Timer_A95_3 : "TP"; 
END_VAR
BEGIN
NETWORK
TITLE =
	  U	 #First_Time; //If already through first pass 
	  SPB   strt; //goto Start
	  SET   ; 
	  S	 #First_Time; //Set First Time through Flag
	  R	 #LTS_Trigger; //Trigger Bit for UV22 LTS Timers
	  R	 #UV22_Active; //Flag to delay Flag RESET after UV22
	  L	 21; //Init Modul_Nr with 21
	  T	 #Modul_Nr; 
NETWORK
TITLE =Prime Loop Counter
strt: NOP   0; 
	  L	 #Modul_Nr; //Get Module Nr. 
	  L	 0; //Finished Modules?
	  ==I   ; 
	  SPB   UV22; //If so do UV22
	  TAK   ; //Get Module Nr. back in AKKU1
NETWORK
TITLE =Initiert Öffnung der Last-Trennschalter, nach Strom-Ausfall etc.
next: NOP   0; 
	  T	 #Modul_Nr; 
	  CALL "INIT Module LTS" , "Instanz DB für FB3" (
		   Module_Nr				:= #Modul_Nr);
	  U	 "Instanz DB für FB3".Trigger; //Check BUSY in FB3 Instanz DB
	  BEB   ; //if so exit
	  L	 #Modul_Nr; 
	  LOOP  next; 
	  T	 #Modul_Nr; //When 0 transfer to Modul_Nr
	  BEB   ; //so that next time UV22 is started
NETWORK
TITLE =Open UV22 LSTs
UV22: NOP   0; 
	  CALL #IEC_Timer_A90_1 (
		   IN					   := #LTS_Trigger,
		   PT					   := T#1S,
		   Q						:= "LSK_1_AUF_Labor_14_UV-22");
	  CALL #IEC_Timer_A90_3 (
		   IN					   := #LTS_Trigger,
		   PT					   := T#1S,
		   Q						:= "LSK_1_AUF_Labor_15_UV-22");
	  CALL #IEC_Timer_A90_5 (
		   IN					   := #LTS_Trigger,
		   PT					   := T#1S,
		   Q						:= "LSK_1_AUF_Labor_16_UV-22");
	  CALL #IEC_Timer_A90_7 (
		   IN					   := #LTS_Trigger,
		   PT					   := T#1S,
		   Q						:= "LSK_2_AUF_Labor_15_UV-22");
	  CALL #IEC_Timer_A91_1 (
		   IN					   := #LTS_Trigger,
		   PT					   := T#1S,
		   Q						:= "LSK_3_AUF_Labor_14_UV-22");
	  CALL #IEC_Timer_A91_3 (
		   IN					   := #LTS_Trigger,
		   PT					   := T#1S,
		   Q						:= "LSK_3_AUF_Labor_15_UV-22");
	  CALL #IEC_Timer_A91_5 (
		   IN					   := #LTS_Trigger,
		   PT					   := T#1S,
		   Q						:= "LSK_3_AUF_Labor_16_UV-22");
	  CALL #IEC_Timer_A91_7 (
		   IN					   := #LTS_Trigger,
		   PT					   := T#1S,
		   Q						:= "LSK_4_AUF_Labor_14_UV-22");
	  CALL #IEC_Timer_A92_1 (
		   IN					   := #LTS_Trigger,
		   PT					   := T#1S,
		   Q						:= "LSK_4_AUF_Labor_15_UV-22");
	  CALL #IEC_Timer_A92_3 (
		   IN					   := #LTS_Trigger,
		   PT					   := T#1S,
		   Q						:= "LSK_4_AUF_Labor_16_UV-22");

NETWORK
TITLE =Open A/B LTS for Modules 16 - 19 Lab select for Modules 20 - 21
	  CALL #IEC_Timer_A92_5 (
		   IN					   := #LTS_Trigger,
		   PT					   := T#1S,
		   Q						:= "LSM_16_AUF_Koll_1");
	  CALL #IEC_Timer_A92_7 (
		   IN					   := #LTS_Trigger,
		   PT					   := T#1S,
		   Q						:= "LSM_16_AUF_Koll_2");
	  CALL #IEC_Timer_A93_1 (
		   IN					   := #LTS_Trigger,
		   PT					   := T#1S,
		   Q						:= "LSM_17_AUF_Koll_1");
	  CALL #IEC_Timer_A93_3 (
		   IN					   := #LTS_Trigger,
		   PT					   := T#1S,
		   Q						:= "LSM_17_AUF_Koll_2");
	  CALL #IEC_Timer_A93_5 (
		   IN					   := #LTS_Trigger,
		   PT					   := T#1S,
		   Q						:= "LSM_18_AUF_Koll_1");
	  CALL #IEC_Timer_A93_7 (
		   IN					   := #LTS_Trigger,
		   PT					   := T#1S,
		   Q						:= "LSM_18_AUF_Koll_2");
	  CALL #IEC_Timer_A94_1 (
		   IN					   := #LTS_Trigger,
		   PT					   := T#1S,
		   Q						:= "LSM_19_AUF_Koll_1");
	  CALL #IEC_Timer_A94_3 (
		   IN					   := #LTS_Trigger,
		   PT					   := T#1S,
		   Q						:= "LSM_19_AUF_Koll_2");
	  CALL #IEC_Timer_A94_5 (
		   IN					   := #LTS_Trigger,
		   PT					   := T#1S,
		   Q						:= "LSM_20_AUF_Labor_13_1");
	  CALL #IEC_Timer_A94_7 (
		   IN					   := #LTS_Trigger,
		   PT					   := T#1S,
		   Q						:= "LSM_20_AUF_Labor_13_2");
	  CALL #IEC_Timer_A95_1 (
		   IN					   := #LTS_Trigger,
		   PT					   := T#1S,
		   Q						:= "LSM_21_AUF_Labor_13_1");
	  CALL #IEC_Timer_A95_3 (
		   IN					   := #LTS_Trigger,
		   PT					   := T#1S,
		   Q						:= "LSM_21_AUF_Labor_13_2");
	  SET   ; 
	  S	 #LTS_Trigger; //Set Trigger after first Time through
NETWORK
TITLE =Initiert Öffnung der Last-Trennschalter, nach Strom-Ausfall oder
	  UN	#IEC_Timer_A95_3.Q; //Wait till end of last Timer pulse
	  U	 #UV22_Active; //This prevents the Flag reset on first time through
	  R	 "M_DO_LTS_RESET"; 
	  R	 #First_Time; 
	  R	 #LTS_Trigger; 
	  SET   ; 
	  S	 #UV22_Active; 
	  BEA   ; 
 
END_FUNCTION_BLOCK

Edit: Somehow got the wrong version, hope it's OK now.
 
Last edited:
Isn't it the following code located at the end of network 5 (the penultimate network):

SET ;
S #LTS_Trigger; //Set Trigger after first Time through
 
Well, it shouldn't be, because when the Timer finally expires, in NW6 both LTS_Trigger and M_DO_LTS_RESET (as well as First_Time - which stays cleared) are cleared. In the next cycle, in OB1, because M_DO_LTS_RESET is clear, FB99 is no longer called - at least that's the theory! :)
 
Just another thought, concerning the following bit of code:

U "Instanz DB für FB3".Trigger; //Check BUSY in FB3 Instanz DB
BEB ; //if so exit
L #Modul_Nr;
LOOP next;
T #Modul_Nr; //When 0 transfer to Modul_Nr
BEB ; //so that next time UV22 is started

the second BEB (BEC in english i think) should be a BEU just to prevent confusion. If you fall through the first BEB, the RLO=1 and the L,LOOP,T instructions don't affect the RLO so the second BEB will always cause a block end when it falls out of the loop. (Was this your intention here ?)

Without seeing OB1, I can't see how your LTS_trigger is being set upon clear down.
 
the second BEB (BEC in english i think) should be a BEU just to prevent confusion.
Yes you're right that should have been a BEU (or since we're in German, BEA). As you say, in order to get there the RLO has to be = to 1 anyway, so it in fact still works as intended, but as you say, it's a bit misleading for anybody reading the program cold.

Here's the code for OB1, the RESET bit is in NW2

Code:
ORGANIZATION_BLOCK OB 1
TITLE =FZR 49 MJ / 100 Tesla Hochmagnetfeld Projekt
VERSION : 0.1
 
VAR_TEMP
OB1_EV_CLASS : BYTE ; //Bits 0-3 = 1 (Coming event), Bits 4-7 = 1 (Event class 1)
OB1_SCAN_1 : BYTE ; //1 (Cold restart scan 1 of OB 1), 3 (Scan 2-n of OB 1)
OB1_PRIORITY : BYTE ; //Priority of OB Execution
OB1_OB_NUMBR : BYTE ; //1 (Organization block 1, OB1)
OB1_RESERVED_1 : BYTE ; //Reserved for system
OB1_RESERVED_2 : BYTE ; //Reserved for system
OB1_PREV_CYCLE : INT ; //Cycle time of previous OB1 scan (milliseconds)
OB1_MIN_CYCLE : INT ; //Minimum cycle time of OB1 (milliseconds)
OB1_MAX_CYCLE : INT ; //Maximum cycle time of OB1 (milliseconds)
OB1_DATE_TIME : DATE_AND_TIME ; //Date and time OB1 started
END_VAR
BEGIN
NETWORK
TITLE =Identify available Modules
//At Start-Up, a check is performed to see which Modules are available for use 
//using FC125. 
//
//This Check is triggered by M550.3 "M_OB100_CALL" which is set in OB100. 
//
//OB82 and OB86 also initiate a call to FC125 and will later be used to handle 
//Modules returning or dropping out during an experiment. The handling of these 
//cases still needs to be discussed with FZR.
//
//Modules which are identified as not being present, or available, are then 
//disabled using FC125. This inhibits STEP7 from attempting to read non-existent 
//Inputs and generating large numbers of error Interrupts every cycle.
//
	 O	 "M_OB82_CALL"; //Wenn ein OB-Bit gesetzt
	 O	 "M_OB86_CALL"; 
	 O	 "M_OB100_CALL"; 
	 O	 "M_OB122_CALL"; 
	 O	 "GLOBAL_DIAG_DB".BUSY; //Oder FC125-Auswertung aktiv
	 S	 "FC125_CHECK_ACTIV"; //-> Startbit setzen
	 UN	"FC125_CHECK_ACTIV"; 
	 SPB conf; 
	 U	 "M_CONFIG_DP_IN_PROGRESS"; //Start Timer to delay LTS & Relay initialisation 
	 L	 S5T#5S; //until well after non-existant modules are disabled
	 SV	"T_DELAY_INIT"; 
 
	 UN	"GLOBAL_DIAG_DB".BUSY; //Wenn FC125-Auswertung fertig
	 R	 "M_OB82_CALL"; //-> alle OB-Bits ruecksetzen
	 R	 "M_OB86_CALL"; 
	 R	 "M_OB100_CALL"; 
	 U	 "M_CONFIG_DP_IN_PROGRESS"; //If first time through
	 SPB lock; 
	 L	 0; //disable interrupts
	 T	 "MB_SFC39_MODE"; 
	 T	 "MW_SFC39_OB-NR"; 
	 CALL "DIS_IRT" (
		 MODE					 := "MB_SFC39_MODE",
		 OB_NR					:= "MW_SFC39_OB-NR",
		 RET_VAL				 := "MW_SFC_RET_VAL");
	 L	 DW#16#FFFF7F00; //Preset Module available Bits in DB1000 in DWORD format
	 T	 DB1000.DBD	0; 
	 U	 "M_DISABLE_DP_CONFIG"; //Skip if Test Bit set from VAT-Table
	 SPB RSET; 
	 SET ; 
	 S	 "M_CONFIG_DP_IN_PROGRESS"; 
lock: CALL "GLOBAL_DP_DIAG" (
		 CHECK_ACTIV			 := "FC125_CHECK_ACTIV",
		 EXTERNAL_DP_INTERFACE	:= FALSE,
		 DP_MASTERSYSTEM		 := 1,
		 DATA_FIELD			 := "GLOBAL_DIAG_DB".DATA_FIELD,
		 SUM_SLAVES_DIAG		 := "GLOBAL_DIAG_DB".SUM_SLAVES_DIAG,
		 LIST_SLAVES_NOT_PRESENT := P#DB100.DBX 52.0 DWORD 4,
		 LIST_SLAVES_ERROR		:= P#DB100.DBX 68.0 DWORD 4,
		 RETVAL				 := "GLOBAL_DIAG_DB".RETVAL,
		 BUSY					 := "GLOBAL_DIAG_DB".BUSY);
	 UN	"GLOBAL_DIAG_DB".BUSY; //Wenn FC125-Auswertung fertig
	 R	 "FC125_CHECK_ACTIV"; //Reset enable bit for FC125
	 U	 "FC125_CHECK_ACTIV"; 
	 BEB ; 
conf: NOP 0; 
	 UN	"M_CONFIGURE_DP_SYSTEMS"; 
	 SPB ex01; 
	 L	 DW#16#FFFF7F00; //Mask for Module available Bits in DB1000 in DWORD format
	 L	 "GLOBAL_DIAG_DB".LIST_SLAVES_NOT_PRESENT[1]; //NB, Mask also includes UV22 addreses 22 and 23
	 UD	; 
	 XOD ; //Exclude faulty modules
	 T	 DB1000.DBD	0; //Store in DB1000
	 CALL "Lock out non-exist Modul" ;//Disable Modules not present
	 U	 "M_CONFIGURE_DP_SYSTEMS"; 
	 BEB ; 
	 L	 0; //and restore interrupts
	 T	 "MB_SFC40_MODE"; 
	 T	 "MW_SFC40_OB_NR"; 
	 CALL "EN_IRT" (
		 MODE					 := "MB_SFC40_MODE",
		 OB_NR					:= "MW_SFC40_OB_NR",
		 RET_VAL				 := "MW_SFC40_RET_VAL");
ex01: NOP 0; 
NETWORK
TITLE =RESET if necessary
//On Start-Up and at the Start of every new experiment, all Flags, etc. are reset 
//and all Outputs are set to the safe state.
RSET: NOP 0; 
	 U	 "M_I_Need_Fixing"; 
	 =	 "M_I_Need_Fixing"; 
	 ON	"M_DO_LTS_RESET"; 
	 O	 "T_DELAY_INIT"; 
	 SPB RelI; 
//	 SPA RelI
	 CALL "LTS_INIT" , "Instanz DB für FB99" ;
RelI: NOP 0; 
	 ON	"M_DO_INIT_REL"; 
	 O	 "T_DELAY_INIT"; 
	 SPB RSet; 
	 CALL "Relais Initialisierung" , "Instanz DB für FB96" ;
//RESET abarbeiten
RSet: NOP 0; 
	 UN	"DB Allgemeine Signale".RESET; 
	 SPB PH00; 
	 CALL "RESET STEUERUNG" (
		 RET_VAL				 := "MW_RETURN_WORD_INT");
NETWORK
TITLE =Nicht existierende Module selektieren verhindern
//Hier wird ein Versuch ein Modul zu selektieren verhindert wenn entweder das 
//Modul nicht existiert, oder die Abkühl-Wartezeit nicht abgelaufen ist.
//
//Inhibit selection of modules that do not exist or whose cooling time after an 
//experiment has not expired.
PH00: NOP 0; 
	 L	 "DB Allgemeine Signale".Phase; 
	 L	 2; 
	 ==I ; 
	 SPB INTL; 
	 CALL "WarteZeit nach Trigger" , "Instanz DB für FB1" ;
	 CALL "Kontrolle Mod. existiert" ;
NETWORK
TITLE =Interlock handling
INTL: NOP 0; 
	 L	 "DB Allgemeine Signale".Phase; 
	 L	 1; 
	 <I	; 
	 SPB DSM; 
	 CALL "Interlock Überwachung" ;
NETWORK
TITLE =DUMP Single Module
//This FB handles the DUMPing of a single module in the event of a fault. This 
//allows the experiment to continue with the remaining modules if desired.
DSM: NOP 0; 
	 U	 "M_I_Need_Fixing"; 
	 =	 "M_I_Need_Fixing"; 
	 UN	"DB Allgemeine Signale".DUMP_Single_Module; 
	 SPB Err; 
	 CALL "DUMP Single Module" , "Instanz-DB für FB9" ;
NETWORK
TITLE =Check for Alarm Bits set
Err: NOP 0; 
	 CALL "Error Check" ;
NETWORK
TITLE =
//ACHTUNG1!!!!
//
//******************************************************************************
//
//Modifiziert für neue FM352-5 FBs, FCs and DBs
//
//******************************************************************************
	 U	 "M_RUN_FM1"; 
	 =	 L	 20.0; 
	 BLD 103; 
	 U	 "M_Single_Scan_FM1"; 
	 =	 L	 20.1; 
	 BLD 103; 
	 U	 "M_NORMAL_FM1"; 
	 SPBNB _001; 
	 CALL "I_Normal" , "Instanz DB 1 für FB31" (
		 Run					 := L	 20.0,
		 OneScan				 := L	 20.1,
		 LADDRIn				 := L#300,
		 LADDROut				 := L#300,
		 CPU_Out				 := DB251.DBB	0,
		 CPU_In				 := DB252.DBB	0,
		 Error					:= "M_ERROR_FM1",
		 Status				 := "MW_STATUS_FM1");
_001: NOP 0; 
NETWORK
TITLE =
	 U	 "M_NORMAL_FM1"; //Check if FM1 in NORMAL mode
	 SPB FM2; //and if so skip FM1 DEBUG and go check FM2
NETWORK
TITLE =Normal and Debug FBs for FM352-5s (6 Netwworks)
//ACHTUNG1!!!!
//
//******************************************************************************
//
//Modifiziert für neue FM352-5 FBs, FCs and DBs
//
//******************************************************************************
//
 
	 U	 "M_RUN_FM1"; 
	 =	 L	 20.0; 
	 BLD 103; 
	 U	 "M_Single_Scan_FM1"; 
	 =	 L	 20.1; 
	 BLD 103; 
	 UN	"M_NORMAL_FM1"; 
	 SPBNB _005; 
	 CALL "I_Debug" , "Instanz DB 1 für FB30" (
		 Run					 := L	 20.0,
		 OneScan				 := L	 20.1,
		 LADDRIn				 := L#300,
		 LADDROut				 := L#300,
		 CPU_Out				 := DB251.DBB	0,
		 CPU_In				 := DB252.DBB	0,
		 AppFB					:= "Trigger Mod 1- 8",
		 AppInstDB				:= "Instanz DB für FB220",
		 Error					:= "M_ERROR_FM1",
		 Status				 := "MW_STATUS_FM1");
_005: NOP 0; 
 
NETWORK
TITLE =Skip main Program and jump to Test NW
//This Network is used to jump to the Test network at the end of the program.
DLAY: NOP 0; 
	 U	 "M_TEST_ENABLE"; 
	 SPB Test; 
NETWORK
TITLE =Check for Service Bild
//Wenn am HMI PC das Service-Bild aufgerufen ist, wird das normale Programm nicht 
//ausgeführt. Es werden keine Interlock oder andere Überwachungen ausgeführt. 
//Allein die Befehle des Operators im Sinne von schalten von Relais und 
//Leistungsschalter werden ausgeführt.
	 NOP 0; 
	 L	 "Bild_Nr DB".Aktuelle_Bild_Nr; //Identify current screen
	 L	 50; 
	 <I	; //If lower goto Delay Transfer otherwise handle Service screen activity then exit
	 SPB Dlay; 
	 CALL "LG_RESET" ;//LG_RESET can also be called from the 2 Fehler pics, so must always run
	 CALL "Reactivate DP Station" ;//Ditto DP Reactivation
	 CALL "Test-Bild Array" ;//Ditto I/O Mapping
	 L	 "Bild_Nr DB".Aktuelle_Bild_Nr; //Identify current screen
	 L	 80; //Check for test screens
	 <I	; 
	 SPB Dlay; //If not carry on with Delay Zeit Transfer
	 UN	"DB Allgemeine Signale".Test_Bild_Aktiv; 
	 SPB UVT; 
	 CALL "LTS Transit RM" ;
	 CALL "Service Bild Ablauf" ;
	 CALL "Test Trigger Outputs" ;
	 BEA ; //Don't go any further if Service Bild active
UVT: NOP 0; 
	 UN	"DB Allgemeine Signale".UV22_TEST_BILD; 
	 SPB ex02; 
	 CALL "UV22_TEST_BILD" ;
	 BEA ; //Don't go any further if UV22_Test Bild active
ex02: NOP 0; 
END_ORGANIZATION_BLOCK

Edit: I had to chop more than half of OB1 to get under the text length limit, but everything you need should be there.
 
Sorry, I can't see what's wrong here - all I can suggest is checking for overlapping flag bits with flag bytes/word/double words.
Ah well, I guess there's no point in worrying about it, it's working fine; I was really just curious about why the LTS_Trigger Flag was getting set again. Since it's Local Data and I'm only reading accessing it inside FB99, I don't really think it's a problem with overlapping Bytes/Words etc.
 
I was thinking of the global flag "M_DO_LTS_RESET" being used in an overlap with a byte/word/double word. I always find that these little "mysteries" come back and bite you (usually when you least expect it).
 

Similar Topics

Hi! I have a DirectLogic 205 with a H2-ERM100, used to connect some remote IO, via a H2-EBC100. The problem is, they're not communicating. The...
Replies
1
Views
1,892
We pulled a C-more touch panel from a customer's control panel that was freezing on boot up. It would start at a screen that said "Loading..." and...
Replies
4
Views
2,274
Hello, i need to use P_Intlk and feed the Status interlock OK bit to a P_DOut block. However, there's 17 interlocks for this output. How can I...
Replies
1
Views
107
Hi everyone, recently i worked with a cmore panel and have the question that how can clear alarm list whit remote form,right now only can with...
Replies
0
Views
107
Hello, friends, I am trying to upgrade a system that uses an Onrom incremental encoder (E6B2-CWZ6C) connected to a Danfoss VFD (FC360), but now...
Replies
4
Views
271
Back
Top Bottom