Time Stamps to Calculate Duration in Machine Expert

Sham

Member
Join Date
Sep 2019
Location
Australia
Posts
152
Hi All,

I have a rather simple task, but have no experience with the Timedate library so posting here. How can I calculate the time duration between two events ? for example, have to calculate the time duration of a motor running, by calculation the time duration between the time I press the Start button till I press the Stop button.

So, its like time_elapsed = TimeStop - TimeStart;
 
I'm also new and this is what I think should work:


Configure hardware events for each input, rising or falling.
Add two tasks and assign one for each event and program call in each task.

In each of the programs called by the tasks get system time.
In the cyclic program somewhere calculate the time difference.


Add SysTimeCore library to get the three functioins:
SusTimeGetms, SysTimeGetNs and SysTimeGetUs




Edit : I should add that I haven't tried it yet.



Have a look at the .gif in this link
 
I'm also new and this is what I think should work:


Configure hardware events for each input, rising or falling.
Add two tasks and assign one for each event and program call in each task.

In each of the programs called by the tasks get system time.
In the cyclic program somewhere calculate the time difference.


Add SysTimeCore library to get the three functioins:
SusTimeGetms, SysTimeGetNs and SysTimeGetUs



Edit : I should add that I haven't tried it yet.



Have a look at the .gif in this link

Thanks Kalabdel, I had similar thoughts. I wrote this:

--- --- --- VARIABLE DEFINITION --- --- ---
FUNCTION_BLOCK TimeDuration

VAR_INPUT
START: BOOL;
STOP: BOOL;
END_VAR

VAR_OUTPUT
OUTPUT:BOOL;
END_VAR

VAR
Trig_Start:R_Trig;
Trig_Stop:R_Trig;
stUnixStamp:SysTimeRtc.SysTimeCore.SYSTIME;
stdate: SysTimeRtc.RTS_SYSTIMEDATE;
Start_Stamp:ULINT;
Stop_Stamp:ULINT;
Time_ms: ULINT;
Runtime:ULINT;
END_VAR
--- --- --- LOGIC --- --- ---
Trig_Start(CLK:=START);
Trig_Stop(CLK:=STOP);



IF Trig_Start.Q THEN
OUTPUT:=TRUE;
Start_Stamp:=stUnixStamp;
END_IF

IF Trig_Stop.Q THEN
Stop_Stamp:=stUnixStamp;
Runtime:=(Stop_Stamp - Start_Stamp);
END_IF

This looks logically correct, but somehow is not giving any results.
 
The code I suggested is supposed to have nanosecond precision and not tied to scan time; it is based on generating hardware interrupts (trigger events) for digital inputs and using system function that retruns time in nanoseconds.
 
In most of my project I need to display time counters in the HMI. So I have created a library of different hour, minutes and seconds counters/timers.
The following FB is simple time counter that outputs the time in hours, minutes and seconds that has passed since xEnable was set high.

Code:
FUNCTION_BLOCK PUBLIC FB_TimeCount
VAR_INPUT
	xEnable:BOOL;
END_VAR
VAR_OUTPUT
	uiElapsedHour:UINT:=0;
	uiElapsedMin:UINT:=0;
	uiElapsedSec:UINT:=0;
END_VAR
VAR
	uiElapsedTime:UINT:=0;
	udNowTime : UDINT;
	udPrevTime : UDINT;
END_VAR

Code:
udNowTime := TIME_TO_UDINT(TIME());

IF xEnable THEN
	IF (udNowTime - udPrevTime > 1000) THEN
		uiElapsedTime := uiElapsedTime + 1;
		uiElapsedSec := uiElapsedTime MOD 60;
		uiElapsedMin := uiElapsedTime/60 MOD 60;
		uiElapsedHour := uiElapsedTime/3600 MOD 3600;
		udPrevTime := udNowTime;
	END_IF;
ELSE
	uiElapsedSec := 0;
	uiElapsedMin := 0;
	uiElapsedHour := 0;
	uiElapsedTime := 0;
END_IF;
 
In most of my project I need to display time counters in the HMI. So I have created a library of different hour, minutes and seconds counters/timers.
The following FB is simple time counter that outputs the time in hours, minutes and seconds that has passed since xEnable was set high.

Code:
FUNCTION_BLOCK PUBLIC FB_TimeCount
VAR_INPUT
	xEnable:BOOL;
END_VAR
VAR_OUTPUT
	uiElapsedHour:UINT:=0;
	uiElapsedMin:UINT:=0;
	uiElapsedSec:UINT:=0;
