'Count machine runtime in PLC

I am working on a simple machine project in PLC using structured text programming language. Now, I want to count the runtime (hours, mins and seconds) of a machine after Start Command is pressed. As I am new, I struggle to develop an idea. I tried to do it by using 3 counter for each seconds, minutes and hours. But could not achieve solid result. Can you please share the idea how to count runtime hours of a machine on PLC (ST or FB) ?



Solution 1:[1]

There are two issues here:

  1. Correctly handling delta time
  2. Using data types to your advantage

Since you want the time since the Start Command, you need to first store the time when the start command is pressed. Then you calculate the delta time (current time - start time) to obtain the seconds elapsed. Then take the seconds elapsed and get your hours, minutes, seconds. You can even simply use a TON FUNCTION_BLOCK for this - the ET output is in the TIME data type.

There are a number of good built-in data times for date and time. TOD (or TIME_OF_DAY) automatically is in the HH:MM:SS.mmm format for you. If your max elapsed time is less than 24 hours, you can use this format. If it could be longer, then use the TIME will go to 49 and some days, otherwise DT (DATE_AND_TIME) will count until the year 2106. You will get YYYY-MM-DD-HH:MM:SS in that format.

The following is a TON trick you can use, assuming 49 days or less is true.

PROGRAM PLC_PRG
VAR
   Running   : BOOL := FALSE;
   Start     : BOOL := FALSE;
   MyTimer   : TON;
   Elapsed   : TOD;
   MyEt      : TIME;
END_VAR

//calculate Elapsed time only if running
IF Running THEN
   //ET is in milliseconds, so can easily convert to TOD
   Elapsed := TIME_TO_TOD(MyEt);
ELSE
   Elapsed := TOD#0:0:0.000;
END_IF

//run a TON timer, but set the PT to the absolute limit
//this trick is only valid for 49 days or less!
MyTimer(IN:=Running,PT:=DWORD_TO_TIME(16#FFFFFFFF),ET=>MyEt);

//only start once
IF Start AND NOT Running THEN
   Running := TRUE;
   Start := FALSE;
END_IF

If you are adverse to the trick, you can also do something like below (requires the SysTime library). In your online debugger, you will see Elapsed in HH:MM:SS format. Of course you should create a FUNCTION_BLOCK for this.

PROGRAM PLC_PRG
VAR
   Running   : BOOL := FALSE;
   Start     : BOOL := FALSE;
   Now       : ULINT;
   StartTime : ULINT;
   Elapsed   : TOD;
   pResult: SysTimeRtc.RTS_IEC_RESULT;
END_VAR

//get current time (result is in seconds)
Now := DWORD_TO_ULINT(SysTimeRtcGet(pResult));

//calculate Elapsed time only if running
IF Running THEN
   //TOD is in milliseconds, so we x1000
   Elapsed := ULINT_TO_TOD((Now - StartTime) * 1000);
ELSE
   Elapsed := TOD#0:0:0.000;
END_IF

//only start once
IF Start AND NOT Running THEN
   StartTime := Now;
   Running := TRUE;
   Start := FALSE;
END_IF

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Scott