So jeebs needs the retentiveness of the FC80 TONR block.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.
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.
Jeebs needs the retentive/remanent/whatever kind that manmeet suggest or FC80 TONR. If it is not "rententive" what is the correct term ?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.
There is the realtime clock that you can read out with SFC1 READ_CLK.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.
Even more simple. Using the #OB1_PREV_CYCLE is actually very accurate.Then one could do what Manneet suggested with finer granularity. One would do this
timer:=timer+NewTime-OldTIme;
OldTim=NewTime;
timer:=timer+NewTime-OldTIme;
OldTim=NewTime;
diTimer:=diTimer + "di_OB1_PREV_CYCLE"
We can increment counter using 8 bit clock pulse indicated by PeterW. I think these are very accurate as they must be hardware based.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.
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 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.Jeebs needs the retentive/remanent/whatever kind that manmeet suggest or FC80 TONR. If it is not "rententive" what is the correct term ?
That is fine, at least the time will not be off by more than a millisecond when summed.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.
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
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
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