END_VAR
VAR
	uiElapsedTime:UINT:=0;
	udNowTime : UDINT;
	udPrevTime : UDINT;
END_VAR

Code:
udNowTime := TIME_TO_UDINT(TIME());

IF xEnable THEN
	IF (udNowTime - udPrevTime > 1000) THEN
		uiElapsedTime := uiElapsedTime + 1;
		uiElapsedSec := uiElapsedTime MOD 60;
		uiElapsedMin := uiElapsedTime/60 MOD 60;
		uiElapsedHour := uiElapsedTime/3600 MOD 3600;
		udPrevTime := udNowTime;
	END_IF;
ELSE
	uiElapsedSec := 0;
	uiElapsedMin := 0;
	uiElapsedHour := 0;
	uiElapsedTime := 0;
END_IF;

Thanks Kalileo, please check your inbox!
 
It looks like the SysTimeRtcHighResGet function is not supported in all CPUs, definitely not my M241.

time delta4.PNG
 
Last edited:
Thanks Kallileo. I can add the library and have access to the instruciton; I do not get any errors it just doesn't output the result.

You are right though, it is supported in M241 I will spend some time later to get it to work.
 
Almost every piece of code I write in ST is a state machine.
The following code counts motor operating hours add them to the old values values that can should be declared as Persistent variables in SoMachine/Machine Expert/Codesys.
You can also convert the operating minutes to hours and add them as well.

Code:
FUNCTION_BLOCK PUBLIC FB_TimeCount
VAR_INPUT
	xEnable:BOOL;
END_VAR
VAR_OUTPUT
	uiElapsedHour:UINT:=0;
	uiElapsedMin:UINT:=0;
	uiElapsedSec:UINT:=0;
END_VAR
VAR
	uiElapsedTime:UINT:=0;
	udNowTime : UDINT;
	udPrevTime : UDINT;
	iStatus : INT :=0;
END_VAR

udNowTime := TIME_TO_UDINT(TIME());
IF xEnable THEN
	CASE iStatus OF
	0:
		uiElapsedSec := 0;
		uiElapsedMin := 0;
		uiElapsedHour := 0;
		uiElapsedTime := 0;
		iStatus := 10;
	10:		
		IF (udNowTime - udPrevTime > 1000) THEN
			uiElapsedTime := uiElapsedTime + 1;
			uiElapsedSec := uiElapsedTime MOD 60;
			uiElapsedMin := uiElapsedTime/60 MOD 60;
			uiElapsedHour := uiElapsedTime/3600 MOD 3600;
			udPrevTime := udNowTime;
		END_IF;
	END_CASE
ELSE	
		iStatus := 0;
END_IF;


Code:
PROGRAM PLC_PRG
VAR
	motorOperHours : FB_TimeCount;
	uiOperHours : UINT;
	uiOperMinutes : UINT;
	uiOperSecs : UINT;
	xMotorStart : BOOL;
	ftMotor : F_TRIG;
	uiOldMotorHours : UINT := 10;
END_VAR

motorOperHours(xEnable:=xMotorStart, uiElapsedHour=>uiOperHours, uiElapsedMin=>uiOperMinutes, uiElapsedSec=>uiOperSecs);

ftMotor(CLK:=xMotorStart);
IF ftMotor.Q THEN
	uiOldMotorHours := uiOldMotorHours + uiOperHours;
END_IF
 
Thanks kallileo. I'm sure your code will come in handy.



Thanks Kalabdel, I had similar thoughts. I wrote this:



This looks logically correct, but somehow is not giving any results.


I think you need to call the function to actually access the time.


Result := SysTimeRtcHighResGet (pTimeStamp := StartTime);


That worked for me.


Thanks for asking the question, it was a nice exercise.

time delta5.PNG
 

Similar Topics

Is it possible to calculate the time difference between two timestamps in Redlion crimson 3.1? Thank you,
Replies
2
Views
1,386
Hi, I'm fairly sure that the boffins in here have already solved this several times but I cant find it... I have a program from an S7-400 that...
Replies
2
Views
1,852
Hi guys, Thought I might ask here if anyone knows, currently have tech support looking for a solution. I have a micro820 and wanting to...
Replies
8
Views
2,513
Hi All, Is it possible to alter the project date/timestamps for concept 2.6 projects? I have a remote PLC that I need to connect to but the...
Replies
0
Views
2,416
Hi, i recently asked the question on how to unprotect s7 blocks, i got the answer and have done exactly that. i made a copy of the entire project...
Replies
0
Views
4,708
Back
Top Bottom