Life Sign Generation (TON does not work as required.)

necati
2022-12-08
2022-12-11
  • necati - 2022-12-08

    Dear All,

    I am trying to generate a life sign which increases by 1 in every 32ms. My program which shown below, increases life sign in approximately every 80 ms. How can fix it to 32ms? Could you please help me?

    PROGRAM POU_2
    VAR_INPUT
        cycle_time: TIME:= T#32ms;
    END_VAR
    VAR_OUTPUT
        life_sign: USINT:= 0;
    END_VAR
    VAR
        TON_0: TON;
        R_TRIG_0: R_TRIG;
        time_ms: SysTimeRtc.SYSTIME;
        time_array: ARRAY[0..999, 0..1] OF ULINT;
        prev_time: ULINT:= 0;
        i: INT:= 0;
    END_VAR
    

     
  • sgronchi - 2022-12-11

    First - what's the task cycle time? Timers cannot have better resolution than that.
    E.g. if your task cycle time is 20 ms, the following happens (every bullet is a cycle - the first is the global clock):

    1) t#000ms - IN = TRUE - ET = t#0ms - Q = FALSE
    2) t#020ms - IN = TRUE - ET = t#20ms - Q = FALSE
    3) t#040ms - IN = TRUE - ET = t#40ms - Q = TRUE
    4) t#060ms - IN = FALSE - ET = t#0ms - Q = FALSE
    5) t#080ms - IN = TRUE - ET = t#0ms - Q = FALSE
    6) t#100ms - IN = TRUE - ET = t#20ms - Q = FALSE
    7) t#120ms - IN = TRUE - ET = t#40ms - Q = TRUE

    As you can see, the interval between two Q = TRUE is 80 ms. Remember, Q = (ET >= PT).

    Furthermore, you should notice that in this way you need two cycles for resetting (point 4 and 5) - if you want to avoid that, you should call the timer with IN = FALSE and then IN = TRUE in the same cycle as the one when Q got TRUE, for a total of three times in a single cycle.

    The ST way is the most elegant (below), in LD/FBD is a bit uglier (Q starts an EN/ENO line on the same timer called two times - it SHOULD work), in CFC is horrible (you should set a variable and then use that to call the timer two times and finally reset it):

    tmr(IN := TRUE);
    IF tmr.Q THEN
        tmr(IN := FALSE);
        tmr(IN := TRUE);
    
        // your code to be executed
    END_IF
    
     
    πŸ‘
    1
  • sgronchi - 2022-12-11

    Anyway a better way for what you want to achieve is executing the task with 32 ms (or submultiple like 16, 8, 4 ms...) execution time and increment the counter every 1 (2, 4, 8...) cycles without timers. You'll get the best behaviour your platform can provide.

     
  • hermsen

    hermsen - 2022-12-11

    a super easy way for a Watchdog signal is just to add a global var iWdTaskX and tally it up every cycle. If you have more tasks running just name them accordingly

    so in task XYZ we program a single line of code somewhere;

    GVL.iTaskXYZ := GVL.iTaskXYZ + 1;
    

    Remember that a change in value matters and as long as the current value differs from the last received value we are gold.

     
  • hermsen

    hermsen - 2022-12-11
     

    Last edit: hermsen 2022-12-11

Log in to post a comment.