Welcome to our new forum
All users of the legacy CODESYS Forums, please create a new account at account.codesys.com. But make sure to use the same E-Mail address as in the old Forum. Then your posts will be matched. Close

Simple TON Question - Struggling to understand the basics

boompy
2018-10-30
2018-11-14
  • boompy - 2018-10-30

    Hi all

    Can somebody please help me to understand how this basic function operates.

    I generally understand how a TON timer works... but I need to REALLLLY understand how these things work. I think my question really pertains to how 'scan' cycles works, how code is implemented and when inputs are updated.

    I'm familiar with the whole, read inputs, execute code, update outputs mantra - but I'm not fully following how this works.

    Lets assume I have a program where a TON instance is declared with a PT:= 50ms. Assume my task is operating at 20ms.

    Now in my program I call the FB:

    tonDelay( IN :=NOT tonDelay.Q);
    Output := tonDelay.Q;

    Can somebody please explain how the variable: 'Output' ever achieves a result of TRUE.

    In my mind: As soon as the program calls the tonDelay and sees that tonDelay.Q is false (timer hasn't yet reached the PT), it keeps tonDelay.IN at TRUE and allows the timer to keep running.

    On the next cycle, let's assume the PT of 50ms has elapsed tonDelay is called and tonDelay.Q is TRUE (timer has finished), my understanding is that when this line of code is called:

    tonDelay( IN :=NOT tonDelay.Q);

    ..., the tonDelay.IN condition falls to FALSE, which in turn will set the tonDelay.Q value to FALSE

    So how can the following line of code ever fall TRUE:

    Output := tonDelay.Q;

    By the time it is executed, the timer has set IN to false, which in turn sets Q to false.

    Like I said, I think I'm misunderstanding scan cycles and how the code is executed.

    Can somebody please spell out to me (in detail... scan by scan if necessary) how each scan works, how inputs are calculated and how outputs are updated.

    I'm getting close to understanding, but I'm in need of a wiser sole

    Thanks in anticipation

     
  • dFx

    dFx - 2018-10-30

    You feel not so familiar with :

    Zitat:
    read inputs, execute code, update outputs mantra

    Basicaly, what the code does ?
    tonDelay( IN :=NOT tonDelay.Q);
    1) Copies value NOT tonDelay.Q
    2) Paste it to tonDelay.IN
    3) Call tonDelay FB instance (so calls TON FB, with tonDelay memory)
    4) tonDelay updates its outputs, setting the right value to tonDelay.Q
    Output := tonDelay.Q;
    5) Copies value of tonDelay.Q
    6) Paste it to Output

    So, in your exemple, this will produce :
    1) While PT not reached
    tondelay.Q FALSE
    Output FALSE
    2) Once PT reached, IN was evaluted before, so its true, and Q is set after so its TRUE
    tondelay.Q TRUE
    Output TRUE
    3) Q is set, IN is now FALSE
    tondelay.Q FALSE
    Output FALSE
    4) we are back to 1)

    EDIT: It feels you Watch the code as it was the instant value. This is wrong. Code is full of steps.

    Kind regards,
    dFx

     
  • Anonymous - 2018-10-30

    Originally created by: rickj

    I think dFx has it right when he says:

    Zitat:
    It feels you Watch the code as it was the instant value. This is wrong. Code is full of steps.

    Set he task scan time to 1 or 2 seconds so that you can see the results after each scan. Set the TON timeout to 5 or 10 seconds. You should be able to see how it all works, all the steps just like dFx says.

     
  • josepmariarams - 2018-10-30

    Hi.

    The inputs are setted before fb execution. In the cycle when Q rises to true, Q is false before the fb execution.

    In the next cycle fb see Q as true and after the fb execution Q falls to false.

    You have made an oscilator.

    Another question is about the temporizer time source. I prefer to work with temporizers wich be increased every cycle with task cycle time. In that case the code sees the time as it be executed at the beguining of the task, it is synchronized with input output latches.

    Ton increases in the middle of the task, it could vary if your task code execution time is more or less long.

    Sent from my Moto G (5S) Plus using Tapatalk

     
  • dFx

    dFx - 2018-10-31

    Josep M. Rams hat geschrieben:
    Ton increases in the middle of the task, it could vary if your task code execution time is more or less long.

    Not sure how TON works internaly, but I would bet on getting actual CPU time and comparing with previous scan one. This should avoid task scan jitter.

     
  • boompy - 2018-11-07

    Hi guys,

    My apologies for the delayed response.

    Thank you so much dfx & Josep for explaining the fundamentals. I'ts strange, I've managed to solve most of my algorithm dilemas without too much difficulty, but I hate not understanding the 'fine details' like PLC scan cycle behaviour having come from a coding background removed from PLC environments.

    I'm still struggling a little to understand the behaviour of "software based variables". Rickj, I've taken your advice and slowed scan cycle time in an attempt to better understand execution behaviour (thanks for the tip).

    With respect to the "read inputs, execute code, update outputs" sequence... how does this apply to system variables - and by that I mean, purely software based variables, not "physical IO". It seems as if the program can update variables dynamically as it is executing.

    This question makes me feel a little dumb, I'm not fully grasping the logic as yet.

    Thanks again

     
  • Anonymous - 2018-11-07

    Originally created by: rickj

    Software variables are updated whenever written, as you correctly observed. However, input and output parameters work a bit differently.

    The other thing you may need to get your head around, if you haven't already, is that ladder language is basically an "all the code is executed all the time" kind of thing. Conditionally executed code needs to be wrapped in an action, function, method, etc and then called conditionally. Coils write to Boolean variables all the time so you can't have two coils writing to the same variable in the same pou. If you want to conditionally write to a Boolean in ladder language you would need to use a MOVE function block or Set/Clear type coils.

    I appreciate where you're coming from and the fact that you want to understand. Don't be shy to ask questions.

     
  • Anonymous - 2018-11-08

    Originally created by: scott_cunningham

    Let’s think how the TON code works inside (at least one way):

    Now = device time
    If not EN then
    Trip = Now + PT
    End if

    If Now > Trip then
    Q = true
    Else
    Q = false
    End if

    Of course this way doesn’t give the ET, but it explains some things:

    1) Scan time is not factored in - everything is based on the clock.

    2) Once Q goes true, it will stay true until EN is dropped.

    3) When you use Timer(EN:=NOT(Timer.Q)), EN will go false on the next code scan after Q goes true.

    4) If you set the PLC scab to exactly 1ms, and use a PT of 1 sec, Timer.Q will be true for 1ms, every 1.002 seconds. (1 second plus 1 scan to set EN false plus 1 scan to EN true).

    These observations are based on my experience and duplication of events with my own versions of TON FBs.

     
  • dFx

    dFx - 2018-11-14

    dFx hat geschrieben:
    read inputs, execute code, update outputs mantra

    This does NOT apply ONLY to physical I/Os. Every sub-code execution works also like this (functions, function blocks).

    To me, you are confused by 2 things :
    1) Code is executed line by line, up to down, and therefore, code that is in a IF block will be executed if, when reading the if condition line, it is true. Even if in this same IF block, the condition would be evaluated to false, because of some value change. What only counts was the value of your test WHEN evaluating it.

    a := 5;
    IF a == 5 THEN
    Β  Β a := 8;
    Β  Β b := 3;
    END_IF;
    

    In this exemple, "b := 3;" line will be executed, because your code is interpreted line by line, up to down, and therefore once you entered a IF block, you execute all the lines in it.

    2) functions parameters and function blocks uses private memory, meaning the values in these memory addresses need to be set before executing the function. As says the mantra, you first update inputs, then execute code that update private memory outputs, then private memory outputs are copied over your calling outputs values.
    Let say we have function name funcA, with only 1 input named inputA, and 1 ouput named ouputA.
    When you call your function using

    funcA (inputA := MyInputValue, ouputA => MyOutputValue);
    

    internaly this is what your plc will do :

    funcA.inputAΒ  := MyInputValue;
    funcA(); // execute you function code
    MyOutputValue := funcA.outputA;
    

    Hope it is as clear as possible.

    Kind regards,
    dFx

    Edited for typo

     

Log in to post a comment.