Needing S7-200 functionality in S7-400

"retentive" has two different meanings here.
The retentiveness of the S5 timers in the HW config pertains to if they shall be reset upon shutdown or not.
The retentiveness of FC80 TONR pertains to that it can be "paused". I.e. it keeps the timed value, and continue from there until it is activated again. Because of this, there is a separate input to reset it.

jeebs said:
Valve opens, during that 5 mins operator opens door, so safety features makes valve close, but timer still keeps on running. Timer should pauze when door opens, so it can resume when door closes.
So jeebs needs the retentiveness of the FC80 TONR block.
 
Ah great
two kind of retentivness a)nonvoluntary retentivness (shutdown, power off)and b)voluntary retentivness (Pause) !!!So the manual pointed out by LD refers to nonvoluntary retetivness. Have not checked it real PLC, but in PLCSIM this doesnt work and its understandable.
 
Manmeet has the right idea about how to make the timer. I wouldn't call this a retentive timer though. A retentive one would need to be able to survive a power off situation by havnig a battery or flash backup.

I have been trying to program a S7 315-2 PN/DP the last few days. One of the things that I find missing is a free running real time clock. Then one could do what Manneet suggested with finer granularity. One would do this
timer:=timer+NewTime-OldTIme;
OldTim=NewTime;
On first scan a decision must be made if you need to keep the track of the time while the PLC was off or just when it was running. If you want to keep track of the time while the PLC was off then nothing needs to be done. If you want to keep track of the elapse time while the PLC was running then you can't update the timer during the first scan.

Now where is the free running millisecond or microsecond timer.

I deal with writing code for hardware. The CPU may have only two timeres. One is generating the system 'tick' or interrupt. The other is a free running clock from which all software timers are derived.
 
Manmeet has the right idea about how to make the timer. I wouldn't call this a retentive timer though. A retentive one would need to be able to survive a power off situation by havnig a battery or flash backup.

I have been trying to program a S7 315-2 PN/DP the last few days. One of the things that I find missing is a free running real time clock. Then one could do what Manneet suggested with finer granularity. One would do this
timer:=timer+NewTime-OldTIme;
OldTim=NewTime;
On first scan a decision must be made if you need to keep the track of the time while the PLC was off or just when it was running. If you want to keep track of the time while the PLC was off then nothing needs to be done. If you want to keep track of the elapse time while the PLC was running then you can't update the timer during the first scan.

Now where is the free running millisecond or microsecond timer.

I deal with writing code for hardware. The CPU may have only two timeres. One is generating the system 'tick' or interrupt. The other is a free running clock from which all software timers are derived.

There are 8 bits of clock pulses, I often use these for timing functions. In the CPU properties you can select a byte to place the clock bits into, usually defaults to MB0.
 
We are digressing. Maybe it is the topic for another thread. But anyway...
Manmeet has the right idea about how to make the timer. I wouldn't call this a retentive timer though. A retentive one would need to be able to survive a power off situation by havnig a battery or flash backup.
Jeebs needs the retentive/remanent/whatever kind that manmeet suggest or FC80 TONR. If it is not "rententive" what is the correct term ?

I have been trying to program a S7 315-2 PN/DP the last few days. One of the things that I find missing is a free running real time clock. Then one could do what Manneet suggested with finer granularity.
There is the realtime clock that you can read out with SFC1 READ_CLK.
Btw, the IEC timers use the method of storing the realtime clock value.

Then one could do what Manneet suggested with finer granularity. One would do this
timer:=timer+NewTime-OldTIme;
OldTim=NewTime;
Even more simple. Using the #OB1_PREV_CYCLE is actually very accurate.
diTimer:=diTimer + "di_OB1_PREV_CYCLE" ;
It seems that even if the resolution of #OB1_PREV_CYCLE is in milliseconds, it is smart enough to sum the remaining microseconds so that over the long run it is very accurate.
If the cycle time is really 5.3 ms, #OB1_PREV_CYCLE will change like this: 5-5-6-5-5-6-5-5-5-6- etc.
 
Just wondering, would it be possible to create a 'retentive' timer using LC Tx to store time-value and then use it to load the timer at the needed times?

Like LC Tx when door opens, save to varaible (one shot usage most prolly), then when door closes, you load that value again and then do SD/SF/etc Tx with the saved remaining time.

Won't that be more like the TONR used in S7-200?
 
