Simple counter with autoreset

bartm
2020-11-24
2020-11-29
  • bartm - 2020-11-24

    The idea was to setup a simple counter.
    If there is no more counting pulse after a set time, the counter is reset to 0 at the next counting pulse.
    Everything works perfectly, except when the counter is automatically set to 0, there have to be 2 counting pulses before going to state 1, there should be only one because the counter is at 0.

    Where did I make a mistake?

    code(* read system time *)
    tx := DWORD_TO_TIME(T_PLC_MS());
    
    (* Rising edge detection *)
    fb1 (CLK:=in);
    
    (* count the number of clicks *)
    IF fb1.Q = TRUE AND (tx - last) < return_time THEN
        last := tx;
        state := state + 1;
        IF (state > max_steps)  THEN
            state := 0;
        END_IF
    ELSIF ((tx - last) > return_time AND fb1.Q = TRUE   )  THEN
        state := 0;
        last := tx;
    ELSIF reset = TRUE THEN
        state := 0;
        last := tx;
    END_IF
    
     
  • Morberis

    Morberis - 2020-11-25

    Try running a trace on it that includes all the variables.

     
  • ndzied2 - 2020-11-29

    Here's what I came up with:

    FUNCTION_BLOCK MyCounter
    VAR_INPUT
        xIn:        BOOL;   // Count on rising edge of Input
        diDelayMS:  DINT;   // Delay before reset in miliseconds
        xReset:     BOOL;   // Reset the counter to zero on input
    END_VAR
    VAR_OUTPUT
        diCount:    DINT;   // Internal Counter
    END_VAR
    VAR
        tDelay:     TON;    // Timer
        MyTrig:     R_TRIG; // Trigger for input
    END_VAR
    
    =============================================
    
    // Rising Edge in the Input
    MyTrig(CLK:= xIn);
    
    IF MyTrig.Q THEN
        IF tDelay.Q THEN
            // If count is already 0 then we can make it 1
            IF diCount = 0 THEN
                diCount := 1;
            ELSE
                diCount := 0;
            END_IF
    
        ELSE
            diCount := diCount + 1;
        END_IF
    END_IF
    
    // Reset the count if xReset Input is set
    IF xreset THEN
        diCount := 0;
    END_IF
    
    // The Timer to force counter to zero
    // This is at the bottom so that it doesn't prevent counting
    tDelay(IN:= NOT xIn, PT:= DINT_TO_TIME(diDelayMS));
    
     

Log in to post a comment.