• Not Answered

Single line of CALC block expression unsuccessful - Need a Root Cause

My module is set up with the following as the CALC block expression:

IF 'IN1.CV' = 1 OR '^/PID1/PV.ST' = BAD THEN

IF '^/PID1/MODE.TARGET' != MAN THEN

'^/PID1/MODE.TARGET' := MAN

END_IF;

'^/PID1/OUT.CV' := 0;

'^/START.CV' := 0;

END_IF;

IF '^/PID1/PV.ST' = BAD THEN

'OUT1.CV' := 1

ELSE

'OUT1.CV' := 0

END_IF;

 

We recently had the 5th line (and only this line) of the code not execute for over 30+ minutes of the IN1.CV = 1, but we have no visibility retrospectively as to why it didn’t execute

  • The assumed root cause is a PID block error preventing the write; however, line 2 & 3 did write (put the valve into manual mode) --- could a PID block error have caused this if it occurred exactly between line 3 and line 5 executions?
    • What other root cause might this be ? [Note: all other lines of the CALC block were confirmed within Continuous Historian to have executed as written]
  • Should the PID1/PV.ST = BAD have been active if there was a PID block error? [Note: we did not get the alarm tied to OUT1.CV=1]
    • Does PID1/PV.ST = BAD indicate ANY issues within the PID function block?
      • Is this also true if using an FF device (PID block is assigned to a FF Fisher/Baumann control valve)
      • If not, what is the PID1/PV.ST=BAD actually detecting?

If I add a PV_BAD alarm to the entire module, will it capture all device problems that might prevent me from closing my valve per the 5th line in the code in the future?

4 Replies

  • RE: We recently had the 5th line (and only this line) of the code not execute for over 30+ minutes of the IN1.CV = 1
    Can you try to capture value of `^/PID1/MODE.ACTUAL'?

    Like this should be the new line 5.
    OUT2 := `^/PID1/MODE.ACTUAL'
    '^/PID1/OUT.CV' := 0;

    I am guessing that the actual mode may not be MAN hence writing to OUT was rejected.
  • Not sure if this is the problem or not, but as a general rule... never use .ST = BAD. Statuses are an 8-bit unsigned integer where >= 128 are all various types of "good" and < 128 are various types of "bad". There is a table of all status codes in BOL. You need your comparison to be PV.ST < 128 or you can use PV.ST < GOOD as the constant GOOD=128.

    The lower bad value is worse, so it is common to use the following in a CALC block:  'OUT1.ST' := MIN('IN1.ST', 'IN2.ST');

    Edit: Added table screenshot.

  • One thing to keep in mind is how function blocks execute. I agree with Lun that's is probably because the PID block is rejecting the write to out. When you set a FB to a particular mode, it takes a scan (or more possibly) to actually reach that mode (especially when cascaded with other blocks because of the bkcal). This is problematic when originally writing a /OUT when you don't know the mode of the function block.

    If there are interlocks or the downstream block is not in CAS, then likely it would not accept the write to OUT. I would probabably check

    IF
    ('^/PID1/MODE.ACTUAL' = MAN)
    THEN
    '^/PID1/OUT.CV' := 0;
    ENDIF;



    I would also suggest a few other changes if I were writing this code (keep in mind, I'm seeing the expression in a vacuum), but this very much looks like an interlock and a Hold in Man option from the AT block. This might be an alternative to doing custom logic in a calc block. Also, I just want to point out one additional thing. The last 5 lines can be written as OUT1 := ('^/PID1/PV.ST' = BAD);

    BAD as a constant represents .ST < 64. What's missing between 64 and <128 which is Uncertain.
  • In reply to Matt Forbis:

    Using key words of BAD, UNCERTAIN or GOOD if fine. These define the ranges of Status, and effectively are looking at the 2 Status bits of the Status byte.

    The status of PV.ST is based on the incoming value for PV. The BLOCK Error will reflect an input failure, but that does not indicate a fault in the block. The fault is upstream on the PV Source, either AI block or IO reference.

    The PID Block has built in option to shed to MAN on a Bad PV, and coupled with an AI, an Uncertain PV can be handled as a Bad PV and trigger PID mode shedding to manual. This is intended to let the PID block hold its Output on a bad PV rather than possibly integrate due to an invalid PV (Fail Hi on Thermocouple burn out, or Low depending on process design).

    If you drive the PID/OUT to 0 on a PV failure, you disrupt the process that could otherwise hold steady in MAN and alert the Operator who might be able to take action to maintain operation. The secondary action on the PID/OUT could come after a pause to let the Operator respond to the failed signal. An immediate alarm on Bad PV leaves not time for the Operator to respond, which technically reduces that alarms priority. No time to respond.

    Shedding to manual prevents wind up on the PID and keeps process stable. An interlock can be added to force the output after a set time. The PV_BAD alarm has more value if the operator is given time to respond. If there is no Time to Respond, it should not be an alarm, but a log event. An alarm requires a consequence and a time to respond.

    But as mentioned in other posts, a Write to PID/OUT must wait till MODE.ACTUAL is in MAN. Also, your logic begins writing to PID/OUT immediately before the MODE has time to change.

    Error handling is always more work.

    Andre Dicaire