I dont know S7-200. But since S7-200 is really a TI in disguise, and FC80 TONR comes from the TI-S7 Converting Blocks library, isnt it possible that S7-200 TONR and S7-300/400 FC80 TONR are very similar ?
 
Great, it seems that we are on the verge of developing our own accurate software based retentive timers!!!

timer:=timer+NewTime-OldTIme;
OldTim=NewTime;
diTimer:=diTimer + "di_OB1_PREV_CYCLE"

What more Peter Nachtwey we can solve the problem of making our timers retentive even during power loss by incrementing the word stored in DB !
I wouldn't call this a retentive timer though. A retentive one would need to be able to survive a power off situation by havnig a battery or flash backup.
We can increment counter using 8 bit clock pulse indicated by PeterW. I think these are very accurate as they must be hardware based.
 
hi
just for fun tried something, did a very quick test, don't kill me if it isn't fully working like you poeple expect it to work hehe.
Will not reach 5 minuts since i used a int and not a dint, but does stop/pauze and restart where ended
To start from 0 you need to reset
Code:
FUNCTION_BLOCK FB 2
TITLE =
VERSION : 0.1

VAR_INPUT
  iPrevScan : INT ; 
  iSetValue : INT ; //Time you want to in ms
  iResetTimer : BOOL ;  
END_VAR
VAR_OUTPUT
  oElapsTime : INT ;    
  oTimeToGo : INT ; 
  oTimeFlank : BOOL ;   
  oTimerSet : BOOL ;    
END_VAR
VAR
  sSavedTime : INT ;    
END_VAR
BEGIN
NETWORK
TITLE =
      A     #iResetTimer; 
      JCN   _003; 
      SET   ; 
      R     #oTimeFlank; 
      R     #oTimerSet; 
      L     0; 
      T     #sSavedTime; 
      T     #oElapsTime; 
      T     #oTimeToGo; 
_003: A     #oTimerSet; 
      JC    _004; 
      L     #iPrevScan; 
      L     #sSavedTime; 
      +I    ; 
      T     #sSavedTime; 
      L     #iSetValue; 
      L     #sSavedTime; 
      <=I   ; 
      JCN   _001; 
      A     #oTimeFlank; 
      JCN   _002; 
      SET   ; 
      R     #oTimeFlank; 
_002: SET   ; 
      S     #oTimerSet; 
      S     #oTimeFlank; 
_001: L     #iSetValue; 
      L     #sSavedTime; 
      -I    ; 
      T     #oTimeToGo; 
      L     #sSavedTime; 
      T     #oElapsTime; 
      BEU   ; 
_004: SET   ; 
      R     #oTimeFlank; 
END_FUNCTION_BLOCK
 
Hardware guys use the term 'gated'

Jeebs needs the retentive/remanent/whatever kind that manmeet suggest or FC80 TONR. If it is not "rententive" what is the correct term ?
Hardware guys would call this a gated timer. Do a google search for gated timer. A gated timer accumulates time only when the gate input is on. In jeebs case the timer accumulates when the door is closed so there is an extra input for the timer gate.

There are gated counters too.

If the cycle time is really 5.3 ms, #OB1_PREV_CYCLE will change like this: 5-5-6-5-5-6-5-5-5-6- etc.
That is fine, at least the time will not be off by more than a millisecond when summed.
 
previous code you should call the block before you can reset it, this you can reset whenever (added a starttimer input)

Code:
FUNCTION_BLOCK FB 2
TITLE =
VERSION : 0.1
 
VAR_INPUT
  iPrevScan : INT ; 
  iSetValue : INT ; //Time you want to in ms
  iResetTimer : BOOL ;  
  iStartTimer : BOOL ;  
END_VAR
VAR_OUTPUT
  oElapsTime : INT ;    
  oTimeToGo : INT ; 
  oTimeFlank : BOOL ;   
  oTimerSet : BOOL ;    
END_VAR
VAR
  sSavedTime : INT ;    
END_VAR
BEGIN
NETWORK
TITLE =
      A     #iResetTimer; 
      JCN   _003; 
      SET   ; 
      R     #oTimeFlank; 
      R     #oTimerSet; 
      L     0; 
      T     #sSavedTime; 
      T     #oElapsTime; 
      T     #oTimeToGo; 
