• Not Answered

Comparing analog value to a previous value

Hello,

I'd like to create an Alarm/Prompt/Message whenever a setpoint is changed to remind operator to make manual changes in the field. I'm trying to figure out the logic for how to do so. Is it possible to do a While loop that returns Current Value and Previous Value and if they are different by some delta it would make an output TRUE (:= 1)?

Thanks,

Raul Chacon

6 Replies

  • Hello Raul,

    One way that will work is to store the Setpoint in a CALC variable and compare it to the current Setpoint.

    Current_SP := In1;

    If
    Current_SP <> SP_Last_Scan
    Then
    Out1 := True;
    EndIf;

    SP_Last_Scan := Current_SP;

    Keith
  • In reply to KeithStThomas:

    If you want this suggested logic to survive a partial download of the module then you need to use an output of the CALC instead of a CALC variable as variables are reset to 0 on download.

    Current_SP := In1;

    If
    Current_SP <> Out2
    Then
    Out1 := True;
    EndIf;

    Out2 := Current_SP;

    You also need "something" to reset the Out1 to False when you don't want this active anymore...
  • In reply to Matt Stoner:

    Good point Matt. We have used Input or Write parameters, and set the module to preserve user defined parameters on download, but good to know that Outx of a Calc block will hold through a download too.

    My example code is also missing a line to return the output to False. In the example below, Out1 will be true for 1 scan. But it could also be setup so something else resets Out1 to False, such as an operator reset button on a graphic.

    Current_SP := In1;

    If
    Current_SP <> Out2
    Then
    Out1 := True;
    Else
    Out1 := False;
    EndIf;

    Out2 := Current_SP;
  • In reply to Matt Stoner:

    In the examples given, there is no While Do Loop, as none is needed.  The logic executes each scan of the module.  There are a myriad of ways to accomplish this.  The key is to have the last value of SP to compare to, and then develop robust logic to avoid spurious messages or phantom messages.  

    In a CALC block, you can create an initialization sequence to set an internal flag.  

    Current_SP := IN1;

    If (FLAG = 0) then

      FLAG := 1;

      OUT1 :-= 0;  REM  initialize OUT1 to 0

    ELSE;

     IF (Last_SP <> Current_SP)  Then

        OUT1:= 1;

     Else;

        OUT1 := 0;

     ENDIF;

    ENDIF;

    Last_SP := Current_SP;

    On initial execution, the FLAG variable will be 0, and is set to 1, and exits the IF statement to set the Last_SP to the Current value.  on the next scan, the FLAG is 1 and so the logic checks for a change in SP, and toggles OUT1 for one scan on an operator change of SP.  

    A one shot condition change will create a fleeting alarm, that will be inactive/unacknowledged.  Is this that you want?  Is there a more explicit confirmation that the required field action has been completed?  assuming there is, you can add logic to validate the action is complete before setting OUT1 to 0.

    Current_SP := IN1;

    If (FLAG = 0) then

      FLAG := 1;

      OUT1 :-= 0;  REM  initialize OUT1 to 0

    ELSE;

     IF (Last_SP <> Current_SP) and (OUT1 = 0) Then

        OUT1:= 1;

     Else;

        IF ("FIELD ACTION COMPLETED CHECK") then

            OUT1 := 0;

        ENDIF;

     ENDIF;

    ENDIF;

    Last_SP := Current_SP;

    As Matt suggested, you may want to add a means to disable this, which could be as simple as disabling the Alarm, or adding an additional condition in the first IF statement so that the FLAG must be 1 and the enable must be true.

    IF (FLAG =0) OR (IN2 = 0) then

      FLAG := 1;

      OUT1 :-= 0;  REM  initialize OUT1 to 0

    ELSE

    but the logic always branches and never sets OUT1 true. If you disable this while OUT1 is equal to 1, you need to reset OUT1.

    If you don't have this added enable logic, the OUT1 will reset to 0 based on the logic in the nested IF statement.

    The Comparator Block provides a <> comparison.  One can wire the SP to an OUT Parameter and then using an Internal REference to this parameter, you get the last scan of SP.  Connecting this as the reference input along with SP wired in, the Comparator block would deliver the same logic.  Then a Reset/Set Flip flop to latch the output until an explicit confirmation happens.  The Alarm would be created off the SR block output.

    Is this better?  I don't know, but it avoids a CALC block and displays the logic, provided you understand the function.  The wired Output "SP" is updated at the end of the module execution.  The "LAST_SP" is an internal reference that reads "SP" at the beginning of each scan, which means it reads the value of SP from the last scan.  The comparator NEQ output will true for one scan so the SR flip flop latches this until it is reset.  The Reset parameter could be an external reference or a CND block.  Alternatively, the RS block is replaced with a retentive timer that clears the alarm after a set time.  

    You can package this into a Composite block with the SP as the input.  Inside the block, you have an FB representation of the function.  That keeps the top level view of the module clean and allows you to manage the features of this block in one location in your library.  I would add an Output parameter for the alarm reference.  Note that the Comparator can also provide if the SP change was positive or negative.  This lets you make changes to the logic that drives the OUT_D of this logic and still allow existing alarm references to work.

    Something to think about.  The CALC block provides great flexibility, but it does not handle timers and is a bit harder to work with for the uninitiated.  Some prefer expressions, some prefer function blocks.  

    Andre Dicaire

  • In reply to Andre Dicaire:

    I like the idea of canning this in a composite block for re-use. You could use the message box to invoke the reset. I'm getting asked for fat-finger protection (preventing an inadvertent too-large SP change) and have done it both in the module and in the faceplate itself. Scaling would need to happen somewhere (% of PID1/IN_SCALE) . . . maybe I'll start a new thread.
  • a more function block and timely based approch could be to use a dead time FB and a comperator FB

    Stefan Müllner
    Senior Plant Engineer - Automation & Systems

    METADYNEA AUSTRIA GmbH