Yukkotete
Hello,

I am trying to create a TONR function Block, that is a normal TON but with memory, so the timer will remember where was it in order not to reset the timer every time the input is set to 0.

I will need also a way to reset the TONR but first i need a timer with memory.

I am trying to create ir from a TON timer but i am not getting good results.

Thank You.
Reply 0 0
thiagoralves
If you create a functionBlock it will have memory for all local variables. Functions don't have memory. They will always have the same output for a given input.
Check this: http://ua.automation.com/resources-tools/application-stories/programmable-logic-controller-plc/iec-61131-3-functions-and-function-blocks-what-is-the-difference

You can change the provided TON example a little bit to achieve what you want.
Reply 0 0
Yukkotete
I was and I am working in order to change the TON to a TON with memory, now I have no idea but if I find out how to do it I will post it.

If you have some ideas how to change the TON, it would be awesome.
Reply 0 0
thiagoralves
You don't have to change the TON. Create a functionBlock in Structured Text that has the functionality you want. The structure of it is already written in the guide I sent to you.
Reply 0 0
Yukkotete
Hello, looking around i saw an example and i modified it look like that (maybe you will be familiar to this haha)

IF ((STATE = 0) AND NOT(PREV_IN) AND IN)   (* found rising edge on IN *)
THEN
  (* start timer... *)
  STATE := 1;
  Q := FALSE;
  START_TIME := CURRENT_TIME - ET;
ELSE
  (* STATE is 1 or 2 !! *)
  IF (NOT(IN))
  THEN
    (*ET := T#0s;*)
    Q := FALSE;
    STATE := 0;
  ELSIF (STATE = 1)
  THEN
    IF ((START_TIME + PT) <= CURRENT_TIME)
    THEN
      STATE := 2;
      Q := TRUE;
      ET := PT;
    ELSE
      ET := CURRENT_TIME - START_TIME;
    END_IF;
  END_IF;
END_IF;
IF (RESET = 1)
THEN
  IF (STATE = 1)
  THEN
    ET := T#0s;
    START_TIME := CURRENT_TIME;
    Q := FALSE;
  ELSIF (STATE = 2)
  THEN
      Q := FALSE;
      ET := T#0s;
    STATE := 1;
    START_TIME := CURRENT_TIME;
   ELSIF (STATE = 0)
   THEN
    ET := T#0s;
    Q := FALSE;
  END_IF;
END_IF
PREV_IN := IN;


I think like that my timer will preserve the time value, but i cannot compile it because i get errors from the Main program (a lot of "Invalid Statement in ST statement" errors) from the generated program, not from my code.

Any ideas why this is happening? 
What do you think about the code?
Reply 0 0
Yukkotete
Another question, Is the variable CURRENT_TIME defined to get te current time? Will it work as i expect or should i define it somewhere?
Reply 0 0
Yukkotete
Code corrected, now the only problem is getting the CURRENT_TIME, 
How should I correctly get the Current Time?
Reply 0 0
thiagoralves
I'm sorry, this is an undocumented feature. To get current time you will have to use a macro, so that the ST code compiler will translate that line exactly as it is. The line will then get the current time from the OpenPLC environment and store it on a variable defined in your ST code. This can sound complicated but it isn't. Just define the CURRENT_TIME variable of type TIME in your ST code (if you haven't done that already). You can do that using the graphical interface by just adding CURRENT_TIME as TIME in the variables list, or you can manually write this at the beginning of your code:

VAR
    CURRENT_TIME : TIME;
END_VAR

Then, add this line to get the current time from OpenPLC:

{__SET_VAR(data__->,CURRENT_TIME,,__CURRENT_TIME)}

Let me know if it worked.
Reply 0 0
Yukkotete
Tested and works perfect. I leave the code here in case you want to implement a TONR in the program, which i find very usefull:


FUNCTION_BLOCK TONR
  VAR_INPUT
    IN : BOOL;
    Reset : BOOL;
    PT : TIME;
  END_VAR
  VAR_OUTPUT
    Q : BOOL;
  END_VAR
  VAR
    ET : TIME;
    START_TIME : TIME;
    CURRENT_TIME : TIME;
    STATE : INT;
    PREV_IN : BOOL;
    TON0 : TON;
  END_VAR
  {__SET_VAR(data__->,CURRENT_TIME,,__CURRENT_TIME)}
  IF ((STATE = 0) AND NOT(PREV_IN) AND IN)   (* found rising edge on IN *)
  THEN
    (* start timer... *)
    STATE := 1;
    START_TIME := CURRENT_TIME - ET;
  ELSE
    (* STATE is 1 or 2 !! *)
    IF (NOT(IN))
    THEN
      STATE := 0;
    ELSIF (STATE = 1)
    THEN
      IF ((START_TIME + PT) <= CURRENT_TIME)
      THEN
        STATE := 2;
        Q := TRUE;
        ET := PT;
      ELSE
        ET := CURRENT_TIME - START_TIME;
      END_IF;
    END_IF;
  END_IF;
  IF (RESET = 1)
  THEN
    IF (STATE = 1)
    THEN
      ET := T#0s;
      START_TIME := CURRENT_TIME;
      Q := FALSE;
    ELSIF (STATE = 2)
    THEN
        Q := FALSE;
        ET := T#0s;
      STATE := 1;
      START_TIME := CURRENT_TIME;
     ELSIF (STATE = 0)
     THEN
      ET := T#0s;
      Q := FALSE;
    END_IF;
  END_IF;
  PREV_IN := IN;
END_FUNCTION_BLOCK


Thank you
Reply 0 0
thiagoralves
Awesome! Thank you Yukkotete
Reply 0 0
nataliabn45
i supouse that a TONR is the same as RTO but in a diferent name, anyways, if someone want that template i tested it.
aparently it works, i'm new in this world of plc, but here is de program like the code thatyukkotete posted
Reply 0 0
Konrad_B
I'm wery glad to find this solve 🙂 
Reply 0 0
Reply