Dynamic Model-based Predictive Controller

DynaMPC is a Dynamic Model-based Predictive Controller that is especially useful for constraint control applications involving long deadtimes and lags, and analyzer inputs. In general, these applications are difficult to implement with standard PID controllers.

DynaMPC utilizes a deadtime plus second-order lag dynamic model to predict the future value of the control variable (CV) using the historical values of the manipulated variable (MV) and up to five disturbance variables (DV). Then, DynaMPC calculates the MV change required to bring the CV to the controller setpoint at the end of the control horizon.

This document has been written assuming that the engineer is familiar with the Foxboro I/A system.

Background

The PID control algorithm provides excellent control for fast-responding loops. However, it is not easy to tune for relatively slow-responding loops, especially those involving long deadtimes. The integral action causes cycling when set too fast, or excessive offset from setpoint when set too slow. DynaMPC has been developed to handle these difficult control applications.

However, DynaMPC may be difficult to implement for large multi-variable control applications. These applications will require a full-feature multi-variable controller, such as DMC.

APPLICATION EXAMPLES

Feed Maximization Example

An example of a typical DynaMPC application is feed maximization. The control objective is to increase the feed rate to a process unit until one or more constraints are met. The response to a change in the feed rate is usually slow, so the controller would need to know that a feed rate change made now will not show up on the constraint for some time. In addition, if the actual response is deviating from the expected response, then a mid-course correction may be required to put the response back on track. DynaMPC is designed to perform these functions.

In the case of a distillation tower, the feed maximization constraints might be:

  • maximum total overhead rate (vapor flooding limit)
  • maximum reboiler steam valve position (heat input limit)
  • maximum pressure control valve position (condensing limit)

DynaMPC would determine the feed rate required to meet each constraint and then a low signal selector would select the lowest feed rate. Therefore, the most limiting constraint would be met and the feed rate would be at the maximum allowed by the constraints.

GC Analyzer Example

Another example of a suitable DynaMPC application is stream quality control using a gas chromatograph analyzer. The analyzer input is updated at the cycle time of the analyzer. In between updates, the input flat-lines at the last value. This stair-step response causes standard PID controllers to over-integrate between analyzer updates. DynaMPC is designed to anticipate the stair-step response and take appropriate control action.

APPLICATION FEATURES

DynaMPC Features

DynaMPC includes the following features, which are discussed in detail below:

  • CV projection
  • Variable model parameters
  • CV setpoint deadband
  • Control horizon determination
  • MV move suppression
  • MV setpoint ramp
  • MV increase/decrease inhibiting
  • Multiple MVs
  • Analyzer cycle projection

CV Projection

DynaMPC can project the future path of a CV given the following information:

  • the current CV value
  • the recent history of the MV and all DVs
  • the response characteristics (i.e., process gain, deadtime, and lag time constants) of the CV to changes in the MV
  • the response characteristics of the CV to changes in each of the DVs

Figure 1 shows the typical deadtime and second-order lag response of a CV to a step change in an MV.

Figure 1 CV Response to Step Change Example
Figure 1 CV Response to Step Change Example

Dynamic Model Lag

The lag is specified by two time constants, called tau1 and tau2. The following equation is the definition of second-order lag:

DelCV(t) = GMV * DelMV * {1 – [tau1 * EXP(-t / tau1) –
tau2 * EXP(-t / tau2)]/ (tau1 – tau2)} (1)

where:

DelCV(t) = Projected CV change at time t
GMV = Process gain (DelCV / DelMV)
DelMV = MV step change magnitude
t = Time since expiration of deadtime
tau1 = Lag 1 time constant
tau2 = Lag 2 time constant

Each time the MV changes, the model can project the CV response due to that MV change. The various responses are superimposed to obtain the net projection. Figure 2 shows this procedure graphically.

Figure 2 Superimposed CV Responses
Figure 2 Superimposed CV Responses

Dynamic Model Time Periods

The CV projection is actually an array of 30 values, each element of which is the CV projection at the end of a time period. The time period length is configurable, and should be set so that the entire response is completed by the end of the last time period. Figure 3 illustrates this concept. Notice that the response is essentially completed by the last time period.

Each time DynaMPC is executed, the latest changes in the MV and each DV are converted to equivalent changes in the CV, as shown below:

Del(t) = [GMV*DelMV(t)] + [GDV1*DelDV1(t)] + [GDV2*DelDV2(t)] + … (2)

where:

Del(t) = Projected CV change in time period t due to latest MV/DV changes
DelMV(t) = Portion of MV change that will affect CV in time period t (obtained from response curve)
GMV = MV process gain (DelCV / DelMV)
DelDVi(t) = Portion of DVi change that will affect CV in time period t (obtained from response curve)
GDVi = DVi process gain (DelCV / DelDVi)

These latest changes are combined with the CV changes calculated during the previous execution. Please note that with each execution, the time periods must advance, as does time itself. Therefore, the previous CV changes must be obtained from the array element that was the next time period in the previous execution.

DelCV(t) = Del(t) + DelCV(t+1) (3)

where:

DelCV(t+1) = Projected CV change due to all previous MV/DV changes

Figure 3 Dynamic Model Time Periods
Figure 3 Dynamic Model Time Periods

Model Execution Frequency vs Time Period Length

The previous discussion assumed that the model was executed at the same frequency as the time period length. However, the model can be executed more frequently, if desired. This is especially important for control action, which is discussed later. DynaMPC calculates the fraction of a time period that the execution frequency represents and then uses that fraction to adjust the projected CV array to the new time period boundaries. Equation 3 is modified to include this feature, as shown below:

DelCV(t) = Del(t) + [Ftp * DelCV(t+1)] + [(1 – Ftp) * DelCV(t)] (4)

where:

DelCV(t) = Projected CV change in time period t due to all previous MV/DV changes
DelCV(t+1)= Projected CV change in next time period due to all previous MV/DV changes
Ftp = Fraction of time period elapsed since previous execution

Please note that equation 4 is identical to equation 3 when the execution frequency is the same as the time period length (i.e., Ftp = 1).

Projected CV Calculation

So far, we have only projected the change in the CV. However, we need the actual value of the CV throughout the projection period for control purposes. This is obtained by starting with the current CV and adding the CV change for each time period as we step through the time periods.

CV(t) = CV(t-1) + DelCV(t) (5)

where:

CV(t) = Projected CV at the end of time period t
CV(t-1) = Projected CV at the end of the previous time period (note: CV(0) is the current CV)
DelCV(t) = Projected CV change in time period t due to all MV/DV changes

Variable Model Parameters

As the above equations show, the DynaMPC dynamic model is structured as an incremental model. During each execution, DynaMPC converts the MV and DV changes into equivalent CV changes and stores the result into the array of 30 time periods. Because of this, all model parameters can be varied from one execution to the next without requiring the model to be re-initialized.

For example, if the process gain is changed, then all future calculations of the CV change will reflect the new gain. However, all previous CV changes calculated with the old gain are not affected. DynaMPC assumes that when the gain changes, the new gain applies only to the future.

Deadtime and lag can also be varied within limits. This feature permits transportation delay to be incorporated into the model. However, these time-oriented parameters should not be altered such that the response occurs beyond the end of the 30 time periods. Changing the time period length is not an option in this case, because the model must be initialized when this is done.

Care should be exercised when varying the model parameters. Excessive parameter fluctuations could cause model instability. At the very least, the parameters should be averaged before being used in DynaMPC.

CV Setpoint Deadband

After projecting the CV, DynaMPC can then determine the MV change required to achieve the CV setpoint. The CV setpoint is an operator-entry that is limited to maximum and minimum values. The setpoint limits are engineer entries.

DynaMPC also includes a setpoint deadband. If the projected CV is within the deadband, then the CV is close enough to the setpoint and no change is made to the MV. The deadband is an engineer entry to DynaMPC.

The deadband location vs. the CV setpoint depends upon the CV type, which is also an engineer entry:

  • maximum constraint (the most likely CV type)
  • minimum constraint
  • normal setpoint

Maximum Constraint

If the CV is a maximum constraint, then exceeding the setpoint is a potential violation of a process or equipment limit. Control action should be taken to bring the CV back down below the setpoint. However, when the CV is below the setpoint, control action is less urgent because the CV is on the “safe” side. Therefore, for a maximum constraint, the location of the deadband is below the setpoint, as shown in Figure 4.

Figure 4 Maximum Constraint CV
Figure 4 Maximum Constraint CV