_003: A     #iStartTimer; 
      JCN   _005; 
      A     #oTimerSet; 
      JC    _004; 
      L     #iPrevScan; 
      L     #sSavedTime; 
      +I    ; 
      T     #sSavedTime; 
      L     #iSetValue; 
      L     #sSavedTime; 
      <=I   ; 
      JCN   _001; 
      A     #oTimeFlank; 
      JCN   _002; 
      SET   ; 
      R     #oTimeFlank; 
_002: SET   ; 
      S     #oTimerSet; 
      S     #oTimeFlank; 
_001: L     #iSetValue; 
      L     #sSavedTime; 
      -I    ; 
      T     #oTimeToGo; 
      L     #sSavedTime; 
      T     #oElapsTime; 
      BEU   ; 
_004: SET   ; 
      R     #oTimeFlank; 
_005: NOP   0; 
END_FUNCTION_BLOCK
 
Last edited:
Thim.

Change your timer to work with DINTs in stead of INTs.
Otherwise it will be limitid to 32.7 seconds, and that may be a tad too little in many cases.

#OB1_PREV_CYCLE is a DINT already. Why FC80 TONR assumes an INT for DELTA is a mystery to me. I know that the cycle time will certainly be less than what can fit in an INT. But to save 2 bytes of memory ?.
Nonsense. #OB1_PREV_CYCLE is an INT. But anyway, use DINTs in your code.
 
Last edited:
Here it is with DINT instead of INT.
If you like i can make it also self reseting when you change the timervalue, or off-delay whatever just let me know.
All comments are welcome, just let me know

Code:
FUNCTION_BLOCK FB 2
TITLE =
VERSION : 0.1
 
VAR_INPUT
  iPrevScan : INT ; 
  iSetValue : DINT ;    //Time you want to in ms
  iResetTimer : BOOL ;  
  iStartTimer : BOOL ;  
END_VAR
VAR_OUTPUT
  oElapsTime : DINT ;   
  oTimeToGo : DINT ;    
  oTimeFlank : BOOL ;   
  oTimerSet : BOOL ;    
END_VAR
VAR
  sSavedTime : DINT ;   
END_VAR
VAR_TEMP
  DintCycleTime : DINT ;    
END_VAR
BEGIN
NETWORK
TITLE =
      L     #iPrevScan; 
      ITD   ; 
      T     #DintCycleTime; 
      A     #iResetTimer; 
      JCN   _003; 
      SET   ; 
      R     #oTimeFlank; 
      R     #oTimerSet; 
      L     0; 
      T     #sSavedTime; 
      T     #oElapsTime; 
      T     #oTimeToGo; 
_003: A     #iStartTimer; 
      JCN   _005; 
      A     #oTimerSet; 
      JC    _004; 
      L     #DintCycleTime; 
      L     #sSavedTime; 
      +D    ; 
      T     #sSavedTime; 
      L     #iSetValue; 
      L     #sSavedTime; 
      <=D   ; 
      JCN   _001; 
      A     #oTimeFlank; 
      JCN   _002; 
      SET   ; 
      R     #oTimeFlank; 
_002: SET   ; 
      S     #oTimerSet; 
      S     #oTimeFlank; 
_001: L     #iSetValue; 
      L     #sSavedTime; 
      -D    ; 
      T     #oTimeToGo; 
      L     #sSavedTime; 
      T     #oElapsTime; 
      BEU   ; 
_004: SET   ; 
      R     #oTimeFlank; 
_005: NOP   0; 
END_FUNCTION_BLOCK
 
I know I'm digging up old stuff here, but this thread helped me out so I converted it to LADder to conform to company standards and did some mild tweaks. Here is the source if anyone is interested or has any input on it.


Code:
FUNCTION_BLOCK "RetentiveTimer"
TITLE =Retentive Timer (Timebase of ms)
//Inputs:
//StartTimer - Bool - Start timing
//ResetTimer - Bool - Reset timer values and output
//TimerValue - Dint - Amount of time timer will run(Entered as ms)
//PrevCycleTime - Int - Previous OB1 cycle time, **from OB1 temps**
//
//Outputs:
//Timer_Q - Bool - Bit that will turn on when Timer has completed
//ElapsedTime - Dint - Amount of time StartTimer has been active
//RemainingTime - Dint - Amout of time left until Timer_Q is turned on
//
//Stat:
//SavedTime - Dint - Stores the sum of the OB1 cycle times.
//
//Temp:
//PrevCycleDINT - Dint - Used as a storage area for converting INT to DINT
//
//This FB creates a Timer that retains its current value when the StartTimer 
//signal is dropped and then continues when it is turned on again.  It will only 
//reset when the ResetTimer bit is triggered.
//
//2011 05 27 - Original FB created. 
VERSION : 0.1
 
