Can timers be passed in and out of subroutines?

I am trying to create a subroutine to be used for input scaling, filtering, and alarming of a process variable. I am having some trouble with the alarm delay however. I will have many of these values (50-100) in a single strategy so it is important that the sub doesn’t hang up the strategy. I guess what I’m asking is does anyone know of a way to start a timer from a sub so that it can be used for an alarm delay?

What I have below works outside of a sub but when in a sub the timer is zeroed out as the sub ends.

//If PV exceeds the high alarms trip point and is not currently in alarm a delay timer is started. If the delay set point is exceeded the high alarm is set true.
If ((f_PV > f_PV_HighAlarm_TP) and (n_PV_HighAlarm == 0)) then

IF (n_DelayTimerActive == 0) then
StartTimer (t_DelayTimer);
n_DelayTimerActive = 1;

If (t_DelayTimer > f_Delay_SP) then
n_PV_HighAlarm = 1;
n_DelayTimerActive = 0;
StopTimer (t_DelayTimer);

//If the PV falls under ther high alarm setpoint the delay timer is stopped
If (f_PV < f_PV_HighAlarm_TP) then
n_DelayTimerActive = 0;
StopTimer (t_DelayTimer);

// the PV ralls under the high alarm trip point minus the deadband the timer is stopped and the alaem is cleared
If (f_PV < (f_PV_HighAlarm_TP - f_PV_Deadband)) then
n_PV_HighAlarm = 0;
n_DelayTimerActive = 0;
StopTimer (t_DelayTimer);

You need to create the timer variable in the strategy and pass it to the subroutine as a parameter.

Also, see this:

1 Like

I guess I should have stated that more clearly. I do have a timer variable in the strategy and I am passing the t_DelayTimer parameter to it but as the sub ends the timer value in the strategy goes to zero instead of continuing to time.

I also do have the alarm reset already written in (deadband). This is also a passed parameter so that it is settable per process variable. Thanks for mentioning it. this is definitely something that gets overlooked too often.

The timers should continue to run when the subroutine exits. I suspect something else is wrong in the logic.

Edit: Make sure you are using a separate timer variable for each alarm point.

Any easy way to handle timers (in and out of subroutines) is to setup a loop timer in your chart and add that value to the value of a Float Tag to be used as a timer. This setup is basically an up timer but it can be adjusted for down time.

Loop time needs to be time from Timer Start of the chart back to that point (which you would use a timer variable), record the total time for the loop as your LOOP TIME. Subroutines and blocks that are setup for timing need to be cycled through each loop of the chart to ensure proper timing. When timer is not active simply set the variable to zero and don’t add the LOOP TIME.

For example put following code at beginning of chart and loop back at the end of the chart:

if (MR_LOOP_TIME <= 0) then
MR_LOOP_TIME = .001;


/////FOR TIMERS (with TIME_TD being setup as a FLOAT):
TIME_TD = 0;

This allow us to run multiple timers (in a chart) using only 1 TIMER Variable - less logic and you don’t have to worry about starting / stopping timers (just do in logic as noted above)

Thanks. I will give this a try.

Thanks for the help everyone. I was able to get this resolved. Ended up creating a sub that just passed a timer into and out of the sub. With that I was able to see where I was causing the problem with the timer resetting as the sub ended. This is where I ended up for an alarm with time delay and deadband. Hope it is helpful to someone else as new to this as I am.

If ((PV > HiAlm_SP) and (DelayTimer <=0)) Then
DelayTimer = 0.001;

If (PV < HiAlm_SP) Then
StopTimer (DelayTimer);

If ((PV > HiAlm_SP) and (DelayTimer > Delay_SP)) Then
HiAlm = 1;

If (PV < (HiAlm_SP - Deadband)) Then
HiAlm = 0;