Minimum Constraint

If the CV is a minimum constraint, then being below the setpoint is a potential violation of a process or equipment limit. Control action should be taken to bring the CV back above the setpoint. However, when the CV is above the setpoint, control action is less urgent because the CV is on the “safe” side. Therefore, for a minimum constraint, the location of the deadband is above the setpoint, as shown in Figure 5.

Figure 5 Minimum Constraint CV
Figure 5 Minimum Constraint CV

Normal Setpoint

If the CV is a normal setpoint, then the CV can be either above or below it without causing concern. There is no “safe” versus “unsafe” side. In this case, half of the deadband is above the setpoint and the other half is below, as shown in Figure 6.

Figure 6 Normal Setpoint CV
Figure 6 Normal Setpoint CV

Control Horizon Determination

DynaMPC determines the minimum MV change required to bring the CV to the closest deadband boundary, called the CV target, at the end of the control horizon. The control horizon is the time required for the CV to reach a stable value after a step change in the MV. It is an engineer entry and is in terms of multiples of the sum of the two MV lag time constants. Typical values are three, at which point the response will be at 95% of the final value, and four, which achieves 98% of the final value. Specifying the control horizon in time-constant multiples, rather than in straight time, automatically adjusts the control horizon whenever the deadtime or lag is changed.

The MV change is calculated as follows:

DelMV = [Target – CV(horz)] / GMV (6)

where:

Target = Nearest boundary of the CV deadband
CV(horz) = Projected CV at the end of the control horizon
GMV = MV process gain (DelCV / DelMV)

MV Move Suppression

Equation 6 above determines the MV change required to move the projected CV to the target. The target is defined to be the nearest boundary of the deadband. If the CV is far away from the target, then a large MV change will be calculated. It is possible that the model is not as accurate for large deviations from target as it is for small deviations, perhaps due to some non-linearity. Therefore, it may not be wise to make the full MV change. Perhaps some of the move should be suppressed and reconsidered after the CV has time to respond.

For example, suppose that the CV is a maximum constraint and that its projection is well below the bottom of the deadband, as shown in Figure 7. To prevent a large overshoot, the engineer may decide to take only a portion of the calculated move, say 50%. DynaMPC accommodates this desire by allowing the engineer to temporarily expand the deadband toward the CV. The new move suppression target is substituted for the target value in equation 6, and a smaller MV change is calculated.

Figure 7 MV Move Suppression (Maximum Constraint)
Figure 7 MV Move Suppression (Maximum Constraint)

Move Suppression Target

The equation for the move suppression target is as follows:

TargMS = SPTCV + FactMS * [CV(0) – SPTCV] (7)

where:

SPTCV = CV setpoint
CV(0) = Current CV
FactMS = Move suppression factor (0.0 to 1.0)

Move suppression itself can be suppressed for maximum and minimum constraints. DynaMPC can be configured to cancel move suppression when the CV is on the “unsafe” side of the setpoint. In this case, the MV change is calculated to return the CV to safe territory as rapidly as possible, even if the CV overshoots into “safe” territory.

For a maximum constraint, the safe side is below the setpoint. Likewise, for a minimum constraint, the safe side is above the setpoint. A normal setpoint does not have a “safe” versus “unsafe” side, so move suppression is always active on both sides of the setpoint.

MV Setpoint Ramp

DynaMPC includes the ability to ramp the MV setpoint to the calculated value. The ramp rates are engineer entries and can be different for increases vs. decreases.

MV Increase / Decrease Inhibiting

DynaMPC also includes the ability to inhibit MV setpoint increases and/or decreases. This feature is useful when a temporary process condition occurs that is not conducive to MV changes. For example, suppose a control valve is wide open downstream of the MV and that any additional MV increases would result in a level filling up. In this case, the valve position can be monitored and the MV increase inhibit triggered whenever the valve is too far open. After the operator opens the control valve bypass and gets the valve back into control range, then the MV inhibit trigger can be released and MV increases permitted again.

Multiple MVs

A DynaMPC controller is designed primarily for a single CV/MV combination. However, DynaMPC can be configured to handle more than one MV, each of which affects the same CV.

One DynaMPC controller, called the main controller, performs the CV projection using one of the MVs, with the other MVs entered as DVs. Then, the CV projection is passed to the DynaMPC auxiliary controllers, one for each remaining MV. An execution trigger is also passed along so that all will execute at roughly the same time. These auxiliary controllers calculate the change for their MV based upon the CV projection provided by the DynaMPC main controller. Figure 8 illustrates the control structure.

Move suppression is essential for this application because each controller is calculating its MV change without regard for the others. Therefore, overshoot is almost guaranteed without move suppression.

Figure 8 Multiple MV Control Structure
Figure 8 Multiple MV Control Structure

GC Analyzer Cycle Projection

One of the more difficult CVs to control is the discontinuous input from a sampling analyzer, such as a GC. The typical response curve is a stair-step approximation of the normal continuous curve, as shown in Figure 9. The stair-steps cause the CV projection to continuously move to the left while on the flat part of the response curve and then suddenly snap back to the projected path when the analyzer updates. The oscillating CV projection can cause the controller to move the MV similarly, thus resulting in a lot of needless MV changes.

DynaMPC includes logic that permits the analyzer input to be ignored during the flat-line portion of the response. Instead, DynaMPC assumes that the CV follows the projected path in between analyzer updates and corrects the projection only when a new sample is received from the analyzer. This eliminates the oscillations in the projected CV and minimizes MV changes.

Figure 9 GC Analyzer Response to Step Change
Figure 9 GC Analyzer Response to Step Change

FOXBORO I/A IMPLEMENTATION

I/A Blocks

DynaMPC is implemented via standard Foxboro I/A blocks. The function of each block is described below along with CALCA block steps and the HLBL sequence program. In addition, the following types of parameters are listed and defined:

  • output parameters – values that the block generates for use in other blocks or displays;
  • configuration parameters – values that are preset by Foxboro and should seldom require changing;
  • tuning parameters – values that the control engineer can readily change from the block detail display;
  • operator parameters – values that the operator can readily change from graphic displays.