VAR_INPUT
  StartTimer : BOOL ; 
  ResetTimer : BOOL ; 
  TimerValue_ms : DINT ; 
  PrevCycleTime : INT ; //From OB1
END_VAR
VAR_OUTPUT
  Timer_Q : BOOL ; 
  ElapsedTime : DINT ; 
  RemainingTime : DINT ; 
END_VAR
VAR
  SavedTime : DINT ; 
END_VAR
VAR_TEMP
  PrevCycleDINT : DINT ; 
END_VAR
BEGIN
NETWORK
TITLE =Previous cycle time to DINT
//Since the previsous cycle time is stored in OB1 stored as an INT it must be 
//converted to a DINT.
      L     #PrevCycleTime; 
      ITD   ; 
      T     #PrevCycleDINT; 
      NOP   0; 
NETWORK
TITLE =Zero timers and Reset Timer Output
      A     #ResetTimer; 
      =     L      4.0; 
      A     L      4.0; 
      JNB   _001; 
      L     0; 
      T     #ElapsedTime; 
_001: NOP   0; 
      A     L      4.0; 
      JNB   _002; 
      L     0; 
      T     #RemainingTime; 
_002: NOP   0; 
      A     L      4.0; 
      JNB   _003; 
      L     0; 
      T     #SavedTime; 
_003: NOP   0; 
      A     L      4.0; 
      BLD   102; 
      R     #Timer_Q; 
NETWORK
TITLE =If Reset Timer is active exit FB
      A     #ResetTimer; 
      SAVE  ; 
      BEC   ; 
NETWORK
TITLE =SavedTime
//As long as the SavedTime is less then the TimerValue ADD the Previous OB1 cycle 
//time to the current SavedTime
      A     #StartTimer; 
      A(    ; 
      L     #SavedTime; 
      L     #TimerValue_ms; 
      <D    ; 
      )     ; 
      JNB   _004; 
      L     #PrevCycleDINT; 
      L     #SavedTime; 
      +D    ; 
      T     #SavedTime; 
_004: NOP   0; 
NETWORK
TITLE =Moved SavedTime to ElapsedTime
//ElapsedTime is what is output from the FB
      L     #SavedTime; 
      T     #ElapsedTime; 
      NOP   0; 
NETWORK
TITLE =Calculate RemainingTime
//Subtracte SavedTime from TimerValue to determine RemainingTime.
//If the timer is finihsed then move a 0 into
      A     #StartTimer; 
      =     L      4.0; 
      A     L      4.0; 
      AN    #Timer_Q; 
      JNB   _005; 
      L     #TimerValue_ms; 
      L     #SavedTime; 
      -D    ; 
      T     #RemainingTime; 
_005: NOP   0; 
      A     L      4.0; 
      A     #Timer_Q; 
      JNB   _006; 
      L     0; 
      T     #RemainingTime; 
_006: NOP   0; 
NETWORK
TITLE =Set Timer Output
//If the SavedTime is greater then or equal to the TimerValue SET the output.
      L     #SavedTime; 
      L     #TimerValue_ms; 
      >=D   ; 
      =     #Timer_Q; 
NETWORK
TITLE =Set and Save
//Ensures that the ENO is True as long as the FB is processed
      SET   ; 
      SAVE  ; 
 
END_FUNCTION_BLOCK
 

Similar Topics

MY question may be silly but am a student and i've got in my graduate project a S7-200 PLC. i've made the pc/ppi cable by myself and it worked...
Replies
1
Views
1,732
Hi I would like to know if you can suggest a solution to a problem. I have a piece of machinery that is primarily pneumatic in its operation and...
Replies
8
Views
1,874
So I have the following assignment for a class I am taking. "Program overview: The size of the load to be wash is selected first. The start...
Replies
6
Views
2,578
So we just wired up a small automotive shop. They bought a second-hand lift but only have a single phase service. The motor is 3 phase, and the...
Replies
19
Views
7,231
Does anyone know of a good HMI that works well with Opto 22? I've been trying Red Lion G306M000 and have been coming up with difficulties in...
Replies
1
Views
1,879
Back
Top Bottom