Join us today!

Notifications
Clear all

Cumulative downtime stats

6 Posts
4 Users
2 Reactions
568 Views
Posts: 15
Topic starter
(@duncan)
Eminent Member
Joined: 2 years ago

Hey folks,

Looking to implement a down-time monitor for our system which will check a 1 second pulse, and increment a downtime counter if a fault exists, or an up-time counter if no fault exists.

I don’t want the cumulative error from running a 1 second repeating timer.

Is there a system flag that will give me a 1 second pulse?

Is there some other recommended way of doing this?

 

I see there are real-time clock commands, but it looks like these are slow to update.

 

I have implemented an LTON for now, and running LTIME_TO_DT to get a date_time, then DT_TO_DINT to get the seconds from the timer.
Feels a bit hacky though, so looking for suggestions.

 

Any help gratefully received!

 

Cheers

Duncan

Reply
Topic Tags
5 Replies
Posts: 15
Topic starter
(@duncan)
Eminent Member
Joined: 2 years ago

This is what I have hacked together so far:

stats_timer(IN:=NOT stats_timer.Q, PT:=LTIME#36_500D); // timer runs for 100 years (then resets to 0)

stats_timer_dt := LTIME_TO_DT(stats_timer.ET); // converts LTIME to DATE_AND_TIME
stats_timer_sec := DT_TO_DINT(dTime); // gets seconds from DATE_AND_TIME
stats_timer_msec := DT_TO_LINT(dTime); // gets milliseconds from DATE_AND_TIME

IOAdmin.SystemSecondsPulse := stats_timer_sec <> stats_timer_sec_prev; // pulse if seconds have incremented
stats_timer_sec_prev := stats_timer_sec; // store previous seconds value

IF IOAdmin.SystemSecondsPulse THEN 
	stats_timer_test := stats_timer_test + 1;
END_IF;
Reply
1 Reply
runtimevictor
(@runtimevictor)
Joined: 2 years ago

Estimable Member
Posts: 156

@duncan , hello:

https://github.com/runtimevic/TwinCAT3_StopWatch

https://github.com/runtimevic/TC3_StopWatch_Level

Reply
kolyur
Posts: 12
(@kolyur)
Active Member
Joined: 2 years ago

You could try using FB_LocalSystemTime. This function block will continually return the time as long as bEnable is held on. Here's some code I used to return the number of seconds since 1/1/1970:

PROGRAM MAIN
VAR
    fbTime: FB_LocalSystemTime;
    tStruct: TIMESTRUCT;
    dTime: DATE_AND_TIME;
    eTime_sec: DINT;
END_VAR
fbTime(bEnable:=TRUE, dwCycle:=1, SystemTime=>tStruct);

dTime := SYSTEMTIME_TO_DT(tStruct);
eTime_sec := DT_TO_DINT(dTime);

The eTime_sec value could be compared to the value from the previous scan, as you did in your code, to trigger the one-second pulse. The dwCycle parameter lets you control how often the timer is synchronized with the system clock.

 

Reply
Posts: 9
(@unchained)
Active Member
Joined: 2 years ago

I use a self resetting clock to create pulses. Then I count the pulses to calculate elapsed time. I also use this clock to create pulsing Lights, buttons etc. You can customize it as you need. It is important to run this block in a fast task so your accuracy is high.

 

 FUNCTION_BLOCK FB_Clock
VAR_INPUT
	
END_VAR
VAR_OUTPUT
	Blink_1Hz : BOOL;
	Clock_1Hz	: BOOL;
	
	Blink_10Hz : BOOL;
	Clock_10Hz	: BOOL;
	
END_VAR
VAR
	Count  : USINT;
	Timer100 : TON;
END_VAR


Timer100(IN := NOT Timer100.Q, PT:= T#100MS, Q => Clock_10Hz);

IF Timer100.Q THEN
	Count := Count +1;
	Blink_10Hz := NOT Blink_10Hz; 
END_IF

IF Count >= 5   THEN
	
	Blink_1Hz := TRUE;
	
ELSE
	Blink_1Hz := FALSE;
	
END_IF



IF Count = 10   THEN
	
	Clock_1Hz := TRUE;
	Count := 0;
	
ELSE
	
	Clock_1Hz := FALSE;
	
END_IF
Reply
Posts: 9
(@unchained)
Active Member
Joined: 2 years ago

Alternatively you could use the system time to monitor machine down time. You can create a boolean tag which goes TRUE while there is an error on the machine, then monitor this tag's rising and falling edges, using my code below.

 

Disadvantage of that block is that you wont know the elapsed time during the alarm state. You can add a Method to see elapsed time comparing the current time with RisingTime.

 

FUNCTION_BLOCK FB_SignalMonitor
VAR_INPUT
	
	SignalToMonitor 	: BOOL; 
END_VAR
VAR_OUTPUT
		
	RisingTime 		: UDINT;   // unit :  ns
	FallingTime 	        : UDINT; 	// unit : ns 
        Duration                  : DINT;   // unit : ms 
	
END_VAR
VAR
	
	R_Edge 	: R_TRIG; 
	F_Edge	: F_TRIG; 	
	
END_VAR

(* -----------------------------------------------------------------------------------
									FB_SignalMonitor ver1.0
	Created by unchained 28/03/2023

 This FB monitors the given signal and records the time of Rising Edge and Falling Edge.
	
------------------------------------------------------------------------------------*)



R_Edge(CLK := SignalToMonitor);
F_Edge(CLK := SignalToMonitor); 


IF R_Edge.Q THEN 
	//Read the Rising Edge Time 
	
	RisingTime := ULINT_TO_UDINT(F_GetCurDcTaskTime64() AND 16#FFFFFFFF);  
	
END_IF

IF F_Edge.Q THEN 
	//Read the Falling Edge Time 
	
	FallingTime := ULINT_TO_UDINT(F_GetCurDcTaskTime64() AND 16#FFFFFFFF);
	Duration    := (UDINT_TO_DINT(FallingTime) - UDINT_TO_DINT(RisingTime)) / 1000000;
END_IF
Reply
Share: