5

How do timers work in PLC Structured Text (ST)? How do we declare them?

I've been studying a standard of PLC (IEC 61131-3), and they do not speak about timers in ST. I know the great majority of PLC programmers do them in ladder logic, but in this particular case I really need to declare timers in ST.

I am using a Rockwell PLC.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Yoanribeiro
  • 135
  • 1
  • 1
  • 10
  • 2
    Not really, at least as far as I'm aware. The IEC 61131-3 "standard" is something you'll come to learn is more of a loose guideline. Every PLC is different - ladder is done in slightly different ways for each manufacturer, ST is done in slightly different ways by each manufacturer, mnemonics are different for each manufacturer, etc. Some PLCs don't even support timers in ST even though their ST complies with the IEC standard. Rockwell uses `TONR`, `TOFR`, and `CTUD`, etc...OMRON uses `TIMX`, `CNTRX`, etc. – J... Sep 05 '14 at 10:49
  • Damn, my bad for not figuring that out. Anyway can you tell me how do timers work in Rockwell PLC? I want to know, at least in one platform. – Yoanribeiro Sep 05 '14 at 11:00
  • 1
    "How do they work" is a really vague question. Suggest perhaps you study a Rockwell manual. If you're going to program PLCs you will find that the manuals that come with them are of incalculable value. Learning to read and understand a PLC manual is probably one of the most important skills you will need. If you want a summary of Rockwell timers, consider perhaps : http://howtoprogramaplc.blogspot.ca/2011/11/timer-and-counter-instructions.html – J... Sep 05 '14 at 11:07
  • When I say "how do they work" is in a ST program how to you initialize it and stuff like that.. Sorry if I wasn't explicit. – Yoanribeiro Sep 05 '14 at 14:35

6 Answers6

11

You can find explanations about timers and how to use (declare) it in the help system of your IDE. For example, in the CODESYS help you can read about timers of the standard library.

In general, you can declare timer-delay (TON) as:

VAR
    MY_TON: TON;
END_VAR
(* standard.library should be added to the project *)

Then you can use it:

MY_TON(IN:= IN_VALUE,PT:= TIME_SET);
(*IN_VALUE - is BOOL variable that activates your timer
  TIME_SET - is TIME variable*)

SOME_OUTPUT := MY_TON.Q;
(*Q - is the timer's output, and it can be used as BOOL variable. *)

You can also use constants to set up your timer:

MY_TON(IN:= True, PT:= t#5s);

As a BOOL variable, the timer's output can be used in IF and WHILE statements:

IF MY_TON.Q THEN
    (*Some statements...*)
END_IF

WHILE MY_TON.Q DO
    (*Some statements...*)
END_WHILE

All examples are run in CODESYS v3.5 SP5 and v2.3. For other IDEs there might be nuances.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
nadein
  • 357
  • 5
  • 14
  • I have a question closely related to your solution @sonysun . Answering this will help improve upon the information already provided. After MY_TON() does the execution wait till MY_TON.Q is turned TRUE or flows through and has to come back to the point to check multiple times before it is true. OR do I need to use a WHILE to make the execution spin in a loop till Q is TRUE and continue execution once it is TRUE. I am sure you can help me understand this better. (I am using a Rockwell Micro850 with CCW environment.) – aviimaging Jun 21 '16 at 06:29
  • @aviimaging it depends on your environment and controller. I'm not familiar with Rockwell Micro850 with CCW environment. In case of mine (Codesys v3.5 SP5 and v2.3 and controllers of my local manufacturer) the program is running in infinite loop and it checks the states of input variables multiple times. So I don't need to use WHILE or any loop commands. In your case you should check how your program executes. Then made a decision about using loops. – nadein Jun 24 '16 at 14:22
1

I solved it like this in Gx-Works(Mitsubishi / FXCPU):

TON_1(IN:= Enable_Timer,PT:= PresetTime ,Q:= Output,ET:= TimeLeft);

Remember to declare TON_1 :)

Richard87
  • 1,592
  • 3
  • 16
  • 29
1

The timer works so that TON.Q goes high only if TON.IN is continuously high for at least the duration of TON.PT.

This makes sure that TON.Q only goes high if TON.IN is in a stable high state.

This could be useful for instance to ensure that the output is only enabled if a button is pressed for at least a duration of TON.PT.

Adam.at.Epsilon
  • 263
  • 2
  • 12
0

Typically, you set a preset time and enable the timer. When it elapses, there will be done sort of done bit set true. When you reset the enable, the time will reset as well.

tkezy
  • 162
  • 7
0

I have done this with an OMRON PLC which supports the ST language.

There's a timer interrupt in the PLC, and we used it to build our own timer in ST, and then we could skip out of the PLC limitations. When the PLC power on, the code inside the interrupt task is executed every interruption, and you can write "A=A+1" inside the interrupt handler.

When you start to use the timer, just record the current data of A. Let's say A1; the interval is:

Interval= Current_Data_Of_A-A1

Then compare Interval to the time you want. If Interval is bigger than the time you want, then execute the next code.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Sunh Hao
  • 3
  • 2
0

We also have built our own timer structure with using milliseconds counter provided by PLC, so we could make arrays of timer (Schneider Electric) when we need and exceed PLC limitation.

TTIMER
 Count: UINT 
 timclock :INT 
 OUT :BOOL
 IN: BOOL 
END_STRUCT;
TIM_SOD=ARRAY[0..1] OF TTIMER;

(*This part runs every cycle of PLC*)
FOR I:=0 TO 1 DO
  IF TIM_SOD[I].IN (*timer on*)
  THEN
   IF (TIM_SOD[I].Count)>0 (*number of seconds left*)
   THEN
    IF ABS_INT(IN:=timclock-TIM_SOD[I].CLK)>=100 (*timclock -mSec counter*)
    THEN aTIM_SOD[I].Count:=TIM_SOD[I].Count-1;
     TIM_SOD[I].CLK:=TIM_SOD[I].CLK+100;
    END_IF;
   ELSE
    TIM_SOD[I].IN:=0; (*timer off*)
    TIM_SOD[I].Out:=1; (*Timer have run out*)
   END_IF;
  END_IF;
 END_FOR;
(*-------------------------------------------------*)

(*This part runs once when we need start timer*)
  TIM_SOD[0].COUNT:=H690; (*delay in seconds*)
  TIM_SOD[0].CLK:=TIMCLOCK; (*current value of mSec counter*)
  TIM_SOD[0].IN:=True; 
(*-------------------------------------------------*)

(*This part runs once when we need stop timer*)
  TIM_SOD[0].IN:=False;


(*Checking timer*)
IF TIM_SOD[0].OUT
THEN
  (*doing smth......*)
END_IF;
to1234go
  • 1
  • 1