The following blocks must be built to implement one DynaMPC controller (note: ##### should be replaced by a mnemonic that identifies the CV):

  • #####LOG Model initialization logic block
  • #####DVi Disturbance variable data block (i = 1 to 5)
  • #####TIM Execution timer block (in compound zone SEQ)
  • #####MPC DynaMPC main controller block (in compound zone SEQ)

If the DynaMPC application includes multiple MVs, as described in the previous section, then an auxiliary controller block will be required for each additional MV. The name for the block should be based on the main controller, with a suffix added to make the name unique (e.g., #####MPC2).

If a CP contains more than one DynaMPC controller, then a DynaMPC scheduler block should be added to prevent more than one controller from executing at the same time. Also, an analyzer cycle block must be included if the CV comes from a discontinuous analyzer.

Model Initialization Logic Block

The model initialization logic block (#####LOG) is a CALCA block that performs logic to initialize the model when a bad input is detected or on engineer command. This block is required for each DynaMPC main controller.

Output Parameters

  • BO01 = model initialization signal to DynaMPC main controller.
  • BO02 = DV1 initialization signal to DynaMPC main controller.
  • BO03 = DV2 initialization signal to DynaMPC main controller.
  • BO04 = DV3 initialization signal to DynaMPC main controller.
  • BO05 = DV4 initialization signal to DynaMPC main controller.
  • BO06 = DV5 initialization signal to DynaMPC main controller.

Configuration Parameters

• PERIOD = 1 (0.5 sec) or 2 (1.0 sec execution frequency).
• MA = lock into auto (:#####LOG.MA.1).
• TIMINI = 1.
• BI01 = CV bad signal indicator.
• BI02 = MV bad signal indicator.
• BI03 = DV1 bad signal indicator.
• BI04 = DV2 bad signal indicator.
• BI05 = DV3 bad signal indicator.
• BI06 = DV4 bad signal indicator.
• BI07 = DV5 bad signal indicator.
• BI08 = Analyzer frozen alarm from Analyzer Cycle Block BO03.
• BI14 = CV controller MA parameter (if CV is a controller).
• BI15 = MV controller INITO parameter.
• M01 = delay time (sec) for return from bad signal.

Tuning Parameters

  • BI09 = DV1 initialization command (1=init). The model will ignore the DV1 input while this parameter is set to 1 or when the DV1 input is bad (BI03).
  • BI10 = DV2 initialization command (1=init). The model will ignore the DV2 input while this parameter is set to 1 or when the DV2 input is bad (BI04).
  • BI11 = DV3 initialization command (1=init). The model will ignore the DV3 input while this parameter is set to 1 or when the DV3 input is bad (BI05).
  • BI12 = DV4 initialization command (1=init). The model will ignore the DV4 input while this parameter is set to 1 or when the DV4 input is bad (BI06).
  • BI13 = DV5 initialization command (1=init). The model will ignore the DV5 input while this parameter is set to 1 or when the DV5 input is bad (BI07).
  • BI16 = model initialization command (1=init). The model will initialize itself while this parameter is set to 1 or when it detects a bad CV (BI01), bad MV (BI02), analyzer frozen alarm (BI08), CV in manual (BI14), or MV initializing (BI15).

Model Initialization Logic Block Steps

STEP01 = OR BI01 BI02 ;CV OR MV BAD
STEP02 = DOFF M01 ;DELAY RETURN FM BAD
STEP03 = OR BI16 ;MODEL INIT COMMAND
STEP04 = OUT BO01 ;>DYNAMPC.BI0003&4
STEP05 = IN BI03 ;DV1 BAD
STEP06 = DOFF M01 ;DELAY RETURN FM BAD
STEP07 = OR BI09 ;DV1 INIT COMMAND
STEP08 = OUT BO02 ;>DYNAMPC.BI0005
STEP09 = IN BI04 ;DV2 BAD
STEP10 = DOFF M01 ;DELAY RETURN FM BAD
STEP11 = OR BI10 ;DV2 INIT COMMAND
STEP12 = OUT BO03 ;>DYNAMPC.BI0006
STEP13 = IN BI05 ;DV3 BAD
STEP14 = DOFF M01 ;DELAY RETURN FM BAD
STEP15 = OR BI11 ;DV3 INIT COMMAND
STEP16 = OUT BO04 ;>DYNAMPC.BI0007
STEP17 = IN BI06 ;DV4 BAD
STEP18 = DOFF M01 ;DELAY RETURN FM BAD
STEP19 = OR BI12 ;DV4 INIT COMMAND
STEP20 = OUT BO05 ;>DYNAMPC.BI0008
STEP21 = IN BI07 ;DV5 BAD
STEP22 = DOFF M01 ;DELAY RETURN FM BAD
STEP23 = OR BI13 ;DV5 INIT COMMAND
STEP24 = OUT BO06 ;>DYNAMPC.BI0009
STEP25 = CST
STEP26 = OR BO01 BI08 ;ANALYZER FROZEN ALARM
STEP27 = OR BI14 BI15 ;CV MAN OR MV INITO
STEP28 = OR 2
STEP29 = OUT BO01 ;MODEL INIT
STEP30 = END

Disturbance Variable Data Block

The disturbance variable data block (#####DVi) is an MAIN block that provides the input value, process gain, deadtime, and lag time constants for a disturbance variable. This block is required only if a DV has been defined for this DynaMPC controller. Each DV must have a separate MAIN block.

Output Parameters

  • PNT_1 = DVi input value (filtered and limited).
  • PNT_2 = DVi process gain (limited).
  • PNT_3 = DVi deadtime (limited).
  • PNT_4 = DVi lag 1 time constant (limited).
  • PNT_5 = DVi lag 2 time constant (limited).

Configuration Parameters

  • PERIOD = same as model initialization logic block.
  • IOMOPT = 2 (software input).
  • MA = lock into auto (:#####DVi.MA.1).
  • MEAS_1 = must be connected to DVi input.
  • HSCO1 = maximum allowed DVi input value.
  • LSCO1 = minimum allowed DVi input value.
  • FLOP_1 = 1 to enable signal filtering for input value.
  • HSCO2 = maximum allowed DVi process gain (note: if gain is negative, then this value should be 0.0 or less).
  • LSCO2 = minimum allowed DVi process gain (note: if gain is negative, then this value should also be negative).
  • HSCO3 = maximum allowed DVi deadtime.
  • LSCO3 = minimum allowed DVi deadtime.
  • HSCO4 = maximum allowed DVi lag 1 time constant.
  • LSCO4 = minimum allowed DVi lag 1 time constant.
  • HSCO5 = maximum allowed DVi lag 2 time constant.
  • LSCO5 = minimum allowed DVi lag 2 time constant.

Tuning Parameters

  • FTIM_1 = filter time constant for DVi input signal (used to attenuate high frequency noise).
  • MEAS_2 = DVi process gain (must be negative if a DV increase causes a CV decrease). If gain is variable, then this parameter must be connected to a block that calculates the gain.
  • MEAS_3 = DVi deadtime. If deadtime is variable, then this parameter must be connected to a block that calculates the deadtime.
  • MEAS_4 = DVi lag 1 time constant. If lag is variable, then this parameter must be connected to a block that calculates the lag.
  • MEAS_5 = DVi lag 2 time constant. If lag is variable, then this parameter must be connected to a block that calculates the lag.

Execution Timer Block

The execution timer block (#####TIM) is a TIM block that controls the execution frequency of the DynaMPC main controller block.

Configuration Parameters

  • PERIOD = same as model initialization logic block.
  • MA = lock into auto (:#####TIM.MA.1).

DynaMPC Main Controller Block

The DynaMPC main controller block (#####MPC) is an IND block that performs the DynaMPC control functions for a main controller, as described previously. The HLBL sequence program is shown at the end of this document.

Output Parameters

  • RO0001 = MV controller remote setpoint (or input to a signal selector for constraint control). The ramp rates have been applied.
  • RO0002 = MV calculated target (where the MV is being ramped).
  • RO0003 = MV remote setpoint change from previous execution.
  • RO0004 = projected CV at end of control horizon.
  • RO0005 = CV target used to determine MV calculated target (RO0002).
  • RO0006 = CV change due to latest changes in MV and all DVs.
  • RO0007 = CV change due to latest change in MV alone.
  • RO0008 = CV change due to latest change in DV1 alone.
  • RO0009 = CV change due to latest change in DV2 alone.
  • RO0010 = CV change due to latest change in DV3 alone.
  • RO0011 = CV change due to latest change in DV4 alone.
  • RO0012 = CV change due to latest change in DV5 alone.
  • RO0013 = MV setpoint change required to meet CV target (RO0005).
  • RO0014 = projected CV at beginning of time period 1.
  • RO0015 = projected CV at end of time period 2.
  • BO0001 = control action indicator output to auxiliary controllers.
  • BO0002 = control delay output to DynaMPC scheduler block.
  • BO0003 = analyzer update acknowledge to analyzer cycle block.

Configuration Parameters

  • PERIOD = same as model initialization logic block.
  • MA = must be 1.
  • RSTMA = must be 1.
  • ACTIVE = must be 1.
  • RSTACT = must be 1.
  • RI0001 = CV input via connection.
  • RI0004 = length of time period (minutes) in dynamic model (must be set such that the 30 time periods cover the full CV response to the MV and all DVs).
  • RI0005 = model execution frequency (seconds) entered as a negative number (e.g., -60 for 1 minute frequency).
  • RI0006 = current MV value (usually MV setpoint).
  • II0002 = control horizon stated in multiples of the sum of the MV lag time constants (should be either 3 or 4).
  • BI0001 = CV is a maximum constraint (0=no / 1=yes).
  • BI0002 = CV is a minimum constraint (0=no / 1=yes).
  • BI0003 = model initialization signal from #####LOG.BO01.
  • BI0004 = MV initialization signal (default to 0).
  • BI0005 = DV1 initialization signal from #####LOG.BO02.
  • BI0006 = DV2 initialization signal from #####LOG.BO03.
  • BI0007 = DV3 initialization signal from #####LOG.BO04.
  • BI0008 = DV4 initialization signal from #####LOG.BO05.
  • BI0009 = DV5 initialization signal from #####LOG.BO06.
  • BI0012 = move suppression option (0 = cancel move suppression when on “unsafe” side of CV setpoint; 1 = use move suppression on both sides of CV setpoint).
  • BI0013 = control delay signal from DynaMPC scheduler block or alarm cycle block (1 = delay control execution for number of seconds entered in II0001).
  • BI0014 = must be 0 (used only in DynaMPC auxiliary controller block).
  • BI0015 = MV decrease inhibit command (1=inhibit). If used, it must be connected to logic in another block.
  • BI0016 = MV increase inhibit command (1=inhibit). If used, it must be connected to logic in another block.
  • BI0017 = analyzer update trigger from alarm cycle block. Must be 1 if no analyzer cycle block.
  • SN0002 = name of the execution timer block (#####TIM).
  • SN0003 = name of the DV1 data block (#####DV1). Must be a null entry if DV1 not defined.
  • SN0004 = name of the DV2 data block (#####DV2). Must be a null entry if DV2 not defined.
  • SN0005 = name of the DV3 data block (#####DV3). Must be a null entry if DV3 not defined.
  • SN0006 = name of the DV4 data block (#####DV4). Must be a null entry if DV4 not defined.
  • SN0007 = name of the DV5 data block (#####DV5). Must be a null entry if DV5 not defined.

Tuning Parameters

  • RI0003 = CV deadband.
  • RI0007 = MV process gain (must be negative if an MV increase causes a CV decrease). If gain is variable, then this parameter must be connected to a block that calculates the gain.
  • RI0008 = MV deadtime (minutes). If deadtime is variable, then this parameter must be connected to a block that calculates the deadtime.
  • RI0009 = MV lag 1 time constant (minutes). If lag is variable, then this parameter must be connected to a block that calculates the lag.
  • RI0010 = MV lag 2 time constant (minutes). If lag is variable, then this parameter must be connected to a block that calculates the lag. Enter 0.0 for first-order lag response.
  • RI0011 = MV ramp rate when increasing the MV (MV units per execution frequency). If MV is being ramped after constraint selection, then set to 99999.
  • RI0012 = MV ramp rate when decreasing the MV (MV units per execution frequency). If MV is being ramped after constraint selection, then set to 99999.
  • RI0013 = move suppression factor (FactMS term in equation 7). Must be between 0.0 and 1.0. An entry of 0.0 eliminates move suppression.
  • RI0014 = CV setpoint minimum limit (must be set to -99999 if CV setpoint RI0002 is a connection).
  • RI0015 = CV setpoint maximum limit (must be set to 99999 if CV setpoint RI0002 is a connection). If the minimum limit is set equal to or greater than the maximum, the CV setpoint is locked at the maximum.
  • II0001 = control delay time (sec) used in conjunction with control delay signal in BI0013.

Operator Parameters

  • RI0002 = CV setpoint.

DynaMPC Auxiliary Controller Block

The DynaMPC auxiliary controller block (#####MPC2) is an IND block that performs the DynaMPC control functions for an auxiliary controller, as described previously. The same HLBL sequence program is used for these IND blocks as is used for the main controller.

Output Parameters

  • RO0001 = MV controller remote setpoint (or input to a signal selector for constraint control). The ramp rates have been applied.
  • RO0002 = MV calculated target (where the MV is being ramped).
  • RO0003 = MV remote setpoint change from previous execution.
  • RO0004 = projected CV at end of control horizon.
  • RO0005 = CV target used to determine MV calculated target (RO0002).
  • RO0006 = CV change due to latest change in MV.
  • RO0013 = MV setpoint change required to meet CV target (RO0005).
  • BO0002 = control delay output to DynaMPC scheduler block.

Configuration Parameters

  • PERIOD = same as model initialization logic block.
  • MA = must be 1.
  • RSTMA = must be 1.
  • ACTIVE = must be 1.
  • RSTACT = must be 1.
  • RI0001 = same as main controller block.
  • RI0004 = connect to same parameter of main controller block.
  • RI0005 = connect to same parameter of main controller block.
  • RI0006 = current MV value (usually MV setpoint).
  • RI0007 = MV process gain obtained from parameter PNT_2 of the disturbance variable block (#####DVi) representing this MV as a DV in the main controller.
  • RI0008 = deadtime not used in auxiliary controller (set to 0.0).
  • RI0009 = lag 1 time constant not used in auxiliary controller (set to 1.0).
  • RI0010 = connect to parameter RO0004 of main controller block (note: lag 2 time constant not used in auxiliary controller).
  • BI0001 = CV is a maximum constraint (0=no / 1=yes).
  • BI0002 = CV is a minimum constraint (0=no / 1=yes).
  • BI0003 = connect to same parameter of main controller block.
  • BI0004 = connect to the following parameter of main controller block depending upon which DV input represents this MV in the main controller: BI0005 for DV1; BI0006 for DV2; BI0007 for DV3; BI0008 for DV4; BI0009 for DV5.
  • BI0005 = not used in auxiliary controller.
  • BI0006 = not used in auxiliary controller.
  • BI0007 = not used in auxiliary controller.
  • BI0008 = not used in auxiliary controller.
  • BI0009 = not used in auxiliary controller.
  • BI0012 = move suppression option (0 = cancel move suppression when on “unsafe” side of CV setpoint; 1 = use move suppression on both sides of CV setpoint).
  • BI0013 = control delay signal from DynaMPC scheduler block (1 = delay control execution for number of seconds entered in II0001).
  • BI0014 = connect to parameter BO0001 of main controller block.
  • BI0015 = MV decrease inhibit command (1=inhibit). If used, it must be connected to logic in another block.
  • BI0016 = MV increase inhibit command (1=inhibit). If used, it must be connected to logic in another block.
  • SN0002 = must be a null entry.
  • SN0003 = must be a null entry.
  • SN0004 = must be a null entry.
  • SN0005 = must be a null entry.
  • SN0006 = must be a null entry.
  • SN0007 = must be a null entry.

Tuning Parameters

  • RI0003 = CV deadband (normally connected to same parameter of main controller block).
  • RI0011 = MV ramp rate when increasing the MV (MV units per execution frequency). If MV is being ramped after constraint selection, then set to 99999.
  • RI0012 = MV ramp rate when decreasing the MV (MV units per execution frequency). If MV is being ramped after constraint selection, then set to 99999.
  • RI0013 = move suppression factor (FactMS term in equation 7). Must be between 0.0 and 1.0. An entry of 0.0 eliminates move suppression.
  • RI0014 = CV setpoint minimum limit (must be set to -99999 if CV setpoint RI0002 is a connection).
  • RI0015 = CV setpoint maximum limit (must be set to 99999 if CV setpoint RI0002 is a connection). If the minimum limit is set equal to or greater than the maximum, the CV setpoint is locked at the maximum.
  • II0001 = control delay time (sec) used in conjunction with control delay signal in BI0013.

Operator Parameters

  • RI0002 = CV setpoint (normally connected to same parameter of main controller block).

DynaMPC Scheduler Block

The DynaMPC scheduler block is a LOGIC block that accesses the control delay signals from up to 14 DynaMPC controllers in the same CP and outputs the control delay signal to each of those DynaMPC controllers. The logic performs an OR of the 14 inputs.

Output Parameters

  • BO01 = control delay signal to each block referenced in BI01 – BI14.

Configuration Parameters

  • PERIOD = 1 (0.5 sec execution frequency).
  • MA = lock into auto.
  • TIMINI = 1.
  • BI01 = control delay signal from a DynaMPC controller.
  • BI02 = control delay signal from a DynaMPC controller.
  • BI03 = control delay signal from a DynaMPC controller.
  • BI04 = control delay signal from a DynaMPC controller.
  • BI05 = control delay signal from a DynaMPC controller.
  • BI06 = control delay signal from a DynaMPC controller.
  • BI07 = control delay signal from a DynaMPC controller.
  • BI08 = control delay signal from a DynaMPC controller.
  • BI09 = control delay signal from a DynaMPC controller.
  • BI10 = control delay signal from a DynaMPC controller.
  • BI11 = control delay signal from a DynaMPC controller.
  • BI12 = control delay signal from a DynaMPC controller.
  • BI13 = control delay signal from a DynaMPC controller.
  • BI14 = control delay signal from a DynaMPC controller.

Analyzer Cycle Block

The analyzer cycle block is a CALCA block that detects a change in the analyzer input and alerts the DynaMPC main controller block using the input as its CV. The DynaMPC controller can then update the CV projection using the new sample from the analyzer. If the analyzer input appears to be frozen, an operator alarm can be generated and the DynaMPC model can be initialized. This block also gradually adjusts the control action execution of the DynaMPC main controller block to the time immediately following an analyzer update.

Output Parameters

  • RO01 = previous analyzer input signal (info only).
  • RO02 = analyzer cycle timer in seconds (info only).
  • RO03 = number of analyzer cycles without input change (info only).
  • BO01 = analyzer update trigger to DynaMPC controller parameter BI0017.
  • BO02 = sample ready indicator (info only).
  • BO03 = frozen input alarm (connect to Boolean alarm block if operator alarm is desired).
  • BO04 = bad input initialization flag (info only).
  • BO05 = control delay signal to DynaMPC controller parameter BI0013.

Configuration Parameters

  • PERIOD = 2 (1 sec execution frequency).
  • MA = lock into auto.
  • TIMINI = 3.
  • RI01 = analyzer input signal.
  • RI02 = DynaMPC controller setpoint (RI0002).
  • RI03 = DynaMPC controller deadband (RI0003).
  • RI04 = DynaMPC controller execution frequency (RI0005).
  • RI06 = analyzer cycle time (sec).
  • RI07 = number of analyzer cycles without input change at which the frozen input alarm is triggered.
  • RI08 = minimum analyzer input change that indicates a new sample (must be > 0.0).
  • BI01 = application on/off status from MV controller LR parameter (1=on).
  • BI02 = analyzer update acknowledge from DynaMPC controller.
  • M01 = control execution frequency factor (should be –0.5).

Analyzer Cycle Block Steps

STEP01 = RBD RI01 ;READ BAD INPUT BIT
STEP02 = BIT 38 ;BRANCH IF BAD INPUT
STEP03 = BII 30 ;BRANCH IF INIT
STEP04 = IN BO04 ;READ BAD INPUT INIT FLAG
STEP05 = BIT 30 ;BRANCH IF BAD INPUT INIT
STEP06 = SUB RI01 RO01 ;CURRENT – PREV INPUT
STEP07 = ABS
STEP08 = SUB RI08 ;SIG CHANGE BAND
STEP09 = BIP 26 ;BRANCH IF SIG CHANGE
STEP10 = INC RO02 ;INCREMENT CYCLE TIMER
STEP11 = SUB RO02 RI06 ;CYCLE TIMER – MAX TIME
STEP12 = BIN 28 ;BRANCH IF NOT AT MAX TIME
STEP13 = CLR RO02 ;RESET CYCLE TIMER
STEP14 = IN BI01 ;APPLICATION STATUS
STEP15 = OUT BO02 ;SAMPLE READY FLAG
STEP16 = BIF 33 ;BRANCH IF APPL OFF
STEP17 = SUB RI01 RI02 ;ANALYZER MEAS – SPT
STEP18 = ABS
STEP19 = SUB RI03 ;DEADBAND
STEP20 = BIN 39 ;BRANCH IF INSIDE DEADBAND
STEP21 = INC RO03 ;INCREMENT FROZEN VALUE TIMER
STEP22 = SUB RO03 RI07 ;MAX CYCLES WITHOUT CHANGE
STEP23 = BIN 39 ;BRANCH IF NOT YET FROZEN
STEP24 = SET BO03 ;FROZEN ANALYZER ALARM
STEP25 = GTO 39
STEP26 = SET BO02 ;SAMPLE READY FLAG
STEP27 = GTO 32
STEP28 = CLR BO02 ;SAMPLE READY FLAG
STEP29 = GTO 39
STEP30 = CLR BO01 ;SAMPLE READY TRIGGER
STEP31 = CLR BO04 ;CLEAR BAD INPUT INIT FLAG
STEP32 = CLR RO02 ;RESET CYCLE TIMER
STEP33 = CLR RO03 ;RESET FROZEN VALUE TIMER
STEP34 = CLR BO03 ;FROZEN ANALYZER ALARM
STEP35 = IN RI01 ;CURRENT INPUT
STEP36 = OUT RO01 ;PREV INPUT
STEP37 = GTO 39
STEP38 = SET BO04 ;BAD INPUT INIT FLAG
STEP39 = CST
STEP40 = IN BO02 ;MRS SET
STEP41 = IN BI02 ;MRS RESET
STEP42 = MRS
STEP43 = OUT BO01 ;SAMPLE READY TRIGGER
STEP44 = CLR BO05 ;CONTROL DELAY FLAG
STEP45 = SUB RO02 RI06 ;CYCLE TIMER – MAX TIME
STEP46 = MUL RI04 M01 ;CONTROLLER EXEC FREQ
STEP47 = ADD 2
STEP48 = BIN 50 ;BRANCH IF NOT NEAR CYCLE END
STEP49 = SET BO05 ;CONTROL DELAY FLAG
STEP50 = END

DYNAMPC HLBL SEQUENCE PROGRAM

INDEPENDENT_SEQUENCE{*****************************************************
** **
** Dynamic Model-Based Predictive Controller **
** By: J. R. Griffiths **
** Ver 1.1 Date: 02/15/2016 **
** **
***************************************************************}

CONSTANTS

execf = 1.0 ; {Wait time for one execution (sec)}
ntp = 30 ; {Number of time periods (tp) in dynamic model}

VARIABLES

mv_prev : R ; {MV previous value}
mv_t1prv : R ; {MV previous value of tau1}
mv_t2prv : R ; {MV previous value of tau2}
mv_fact : R ; {MV change times process gain}

dv1_meas : R ; {DV1 measurement from MAIN block}
dv1_gain : R ; {DV1 process gain from MAIN block}
dv1_dt : R ; {DV1 deadtime from MAIN block}
dv1_prev : R ; {DV1 previous value}
dv1_t1pv : R ; {DV1 previous value of tau1}
dv1_t2pv : R ; {DV1 previous value of tau2}
dv1_fact : R ; {DV1 change times process gain}

dv2_meas : R ; {DV2 measurement from MAIN block}
dv2_gain : R ; {DV2 process gain from MAIN block}
dv2_dt : R ; {DV2 deadtime from MAIN block}
dv2_prev : R ; {DV2 previous value}
dv2_t1pv : R ; {DV2 previous value of tau1}
dv2_t2pv : R ; {DV2 previous value of tau2}
dv2_fact : R ; {DV2 change times process gain}

dv3_meas : R ; {DV3 measurement from MAIN block}
dv3_gain : R ; {DV3 process gain from MAIN block}
dv3_dt : R ; {DV3 deadtime from MAIN block}
dv3_prev : R ; {DV3 previous value}
dv3_t1pv : R ; {DV3 previous value of tau1}
dv3_t2pv : R ; {DV3 previous value of tau2}
dv3_fact : R ; {DV3 change times process gain}

dv4_meas : R ; {DV4 measurement from MAIN block}
dv4_gain : R ; {DV4 process gain from MAIN block}
dv4_dt : R ; {DV4 deadtime from MAIN block}
dv4_prev : R ; {DV4 previous value}
dv4_t1pv : R ; {DV4 previous value of tau1}
dv4_t2pv : R ; {DV4 previous value of tau2}
dv4_fact : R ; {DV4 change times process gain}

dv5_meas : R ; {DV5 measurement from MAIN block}
dv5_gain : R ; {DV5 process gain from MAIN block}
dv5_dt : R ; {DV5 deadtime from MAIN block}
dv5_prev : R ; {DV5 previous value}
dv5_t1pv : R ; {DV5 previous value of tau1}
dv5_t2pv : R ; {DV5 previous value of tau2}
dv5_fact : R ; {DV5 change times process gain}

frac_tp : R ; {Control action freq in terms of fraction of tp}
onem_frac: R ; {1 – frac_tp}
ctl_dlyt : R ; {Wait time when other DynaMPC block is executing (sec)}
cv_proj0 : R ; {Projected CV at time 0 (now)}

cv_proj : R[30]; {Projected CV at end of each tp}
cv_chg : R[30]; {Projected CV change in each tp}
mv_resp : R[30]; {Fraction of MV ultimate response in each tp}
dv1_resp : R[30]; {Fraction of DV1 ultimate response in each tp}
dv2_resp : R[30]; {Fraction of DV2 ultimate response in each tp}
dv3_resp : R[30]; {Fraction of DV3 ultimate response in each tp}
dv4_resp : R[30]; {Fraction of DV4 ultimate response in each tp}
dv5_resp : R[30]; {Fraction of DV5 ultimate response in each tp}

i : I ; {Loop index}

pgm_init : B ; {Flag calling for model initialization}
ctl_indp : B ; {Prev status of control action indicator}

USER_LABELS

cv_meas : RI0001 ; {CV measurement input}
cv_spt : RI0002 ; {CV setpoint}
cv_dband: RI0003 ; {CV setpoint deadband}
tp_time : RI0004 ; {Length of time period (min)}
ctl_freq: RI0005 ; {Frequency of control action (negative seconds)}
mv_meas : RI0006 ; {MV measurement input}
mv_gain : RI0007 ; {MV process gain (CV units/MV unit)}
mv_dt : RI0008 ; {MV response deadtime (min)}
mv_tau1 : RI0009 ; {MV response lag1 time constant (min)}
mv_tau2 : RI0010 ; {MV response lag2 time constant (min)}
ramp_up : RI0011 ; {MV ramp-up rate}
ramp_dn : RI0012 ; {MV ramp-down rate}
move_sup: RI0013 ; {MV move suppression (0=none/1=total)}
cvsp_min: RI0014 ; {CV setpoint minimum limit}
cvsp_max: RI0015 ; {CV setpoint maximum limit}

cv_max : BI0001 ; {Is CV setpoint a maximum? (1=yes)}
cv_min : BI0002 ; {Is CV setpoint a minimum? (1=yes)}
mod_init: BI0003 ; {Model initialization signal (1=init)}
mv_init : BI0004 ; {MV initialization signal (1=init)}
dv1_init: BI0005 ; {DV1 initialization signal (1=init)}
dv2_init: BI0006 ; {DV2 initialization signal (1=init)}
dv3_init: BI0007 ; {DV3 initialization signal (1=init)}
dv4_init: BI0008 ; {DV4 initialization signal (1=init)}
dv5_init: BI0009 ; {DV5 initialization signal (1=init)}
ms_viol : BI0012 ; {Move supression when constraint violated?}
ctl_dlyi: BI0013 ; {Control action delay command}
ctl_indi: BI0014 ; {Control action ind (take action when changed)}
inh_decr: BI0015 ; {Inhibit MV decrease (1=inhibit)}
inh_incr: BI0016 ; {Inhibit MV increase (1=inhibit)}
cv_updti: BI0017 ; {CV update trigger indicating new sample from analyzer}

dly_time: II0001 ; {Wait time when other DynaMPC block is executing (sec)}
ctl_horz: II0002 ; {Control horizon (no. of lag times)}

mv_rsp : RO0001 ; {MV remote setpoint (ramp output)}
mv_calc : RO0002 ; {MV calculated value (before ramp)}
mv_del : RO0003 ; {MV change (ramp output)}
cv_horz : RO0004 ; {Projected CV at end of control horizon}
cv_targ : RO0005 ; {CV target value}

ctl_indo: BO0001 ; {Control action indicator output}
ctl_dlyo: BO0002 ; {Control action underway}
cv_updto: BO0003 ; {CV update trigger acknowledge}

res_id : SN0001 ; {NAME of block providing response coeffs (future)}
tim_id : SN0002 ; {NAME of associated TIM block}
dv1_id : SN0003 ; {NAME of MAIN block for DV1 dynamic data}
dv2_id : SN0004 ; {NAME of MAIN block for DV2 dynamic data}
dv3_id : SN0005 ; {NAME of MAIN block for DV3 dynamic data}
dv4_id : SN0006 ; {NAME of MAIN block for DV4 dynamic data}
dv5_id : SN0007 ; {NAME of MAIN block for DV5 dynamic data}

{*************************************************************************
* Subroutine exp_calc *
* *
* Performs EXP function for range -5.5 to 0.0 using Taylor Series *
* Needed because HLBL does not support EXP function. *
*************************************************************************}
SUBROUTINE exp_calc (IN exp_x : R
INOUT exp_r : R)

VARIABLES

exp_b : R ; {Taylor Series base value b}
x_b : R ; {Taylor Series x-b term}
x_b_2 : R ; {Taylor Series x-b term squared}
x_b_3 : R ; {Taylor Series x-b term cubed}

STATEMENTS

IF exp_x > -0.5 THEN exp_b := 1.000;
x_b := exp_x;
GOTO taylor_ser; ENDIF ;

IF exp_x > -1.5 THEN exp_b := 0.368;
x_b := exp_x + 1.0;
GOTO taylor_ser; ENDIF ;

IF exp_x > -2.5 THEN exp_b := 0.135;
x_b := exp_x + 2.0;
GOTO taylor_ser; ENDIF ;

IF exp_x > -3.5 THEN exp_b := 0.050;
x_b := exp_x + 3.0;
GOTO taylor_ser; ENDIF ;

IF exp_x > -4.5 THEN exp_b := 0.018;
x_b := exp_x + 4.0;
GOTO taylor_ser; ENDIF ;

IF exp_x > -5.5 THEN exp_b := 0.007;
x_b := exp_x + 5.0;

ELSE exp_b := 0.000;
x_b := exp_x + 5.0; ENDIF ;

<<taylor_ser>>
x_b_2 := x_b * x_b ;
x_b_3 := x_b * x_b_2 ;

exp_r := exp_b * (1.0 + x_b + x_b_2/2.0 + x_b_3/6.0) ;

ENDSUBROUTINE

{*************************************************************************
* Subroutine ini_resp *
* *
* Initializes values used in model. *
*************************************************************************}
SUBROUTINE ini_resp ()

STATEMENTS

{Initialize previous MV to current value}

mv_prev := mv_meas ;

{Set previous MV tau different from current value to force update}

mv_t1prv := mv_tau1 + 1.0 ;
mv_t2prv := mv_tau2 + 1.0 ;

{Perform same init functions for each DV}

IF dv1_id <> “” THEN dv1_prev := ::’dv1_id’.PNT_1 ;
dv1_t1pv := ::’dv1_id’.PNT_4 + 1.0 ;
dv1_t2pv := ::’dv1_id’.PNT_5 + 1.0 ;
ELSE dv1_meas := 0.0 ;
dv1_gain := 0.0 ;
dv1_dt := 0.0 ;
dv1_resp := SET_ARRAY (0.0) ; ENDIF ;

IF dv2_id <> “” THEN dv2_prev := ::’dv2_id’.PNT_1 ;
dv2_t1pv := ::’dv2_id’.PNT_4 + 1.0 ;
dv2_t2pv := ::’dv2_id’.PNT_5 + 1.0 ;
ELSE dv2_meas := 0.0 ;
dv2_gain := 0.0 ;
dv2_dt := 0.0 ;
dv2_resp := SET_ARRAY (0.0) ; ENDIF ;

IF dv3_id <> “” THEN dv3_prev := ::’dv3_id’.PNT_1 ;
dv3_t1pv := ::’dv3_id’.PNT_4 + 1.0 ;
dv3_t2pv := ::’dv3_id’.PNT_5 + 1.0 ;
ELSE dv3_meas := 0.0 ;
dv3_gain := 0.0 ;
dv3_dt := 0.0 ;
dv3_resp := SET_ARRAY (0.0) ; ENDIF ;

IF dv4_id <> “” THEN dv4_prev := ::’dv4_id’.PNT_1 ;
dv4_t1pv := ::’dv4_id’.PNT_4 + 1.0 ;
dv4_t2pv := ::’dv4_id’.PNT_5 + 1.0 ;
ELSE dv4_meas := 0.0 ;
dv4_gain := 0.0 ;
dv4_dt := 0.0 ;
dv4_resp := SET_ARRAY (0.0) ; ENDIF ;

IF dv5_id <> “” THEN dv5_prev := ::’dv5_id’.PNT_1 ;
dv5_t1pv := ::’dv5_id’.PNT_4 + 1.0 ;
dv5_t2pv := ::’dv5_id’.PNT_5 + 1.0 ;
ELSE dv5_meas := 0.0 ;
dv5_gain := 0.0 ;
dv5_dt := 0.0 ;
dv5_resp := SET_ARRAY (0.0) ; ENDIF ;

ENDSUBROUTINE

{*************************************************************************
* Subroutine get_resp *
* *
* Loads response curve for second-order lag into response array. *
*************************************************************************}
SUBROUTINE get_resp (IN tau1,tau2 : R
INOUT prv1,prv2 : R
INOUT resp_arr : R[30])

VARIABLES

exp_t1 : R ; {lag1 exponent in terms of time period}
exp_t2 : R ; {lag2 exponent in terms of time period}
exp_x : R ; {EXP x input}
exp_r1 : R ; {EXP result for lag1}
exp_r2 : R ; {EXP result for lag2}
tau1_m : R ; {Modified time constant for lag1}
tau2_m : R ; {Modified time constant for lag2}

STATEMENTS

{Bypass response array update if lag constants have not changed}

IF prv1 = tau1 AND prv2 = tau2 THEN GOTO sub_exit ; ENDIF ;
prv1 := tau1 ;
prv2 := tau2 ;

{Limit tau1 to resonable entries}

IF tau1 < 0.01 THEN tau1_m := 0.01 ;
ELSE tau1_m := tau1 ; ENDIF ;

exp_t1 := -tp_time / tau1_m ;

{Limit tau2 to resonable entries}

IF tau2 < 0.01 THEN tau2_m := 0.01 ;
ELSEIF ABS(tau1 – tau2) < 0.01 THEN tau2_m := tau1 – 0.01 ;
ELSE tau2_m := tau2 ; ENDIF ;

exp_t2 := -tp_time / tau2_m ;

FOR i := 1 TO ntp DO

exp_x := i * exp_t1 ;
CALL exp_calc (exp_x, exp_r1) ;

exp_x := i * exp_t2 ;
CALL exp_calc (exp_x, exp_r2) ;

resp_arr[i] := 1.0 – ((tau1_m*exp_r1 – tau2_m*exp_r2)/(tau1_m-tau2_m)) ;

ENDFOR ;

<<sub_exit>> ;
ENDSUBROUTINE

{*************************************************************************
* Subroutine upd_resp *
* *
* Updates first-order lag response curve for MV and each DV. *
*************************************************************************}
SUBROUTINE upd_resp ()

VARIABLES

dv_tau1 : R ; {Lag1 time constant for second-order response}
dv_tau2 : R ; {Lag2 time constant for second-order response}

STATEMENTS

{Update response data for MV}

IF tim_id <> “” THEN
CALL get_resp (mv_tau1, mv_tau2, mv_t1prv, mv_t2prv, mv_resp) ;
ENDIF ;

{Update response data for DVs}

IF dv1_id <> “” THEN dv_tau1 := ::’dv1_id’.PNT_4 ;
dv_tau2 := ::’dv1_id’.PNT_5 ;
CALL get_resp (dv_tau1, dv_tau2, dv1_t1pv, dv1_t2pv, dv1_resp) ;
ENDIF ;

IF dv2_id <> “” THEN dv_tau1 := ::’dv2_id’.PNT_4 ;
dv_tau2 := ::’dv2_id’.PNT_5 ;
CALL get_resp (dv_tau1, dv_tau2, dv2_t1pv, dv2_t2pv, dv2_resp) ;
ENDIF ;

IF dv3_id <> “” THEN dv_tau1 := ::’dv3_id’.PNT_4 ;
dv_tau2 := ::’dv3_id’.PNT_5 ;
CALL get_resp (dv_tau1, dv_tau2, dv3_t1pv, dv3_t2pv, dv3_resp) ;
ENDIF ;

IF dv4_id <> “” THEN dv_tau1 := ::’dv4_id’.PNT_4 ;
dv_tau2 := ::’dv4_id’.PNT_5 ;
CALL get_resp (dv_tau1, dv_tau2, dv4_t1pv, dv4_t2pv, dv4_resp) ;
ENDIF ;

IF dv5_id <> “” THEN dv_tau1 := ::’dv5_id’.PNT_4 ;
dv_tau2 := ::’dv5_id’.PNT_5 ;
CALL get_resp (dv_tau1, dv_tau2, dv5_t1pv, dv5_t2pv, dv5_resp) ;
ENDIF ;

ENDSUBROUTINE

{*************************************************************************
* Subroutine init_var *
* *
* Initializes values used in model. *
*************************************************************************}
SUBROUTINE init_var ()

STATEMENTS

{Initialize previous MV to current value}

IF mv_init OR pgm_init THEN mv_prev := mv_meas ; ENDIF ;

{Perform same init function for each DV}

IF (dv1_init OR pgm_init) AND dv1_id <> “” THEN
dv1_prev := ::’dv1_id’.PNT_1 ; ENDIF ;

IF (dv2_init OR pgm_init) AND dv2_id <> “” THEN
dv2_prev := ::’dv2_id’.PNT_1 ; ENDIF ;

IF (dv3_init OR pgm_init) AND dv3_id <> “” THEN
dv3_prev := ::’dv3_id’.PNT_1 ; ENDIF ;

IF (dv4_init OR pgm_init) AND dv4_id <> “” THEN
dv4_prev := ::’dv4_id’.PNT_1 ; ENDIF ;

IF (dv5_init OR pgm_init) AND dv5_id <> “” THEN
dv5_prev := ::’dv5_id’.PNT_1 ; ENDIF ;

ENDSUBROUTINE

{*************************************************************************
* Subroutine get_targ *
* *
* Determines actual CV target based upon deadband and move suppression. *
*************************************************************************}
SUBROUTINE get_targ ()

VARIABLES

db_high : R ; {Upper boundary of CV deadband}
db_low : R ; {Lower boundary of CV deadband}
move_tgt : R ; {Move suppresion target for CV}
proj_hor : I ; {Time period at end of control horizon}

STATEMENTS

{Determine CV value at end of control horizon}
{Note: Horizon comes from main DynaMPC block via mv_tau2 if this is aux block}

IF tim_id = “” THEN cv_horz := mv_tau2 ;
GOTO move_supress ; ENDIF ;

proj_hor := ROUND ((mv_dt + ctl_horz*(mv_tau1+mv_tau2)) / tp_time) + 1 ;
IF proj_hor > ntp THEN proj_hor := ntp ; ENDIF ;
cv_horz := cv_proj[proj_hor] ;

{Calculate move supression target}

<<move_supress>>
move_tgt := cv_spt + move_sup * (cv_meas – cv_spt);

{Determine high/low boundaries of control deadband}

IF cv_max THEN GOTO max_cnstr ; ENDIF ;
IF cv_min THEN GOTO min_cnstr ; ENDIF ;

db_high := cv_spt + cv_dband/2 ;
db_low := cv_spt – cv_dband/2 ;
IF move_tgt > db_high THEN db_high := move_tgt ; ENDIF ;
IF move_tgt < db_low THEN db_low := move_tgt ; ENDIF ;
GOTO targ_set ;

<<min_cnstr>>
db_low := cv_spt ;
db_high := cv_spt + cv_dband ;
IF move_tgt > db_high THEN db_high := move_tgt ; ENDIF ;
IF NOT ms_viol THEN GOTO targ_set ; ENDIF ;
IF move_tgt < db_low THEN db_low := move_tgt ; ENDIF ;
GOTO targ_set ;

<<max_cnstr>>
db_high := cv_spt ;
db_low := cv_spt – cv_dband ;
IF move_tgt < db_low THEN db_low := move_tgt ; ENDIF ;
IF NOT ms_viol THEN GOTO targ_set ; ENDIF ;
IF move_tgt > db_high THEN db_high := move_tgt ; ENDIF ;

<<targ_set>>
IF cv_horz > db_high THEN cv_targ := db_high ;
ELSEIF cv_horz < db_low THEN cv_targ := db_low ;
ELSE cv_targ := cv_horz ; ENDIF ;

ENDSUBROUTINE

{*************************************************************************
* Subroutine init_mod *
* *
* Initializes values used in model. *
*************************************************************************}
SUBROUTINE init_mod ()

STATEMENTS

{Reset Timer}

IF tim_id <> “” THEN START_TIMER(::’tim_id’.TIMR1, ctl_freq); ENDIF;

{Initialize CV projection to current CV measurement}
{Zero CV change array}

cv_proj0 := cv_meas ;
cv_proj := SET_ARRAY (cv_meas) ;
cv_chg := SET_ARRAY (0.0) ;

{Set input initialization flags}

pgm_init := TRUE ;
CALL init_var () ;
pgm_init := FALSE ;

CALL get_targ () ;

mv_del := 0.0 ;
mv_calc := mv_meas ;
mv_rsp := mv_meas ;

ENDSUBROUTINE

{*************************************************************************
* Subroutine get_data *
* *
* Get response data for a variable in a given tp. *
*************************************************************************}
SUBROUTINE get_data (IN resp_arr : R[30]
IN d_time : R
IN tp : I
INOUT resp_dat : R)

VARIABLES

dt_tp : I ; {Time period at end of response deadtime}

STATEMENTS

dt_tp := ROUND (d_time / tp_time) ;

IF tp > dt_tp THEN resp_dat := resp_arr[tp – dt_tp] ;
ELSE resp_dat := 0.0 ; ENDIF ;

ENDSUBROUTINE

{*************************************************************************
* Subroutine proj_cv *
* *
* Project CV response for each tp. *
************************************************************************}
SUBROUTINE proj_cv ()

VARIABLES

resp_prv : R ; {Total CV response in previous time period}
resp_cur : R ; {MV or DV response in current time period}
cv_resp : R ; {Total CV response in current time period}
var_del : R ; {Change in CV response from prev tp}
nxt_tp : R ; {CV change stored in array for next tp}
prv_tp : R ; {CV projection in previous tp}

STATEMENTS

var_del := mv_meas – mv_prev ;
mv_prev := mv_meas ;
mv_fact := mv_gain * var_del ;

IF dv1_id <> “” THEN dv1_meas := ::’dv1_id’.PNT_1 ;
dv1_gain := ::’dv1_id’.PNT_2 ;
dv1_dt := ::’dv1_id’.PNT_3 ; ENDIF ;

var_del := dv1_meas – dv1_prev ;
dv1_prev := dv1_meas ;
dv1_fact := dv1_gain * var_del ;

IF dv2_id <> “” THEN dv2_meas := ::’dv2_id’.PNT_1 ;
dv2_gain := ::’dv2_id’.PNT_2 ;
dv2_dt := ::’dv2_id’.PNT_3 ; ENDIF ;

var_del := dv2_meas – dv2_prev ;
dv2_prev := dv2_meas ;
dv2_fact := dv2_gain * var_del ;

IF dv3_id <> “” THEN dv3_meas := ::’dv3_id’.PNT_1 ;
dv3_gain := ::’dv3_id’.PNT_2 ;
dv3_dt := ::’dv3_id’.PNT_3 ; ENDIF ;

var_del := dv3_meas – dv3_prev ;
dv3_prev := dv3_meas ;
dv3_fact := dv3_gain * var_del ;

IF dv4_id <> “” THEN dv4_meas := ::’dv4_id’.PNT_1 ;
dv4_gain := ::’dv4_id’.PNT_2 ;
dv4_dt := ::’dv4_id’.PNT_3 ; ENDIF ;

var_del := dv4_meas – dv4_prev ;
dv4_prev := dv4_meas ;
dv4_fact := dv4_gain * var_del ;

IF dv5_id <> “” THEN dv5_meas := ::’dv5_id’.PNT_1 ;
dv5_gain := ::’dv5_id’.PNT_2 ;
dv5_dt := ::’dv5_id’.PNT_3 ; ENDIF ;

var_del := dv5_meas – dv5_prev ;
dv5_prev := dv5_meas ;
dv5_fact := dv5_gain * var_del ;

resp_prv := 0.0 ;

IF tim_id = “” THEN GOTO sub_end ; ENDIF ;

{Use current CV for time period 0 if analyzer has updated}
{Otherwise, use projected CV from previous execution}

IF cv_updti THEN cv_proj0 := cv_meas ;
cv_updto := TRUE ;
WAIT execf ;
cv_updto := FALSE ;
ELSE cv_proj0 := onem_frac*cv_meas + frac_tp*cv_proj[1] ;
ENDIF ;

{Loop thru time periods and update CV projection}

FOR i := 1 TO ntp DO

CALL get_data (mv_resp, mv_dt, i, resp_cur) ;
cv_resp := mv_fact * resp_cur ;

CALL get_data (dv1_resp, dv1_dt, i, resp_cur) ;
cv_resp := dv1_fact * resp_cur + cv_resp ;

CALL get_data (dv2_resp, dv2_dt, i, resp_cur) ;
cv_resp := dv2_fact * resp_cur + cv_resp ;

CALL get_data (dv3_resp, dv3_dt, i, resp_cur) ;
cv_resp := dv3_fact * resp_cur + cv_resp ;

CALL get_data (dv4_resp, dv4_dt, i, resp_cur) ;
cv_resp := dv4_fact * resp_cur + cv_resp ;

CALL get_data (dv5_resp, dv5_dt, i, resp_cur) ;
cv_resp := dv5_fact * resp_cur + cv_resp ;

var_del := cv_resp – resp_prv ;
resp_prv := cv_resp ;

IF i < ntp THEN nxt_tp := cv_chg[i+1] ;
ELSE nxt_tp := 0.0 ; ENDIF ;

cv_chg[i] := var_del + onem_frac * cv_chg[i] + frac_tp * nxt_tp ;

IF i > 1 THEN prv_tp := cv_proj[i-1] ;
ELSE prv_tp := cv_proj0 ; ENDIF ;

cv_proj[i] := cv_chg[i] + prv_tp ;

ENDFOR ;

<<sub_end>> ;
ENDSUBROUTINE

{*************************************************************************
* Subroutine ctl_actn *
* *
* Determine MV move required to meet CV target. *
************************************************************************}
SUBROUTINE ctl_actn ()

STATEMENTS

IF mv_gain = 0.0 THEN mv_del := 0.0 ;
ELSE mv_del := (cv_targ – cv_horz) / mv_gain ; ENDIF ;

IF (mv_del > 0.0 AND inh_incr) OR
(mv_del < 0.0 AND inh_decr) THEN mv_del := 0.0 ; ENDIF ;

mv_calc := mv_meas + mv_del ;

IF mv_del > 0.0 AND mv_del > ramp_up THEN
mv_del := ramp_up ; ENDIF ;

IF mv_del < 0.0 AND ABS(mv_del) > ramp_dn THEN
mv_del := -ramp_dn ; ENDIF ;

mv_rsp := mv_meas + mv_del ;

ENDSUBROUTINE

{*************************************************************************
* Subroutine disp_res *
* *
* Store CV projection into external variables for monitoring. *
*************************************************************************}
SUBROUTINE disp_res ()

STATEMENTS

RO0006 := mv_fact + dv1_fact + dv2_fact + dv3_fact + dv4_fact
+ dv5_fact ;
RO0007 := mv_fact ;
RO0008 := dv1_fact ;
RO0009 := dv2_fact ;
RO0010 := dv3_fact ;
RO0011 := dv4_fact ;
RO0012 := dv5_fact ;
RO0013 := mv_calc – mv_meas ;
RO0014 := cv_proj0 ;
RO0015 := cv_proj[1] ;

ENDSUBROUTINE

{*************************************************************************
* Main Program *
*************************************************************************}

STATEMENTS

{Initialize program whenever this block is reloaded}

IF tim_id <> “” THEN START_TIMER(::’tim_id’.TIMR1, ctl_freq); ENDIF;
ctl_indp := ctl_indi ;
ctl_dlyo := FALSE ;
cv_updto := FALSE ;

CALL ini_resp () ;

frac_tp := ctl_freq / (-60 * tp_time) ;
onem_frac := 1.0 – frac_tp ;

{Limit CV setpoint to max/min}

IF cv_spt < cvsp_min THEN cv_spt := cvsp_min ; ENDIF ;
IF cv_spt > cvsp_max THEN cv_spt := cvsp_max ; ENDIF ;

{Initialize model}

CALL init_mod () ;

{————————————————————————-
Perform Model}

{Wait for timer expiration}

<<wait_timer>>
CALL init_var () ;
CALL upd_resp () ;

{Limit CV setpoint to max/min}

IF cv_spt < cvsp_min THEN cv_spt := cvsp_min ; ENDIF ;
IF cv_spt > cvsp_max THEN cv_spt := cvsp_max ; ENDIF ;

{Initialize model if commanded}

IF mod_init THEN CALL init_mod () ;
CALL disp_res () ; ENDIF ;

IF tim_id = “” THEN GOTO timer_byp ; ENDIF ;

IF ::’tim_id’.POS_V1 THEN GOTO cal_resp ; ENDIF ;
WAIT execf ;
GOTO wait_timer ;

<<timer_byp>>
IF ctl_indi <> ctl_indp THEN GOTO cal_resp ; ENDIF ;
WAIT execf ;
GOTO wait_timer ;

{Restart timer}

<<cal_resp>>
IF ctl_dlyi THEN ctl_dlyt := dly_time ;
WAIT ctl_dlyt ; ENDIF ;
ctl_dlyo := TRUE ;

IF tim_id <> “” THEN START_TIMER(::’tim_id’.TIMR1, ctl_freq); ENDIF;
ctl_indp := ctl_indi ;

CALL proj_cv () ;

{————————————————————————-
Control Algorithm}

CALL get_targ () ;

CALL ctl_actn () ;

CALL disp_res () ;

ctl_dlyo := FALSE ;

WAIT execf ;
IF ctl_indo THEN ctl_indo := FALSE ;
ELSE ctl_indo := TRUE ; ENDIF ;

WAIT execf ;

GOTO wait_timer ;

ENDSEQUENCE