diff --git a/Buildings/Controls/OBC/CDL/Continuous/Divide.mo b/Buildings/Controls/OBC/CDL/Continuous/Divide.mo index 2cb7a2f5578..1165ee65155 100644 --- a/Buildings/Controls/OBC/CDL/Continuous/Divide.mo +++ b/Buildings/Controls/OBC/CDL/Continuous/Divide.mo @@ -76,10 +76,6 @@ Modelica Standard Library. Ellipse( fillPattern=FillPattern.Solid, extent={{-5,-30},{5,-20}}), - Text( - textColor={0,0,255}, - extent={{-150,110},{150,150}}, - textString="%name"), Line( points={{-100,60},{-66,60},{-40,30}}, color={0,0,127}), diff --git a/Buildings/Controls/OBC/CDL/Continuous/PID.mo b/Buildings/Controls/OBC/CDL/Continuous/PID.mo index 41bd1e82446..e647c34f761 100644 --- a/Buildings/Controls/OBC/CDL/Continuous/PID.mo +++ b/Buildings/Controls/OBC/CDL/Continuous/PID.mo @@ -54,7 +54,7 @@ block PID "Connector of actuator output signal" annotation (Placement(transformation(extent={{220,-20},{260,20}}),iconTransformation(extent={{100,-20},{140,20}}))); Buildings.Controls.OBC.CDL.Continuous.Subtract controlError "Control error (set point - measurement)" - annotation (Placement(transformation(extent={{-200,-10},{-180,10}}))); + annotation (Placement(transformation(extent={{-200,-16},{-180,4}}))); Buildings.Controls.OBC.CDL.Continuous.MultiplyByParameter P(final k=k) "Gain for proportional control action" annotation (Placement(transformation(extent={{-50,130},{-30,150}}))); @@ -75,10 +75,10 @@ block PID annotation (Placement(transformation(extent={{-140,60},{-120,80}}))); Buildings.Controls.OBC.CDL.Continuous.Subtract errI1 if with_I "I error (before anti-windup compensation)" - annotation (Placement(transformation(extent={{-140,-10},{-120,10}}))); + annotation (Placement(transformation(extent={{-140,-4},{-120,16}}))); Buildings.Controls.OBC.CDL.Continuous.Subtract errI2 if with_I "I error (after anti-windup compensation)" - annotation (Placement(transformation(extent={{-90,-10},{-70,10}}))); + annotation (Placement(transformation(extent={{-100,-10},{-80,10}}))); Buildings.Controls.OBC.CDL.Continuous.Limiter lim( final uMax=yMax, final uMin=yMin) @@ -107,16 +107,17 @@ protected Buildings.Controls.OBC.CDL.Continuous.Sources.Constant Dzero( final k=0) if not with_D "Zero input signal" - annotation (Evaluate=true,HideResult=true,Placement(transformation(extent={{-20,110},{0,130}}))); + annotation (Evaluate=true,HideResult=true,Placement(transformation(extent={{-50,90}, + {-30,110}}))); Buildings.Controls.OBC.CDL.Continuous.MultiplyByParameter uS_revAct( final k=revAct/r) "Set point multiplied by reverse action sign" annotation (Placement(transformation(extent={{-200,30},{-180,50}}))); Buildings.Controls.OBC.CDL.Continuous.MultiplyByParameter uMea_revAct( final k=revAct/r) "Set point multiplied by reverse action sign" - annotation (Placement(transformation(extent={{-180,-50},{-160,-30}}))); + annotation (Placement(transformation(extent={{-200,-50},{-180,-30}}))); Buildings.Controls.OBC.CDL.Continuous.Add addPD "Outputs P and D gains added" - annotation (Placement(transformation(extent={{20,116},{40,136}}))); + annotation (Placement(transformation(extent={{20,124},{40,144}}))); Buildings.Controls.OBC.CDL.Continuous.Add addPID "Outputs P, I and D gains added" annotation (Placement(transformation(extent={{80,80},{100,100}}))); @@ -138,7 +139,7 @@ protected Buildings.Controls.OBC.CDL.Continuous.Sources.Constant Izero( final k=0) if not with_I "Zero input signal" - annotation (Placement(transformation(extent={{40,74},{60,94}}))); + annotation (Placement(transformation(extent={{-50,20},{-30,40}}))); Buildings.Controls.OBC.CDL.Continuous.Sources.Constant con( final k=0) if with_I "Constant zero" @@ -150,37 +151,40 @@ protected equation connect(u_s,uS_revAct.u) - annotation (Line(points={{-240,0},{-212,0},{-212,40},{-202,40}},color={0,0,127})); + annotation (Line(points={{-240,0},{-210,0},{-210,42},{-206,42},{-206,40},{ + -202,40}}, color={0,0,127})); connect(u_m,uMea_revAct.u) - annotation (Line(points={{0,-220},{0,-160},{-190,-160},{-190,-40},{-182,-40}},color={0,0,127})); + annotation (Line(points={{0,-220},{0,-160},{-210,-160},{-210,-40},{-202,-40}},color={0,0,127})); connect(D.u,errD.y) annotation (Line(points={{-52,70},{-118,70}}, color={0,0,127})); connect(errI1.u1,uS_revAct.y) - annotation (Line(points={{-142,6},{-170,6},{-170,40},{-178,40}},color={0,0,127})); + annotation (Line(points={{-142,12},{-170,12},{-170,40},{-178,40}}, + color={0,0,127})); connect(addPID.u1,addPD.y) - annotation (Line(points={{78,96},{70,96},{70,126},{42,126}},color={0,0,127})); + annotation (Line(points={{78,96},{50,96},{50,134},{42,134}},color={0,0,127})); connect(lim.y,y) annotation (Line(points={{142,90},{200,90},{200,0},{240,0}},color={0,0,127})); connect(antWinErr.y,antWinGai.u) annotation (Line(points={{182,60},{190,60},{190,-20},{182,-20}},color={0,0,127})); connect(addPD.u2,Dzero.y) - annotation (Line(points={{18,120},{2,120}}, color={0,0,127})); + annotation (Line(points={{18,128},{-10,128},{-10,100},{-28,100}},color={0,0,127})); connect(D.y,addPD.u2) - annotation (Line(points={{-28,70},{10,70},{10,120},{18,120}}, color={0,0,127})); + annotation (Line(points={{-28,70},{-10,70},{-10,128},{18,128}},color={0,0,127})); connect(addPID.u2,I.y) - annotation (Line(points={{78,84},{72,84},{72,0},{-28,0}},color={0,0,127})); + annotation (Line(points={{78,84},{60,84},{60,0},{-28,0}},color={0,0,127})); connect(antWinErr.u2,lim.y) annotation (Line(points={{158,54},{150,54},{150,90},{142,90}}, color={0,0,127})); connect(I.u,errI2.y) - annotation (Line(points={{-52,0},{-68,0}},color={0,0,127})); + annotation (Line(points={{-52,0},{-78,0}},color={0,0,127})); connect(errI1.y,errI2.u1) - annotation (Line(points={{-118,0},{-100,0},{-100,6},{-92,6}}, + annotation (Line(points={{-118,6},{-102,6}}, color={0,0,127})); connect(cheYMinMax.y,assMesYMinMax.u) annotation (Line(points={{142,-150},{158,-150}},color={255,0,255})); connect(Izero.y,addPID.u2) - annotation (Line(points={{62,84},{78,84}}, color={0,0,127})); + annotation (Line(points={{-28,30},{60,30},{60,84},{78,84}}, + color={0,0,127})); connect(con.y,I.y_reset_in) annotation (Line(points={{-78,-40},{-60,-40},{-60,-8},{-52,-8}},color={0,0,127})); connect(con1.y,I.trigger) @@ -190,27 +194,27 @@ equation connect(errD.u1,uS_revAct.y) annotation (Line(points={{-142,76},{-170,76},{-170,40},{-178,40}},color={0,0,127})); connect(addPD.u1, P.y) - annotation (Line(points={{18,132},{10,132},{10,140},{-28,140}}, - color={0,0,127})); + annotation (Line(points={{18,140},{-28,140}}, color={0,0,127})); connect(P.u, errP.y) annotation (Line(points={{-52,140},{-118,140}},color={0,0,127})); connect(addPID.y, lim.u) annotation (Line(points={{102,90},{118,90}},color={0,0,127})); - connect(addPID.y, antWinErr.u1) annotation (Line(points={{102,90},{110,90},{ - 110,66},{158,66}}, + connect(addPID.y, antWinErr.u1) annotation (Line(points={{102,90},{114,90},{ + 114,66},{158,66}}, color={0,0,127})); - connect(u_s, controlError.u1) annotation (Line(points={{-240,0},{-212,0},{ - -212,6},{-202,6}}, color={0,0,127})); + connect(u_s, controlError.u1) annotation (Line(points={{-240,0},{-202,0}}, + color={0,0,127})); connect(u_m, controlError.u2) annotation (Line(points={{0,-220},{0,-160},{ - -212,-160},{-212,-6},{-202,-6}}, color={0,0,127})); - connect(uMea_revAct.y, errP.u2) annotation (Line(points={{-158,-40},{-150,-40}, + -210,-160},{-210,-12},{-202,-12}}, + color={0,0,127})); + connect(uMea_revAct.y, errP.u2) annotation (Line(points={{-178,-40},{-150,-40}, {-150,134},{-142,134}}, color={0,0,127})); - connect(uMea_revAct.y, errD.u2) annotation (Line(points={{-158,-40},{-150,-40}, + connect(uMea_revAct.y, errD.u2) annotation (Line(points={{-178,-40},{-150,-40}, {-150,64},{-142,64}}, color={0,0,127})); - connect(uMea_revAct.y, errI1.u2) annotation (Line(points={{-158,-40},{-150, - -40},{-150,-6},{-142,-6}}, color={0,0,127})); - connect(antWinGai.y, errI2.u2) annotation (Line(points={{158,-20},{-100,-20}, - {-100,-6},{-92,-6}}, color={0,0,127})); + connect(uMea_revAct.y, errI1.u2) annotation (Line(points={{-178,-40},{-150, + -40},{-150,0},{-142,0}}, color={0,0,127})); + connect(antWinGai.y, errI2.u2) annotation (Line(points={{158,-20},{-110,-20}, + {-110,-6},{-102,-6}},color={0,0,127})); connect(kDer.y, D.k) annotation (Line(points={{-78,120},{-58,120},{-58,78},{ -52,78}}, color={0,0,127})); connect(TDer.y, D.T) annotation (Line(points={{-78,90},{-60,90},{-60,74},{-52, diff --git a/Buildings/Controls/OBC/CDL/Continuous/PIDWithReset.mo b/Buildings/Controls/OBC/CDL/Continuous/PIDWithReset.mo index 7cb8d02a2ca..f1852d4ab4d 100644 --- a/Buildings/Controls/OBC/CDL/Continuous/PIDWithReset.mo +++ b/Buildings/Controls/OBC/CDL/Continuous/PIDWithReset.mo @@ -61,7 +61,7 @@ block PIDWithReset annotation (Placement(transformation(extent={{-20,-20},{20,20}},rotation=90,origin={-160,-220}),iconTransformation(extent={{-20,-20},{20,20}},rotation=90,origin={-60,-120}))); Buildings.Controls.OBC.CDL.Continuous.Subtract controlError "Control error (set point - measurement)" - annotation (Placement(transformation(extent={{-200,-10},{-180,10}}))); + annotation (Placement(transformation(extent={{-200,-16},{-180,4}}))); Buildings.Controls.OBC.CDL.Continuous.MultiplyByParameter P(final k=k) "Proportional action" annotation (Placement(transformation(extent={{-50,130},{-30,150}}))); Buildings.Controls.OBC.CDL.Continuous.IntegratorWithReset I( @@ -81,10 +81,10 @@ block PIDWithReset annotation (Placement(transformation(extent={{-140,60},{-120,80}}))); Buildings.Controls.OBC.CDL.Continuous.Subtract errI1 if with_I "I error (before anti-windup compensation)" - annotation (Placement(transformation(extent={{-140,-10},{-120,10}}))); + annotation (Placement(transformation(extent={{-140,-4},{-120,16}}))); Buildings.Controls.OBC.CDL.Continuous.Subtract errI2 if with_I "I error (after anti-windup compensation)" - annotation (Placement(transformation(extent={{-90,-10},{-70,10}}))); + annotation (Placement(transformation(extent={{-100,-10},{-80,10}}))); Buildings.Controls.OBC.CDL.Continuous.Limiter lim( final uMax=yMax, final uMin=yMin) @@ -112,12 +112,12 @@ protected Buildings.Controls.OBC.CDL.Continuous.Sources.Constant Dzero( final k=0) if not with_D "Zero input signal" - annotation (Evaluate=true,HideResult=true,Placement(transformation(extent={{-20,110}, - {0,130}}))); + annotation (Evaluate=true,HideResult=true,Placement(transformation(extent={{-50,90}, + {-30,110}}))); Buildings.Controls.OBC.CDL.Continuous.Sources.Constant Izero( final k=0) if not with_I "Zero input signal" - annotation (Placement(transformation(extent={{20,74},{40,94}}))); + annotation (Placement(transformation(extent={{-50,20},{-30,40}}))); Buildings.Controls.OBC.CDL.Continuous.MultiplyByParameter uS_revAct( final k=revAct/r) "Set point multiplied by reverse action sign" @@ -125,16 +125,16 @@ protected Buildings.Controls.OBC.CDL.Continuous.MultiplyByParameter uMea_revAct( final k=revAct/r) "Set point multiplied by reverse action sign" - annotation (Placement(transformation(extent={{-180,-50},{-160,-30}}))); + annotation (Placement(transformation(extent={{-200,-50},{-180,-30}}))); Buildings.Controls.OBC.CDL.Continuous.Add addPD "Outputs P and D gains added" - annotation (Placement(transformation(extent={{20,116},{40,136}}))); + annotation (Placement(transformation(extent={{20,124},{40,144}}))); Buildings.Controls.OBC.CDL.Continuous.Add addPID "Outputs P, I and D gains added" annotation (Placement(transformation(extent={{80,80},{100,100}}))); Buildings.Controls.OBC.CDL.Continuous.Subtract antWinErr if with_I "Error for anti-windup compensation" - annotation (Placement(transformation(extent={{162,50},{182,70}}))); + annotation (Placement(transformation(extent={{160,50},{180,70}}))); Buildings.Controls.OBC.CDL.Continuous.MultiplyByParameter antWinGai( k=1/(k*Ni)) if with_I "Gain for anti-windup compensation" @@ -142,7 +142,7 @@ protected Buildings.Controls.OBC.CDL.Continuous.Sources.Constant yResSig( final k=y_reset) if with_I "Signal for y_reset" - annotation (Placement(transformation(extent={{-140,-90},{-120,-70}}))); + annotation (Placement(transformation(extent={{-140,-84},{-120,-64}}))); Buildings.Controls.OBC.CDL.Continuous.Subtract addRes if with_I "Adder for integrator reset" annotation (Placement(transformation(extent={{-100,-90},{-80,-70}}))); @@ -159,65 +159,72 @@ equation connect(trigger,I.trigger) annotation (Line(points={{-160,-220},{-160,-140},{-40,-140},{-40,-12}},color={255,0,255})); connect(u_s,uS_revAct.u) - annotation (Line(points={{-240,0},{-212,0},{-212,40},{-202,40}},color={0,0,127})); + annotation (Line(points={{-240,0},{-210,0},{-210,40},{-202,40}},color={0,0,127})); connect(u_m,uMea_revAct.u) - annotation (Line(points={{0,-220},{0,-160},{-210,-160},{-210,-40},{-182,-40}},color={0,0,127})); + annotation (Line(points={{0,-220},{0,-160},{-210,-160},{-210,-40},{-202,-40}},color={0,0,127})); connect(errD.u2,uMea_revAct.y) - annotation (Line(points={{-142,64},{-150,64},{-150,-40},{-158,-40}}, color={0,0,127})); + annotation (Line(points={{-142,64},{-150,64},{-150,-40},{-178,-40}}, color={0,0,127})); connect(D.u,errD.y) annotation (Line(points={{-52,70},{-118,70}}, color={0,0,127})); connect(errI1.u1,uS_revAct.y) - annotation (Line(points={{-142,6},{-170,6},{-170,40},{-178,40}},color={0,0,127})); + annotation (Line(points={{-142,12},{-170,12},{-170,40},{-178,40}}, + color={0,0,127})); connect(addPID.u1,addPD.y) - annotation (Line(points={{78,96},{60,96},{60,126},{42,126}},color={0,0,127})); + annotation (Line(points={{78,96},{50,96},{50,134},{42,134}},color={0,0,127})); connect(lim.y,y) annotation (Line(points={{142,90},{200,90},{200,0},{240,0}},color={0,0,127})); connect(antWinErr.y,antWinGai.u) - annotation (Line(points={{184,60},{190,60},{190,-20},{182,-20}},color={0,0,127})); + annotation (Line(points={{182,60},{190,60},{190,-20},{182,-20}},color={0,0,127})); connect(addPD.u2,Dzero.y) - annotation (Line(points={{18,120},{2,120}}, color={0,0,127})); + annotation (Line(points={{18,128},{-10,128},{-10,100},{-28,100}}, + color={0,0,127})); connect(D.y,addPD.u2) - annotation (Line(points={{-28,70},{10,70},{10,120},{18,120}}, color={0,0,127})); + annotation (Line(points={{-28,70},{-10,70},{-10,128},{18,128}},color={0,0,127})); connect(addPID.u2,I.y) - annotation (Line(points={{78,84},{68,84},{68,0},{-28,0}},color={0,0,127})); + annotation (Line(points={{78,84},{60,84},{60,0},{-28,0}},color={0,0,127})); connect(addRes.y,I.y_reset_in) annotation (Line(points={{-78,-80},{-60,-80},{-60,-8},{-52,-8}},color={0,0,127})); connect(antWinErr.u2,lim.y) - annotation (Line(points={{160,54},{150,54},{150,90},{142,90}}, color={0,0,127})); + annotation (Line(points={{158,54},{150,54},{150,90},{142,90}}, color={0,0,127})); connect(I.u,errI2.y) - annotation (Line(points={{-52,0},{-68,0}},color={0,0,127})); + annotation (Line(points={{-52,0},{-78,0}},color={0,0,127})); connect(errI1.y,errI2.u1) - annotation (Line(points={{-118,0},{-100,0},{-100,6},{-92,6}}, color={0,0,127})); + annotation (Line(points={{-118,6},{-102,6}}, color={0,0,127})); connect(controlError.u1,u_s) - annotation (Line(points={{-202,6},{-212,6},{-212,0},{-240,0}}, color={0,0,127})); + annotation (Line(points={{-202,0},{-240,0}}, color={0,0,127})); connect(cheYMinMax.y,assMesYMinMax.u) annotation (Line(points={{142,-150},{158,-150}},color={255,0,255})); connect(Izero.y,addPID.u2) - annotation (Line(points={{42,84},{78,84}}, color={0,0,127})); + annotation (Line(points={{-28,30},{60,30},{60,84},{78,84}}, + color={0,0,127})); connect(errP.u1,uS_revAct.y) annotation (Line(points={{-142,146},{-170,146},{-170,40},{-178,40}},color={0,0,127})); connect(errD.u1,uS_revAct.y) annotation (Line(points={{-142,76},{-170,76},{-170,40},{-178,40}},color={0,0,127})); connect(addPD.u1, P.y) - annotation (Line(points={{18,132},{10,132},{10,140},{-28,140}}, color={0,0,127})); + annotation (Line(points={{18,140},{-28,140}}, color={0,0,127})); connect(P.u, errP.y) annotation (Line(points={{-52,140},{-118,140}},color={0,0,127})); connect(addPID.y, lim.u) annotation (Line(points={{102,90},{118,90}},color={0,0,127})); - connect(addPID.y, antWinErr.u1) annotation (Line(points={{102,90},{110,90},{110, - 66},{160,66}}, color={0,0,127})); + connect(addPID.y, antWinErr.u1) annotation (Line(points={{102,90},{114,90},{ + 114,66},{158,66}}, color={0,0,127})); connect(addRes.u1, yResSig.y) - annotation (Line(points={{-102,-74},{-110,-74},{-110,-80},{-118,-80}}, color={0,0,127})); - connect(u_m, controlError.u2) annotation (Line(points={{0,-220},{0,-160},{-210, - -160},{-210,-6},{-202,-6}}, color={0,0,127})); - connect(uMea_revAct.y, errP.u2) annotation (Line(points={{-158,-40},{-150,-40}, + annotation (Line(points={{-102,-74},{-118,-74}}, color={0,0,127})); + connect(u_m, controlError.u2) annotation (Line(points={{0,-220},{0,-160},{ + -210,-160},{-210,-12},{-202,-12}}, + color={0,0,127})); + connect(uMea_revAct.y, errP.u2) annotation (Line(points={{-178,-40},{-150,-40}, {-150,134},{-142,134}}, color={0,0,127})); - connect(uMea_revAct.y, errI1.u2) annotation (Line(points={{-158,-40},{-150,-40}, - {-150,-6},{-142,-6}}, color={0,0,127})); - connect(antWinGai.y, errI2.u2) annotation (Line(points={{158,-20},{-100,-20},{ - -100,-6},{-92,-6}}, color={0,0,127})); - connect(addPD.y, addRes.u2) annotation (Line(points={{42,126},{60,126},{60,-100}, - {-110,-100},{-110,-86},{-102,-86}}, color={0,0,127})); + connect(uMea_revAct.y, errI1.u2) annotation (Line(points={{-178,-40},{-150, + -40},{-150,0},{-142,0}}, + color={0,0,127})); + connect(antWinGai.y, errI2.u2) annotation (Line(points={{158,-20},{-110,-20}, + {-110,-6},{-102,-6}}, + color={0,0,127})); + connect(addPD.y, addRes.u2) annotation (Line(points={{42,134},{50,134},{50, + -100},{-110,-100},{-110,-86},{-102,-86}}, + color={0,0,127})); connect(kDer.y, D.k) annotation (Line(points={{-78,120},{-58,120},{-58,78},{ -52,78}}, color={0,0,127})); connect(TDer.y, D.T) annotation (Line(points={{-78,90},{-60,90},{-60,74},{-52, diff --git a/Buildings/Controls/OBC/Utilities/PIDWithInputGains.mo b/Buildings/Controls/OBC/Utilities/PIDWithInputGains.mo new file mode 100644 index 00000000000..e3aa0f2c028 --- /dev/null +++ b/Buildings/Controls/OBC/Utilities/PIDWithInputGains.mo @@ -0,0 +1,558 @@ +within Buildings.Controls.OBC.Utilities; +block PIDWithInputGains + "P, PI, PD, and PID controller with output reset and input gains" + parameter Buildings.Controls.OBC.CDL.Types.SimpleController controllerType=Buildings.Controls.OBC.CDL.Types.SimpleController.PI + "Type of controller"; + parameter Real r( + min=100*CDL.Constants.eps)=1 + "Typical range of control error, used for scaling the control error"; + parameter Real yMax=1 + "Upper limit of output" + annotation (Dialog(group="Limits")); + parameter Real yMin=0 + "Lower limit of output" + annotation (Dialog(group="Limits")); + parameter Real Ni( + min=100*CDL.Constants.eps)=0.9 + "Ni*Ti is time constant of anti-windup compensation" + annotation (Dialog(tab="Advanced",group="Integrator anti-windup",enable=controllerType == CDL.Types.SimpleController.PI or controllerType ==CDL.Types.SimpleController.PID)); + parameter Real Nd( + min=100*CDL.Constants.eps)=10 + "The higher Nd, the more ideal the derivative block" + annotation (Dialog(tab="Advanced",group="Derivative block",enable=controllerType == CDL.Types.SimpleController.PD or controllerType ==CDL.Types.SimpleController.PID)); + parameter Real xi_start=0 + "Initial value of integrator state" + annotation (Dialog(tab="Advanced",group="Initialization",enable=controllerType == CDL.Types.SimpleController.PI or controllerType == CDL.Types.SimpleController.PID)); + parameter Real yd_start=0 + "Initial value of derivative output" + annotation (Dialog(tab="Advanced",group="Initialization",enable=controllerType == CDL.Types.SimpleController.PD or controllerType == CDL.Types.SimpleController.PID)); + parameter Boolean reverseActing=true + "Set to true for reverse acting, or false for direct acting control action"; + parameter Real y_reset=xi_start + "Value to which the controller output is reset if the boolean trigger has a rising edge" + annotation (Dialog(enable=controllerType == CDL.Types.SimpleController.PI or controllerType == CDL.Types.SimpleController.PID,group="Integrator reset")); + Buildings.Controls.OBC.CDL.Interfaces.RealInput u_s + "Connector for setpoint input signal" + annotation (Placement(transformation(extent={{-260,-20},{-220,20}}),iconTransformation(extent={{-140,-20},{-100,20}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput u_m + "Connector for measurement input signal" + annotation (Placement(transformation(origin={0,-220},extent={{20,-20},{-20,20}},rotation=270),iconTransformation(extent={{20,-20},{-20,20}},rotation=270,origin={0,-120}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput k( + min=100*Buildings.Controls.OBC.CDL.Constants.eps) + "Connector for control gain signal" + annotation (Placement(transformation(extent={{-260,160},{-220,200}}),iconTransformation(extent={{-140,60},{-100,100}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput Ti( + quantity="Time", + unit="s", + min=100*Buildings.Controls.OBC.CDL.Constants.eps) + if with_I + "Connector for time constant signal for the integral term" + annotation (Placement(transformation(extent={{-260,100},{-220,140}}), + iconTransformation(extent={{-140,20},{-100,60}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealInput Td( + quantity="Time", + unit="s", + min=100*Buildings.Controls.OBC.CDL.Constants.eps) + if with_D + "Connector for time constant signal for the derivative term" + annotation (Placement(transformation(extent={{-260,40},{-220,80}}), iconTransformation(extent={{-140,-60},{-100,-20}}))); + Buildings.Controls.OBC.CDL.Interfaces.RealOutput y + "Connector for actuator output signal" + annotation (Placement(transformation(extent={{220,-20},{260,20}}),iconTransformation(extent={{100,-20},{140,20}}))); + Buildings.Controls.OBC.CDL.Interfaces.BooleanInput trigger + "Resets the controller output when trigger becomes true" + annotation (Placement(transformation(extent={{-20,-20},{20,20}},rotation=90,origin={-160,-220}),iconTransformation(extent={{-20,-20},{20,20}},rotation=90,origin={-60,-120}))); + Buildings.Controls.OBC.CDL.Continuous.Subtract controlError + "Control error (set point - measurement)" + annotation (Placement(transformation(extent={{-200,-16},{-180,4}}))); + Buildings.Controls.OBC.CDL.Continuous.Multiply P + "Proportional action" + annotation (Placement(transformation(extent={{-50,130},{-30,150}}))); + Buildings.Controls.OBC.CDL.Continuous.IntegratorWithReset I( + final k=1, + final y_start=xi_start) if with_I + "Integral term" + annotation (Placement(transformation(extent={{-50,-10},{-30,10}}))); + Buildings.Controls.OBC.CDL.Continuous.Derivative D( + final y_start=yd_start) if with_D + "Derivative term" + annotation (Placement(transformation(extent={{-50,60},{-30,80}}))); + Buildings.Controls.OBC.CDL.Continuous.Subtract errP + "P error" + annotation (Placement(transformation(extent={{-140,130},{-120,150}}))); + Buildings.Controls.OBC.CDL.Continuous.Subtract errD if with_D + "D error" + annotation (Placement(transformation(extent={{-140,60},{-120,80}}))); + Buildings.Controls.OBC.CDL.Continuous.Subtract errI1 if with_I + "I error (before anti-windup compensation)" + annotation (Placement(transformation(extent={{-140,-4},{-120,16}}))); + Buildings.Controls.OBC.CDL.Continuous.Subtract errI2 if with_I + "I error (after anti-windup compensation)" + annotation (Placement(transformation(extent={{-100,-10},{-80,10}}))); + Buildings.Controls.OBC.CDL.Continuous.Limiter lim( + final uMax=yMax, + final uMin=yMin) + "Limiter" + annotation (Placement(transformation(extent={{120,80},{140,100}}))); + Buildings.Controls.OBC.CDL.Continuous.Divide antWinGai2 "Outputs of anti-windup compensation" + annotation (Placement(transformation(extent={{100,-30},{80,-10}}))); + Buildings.Controls.OBC.CDL.Continuous.Divide gaiI if with_I "Gain of the integral term" + annotation (Placement(transformation(extent={{-200,116},{-180,136}}))); + Buildings.Controls.OBC.CDL.Continuous.Multiply errIWithGai if with_I + "I error (after multiplying with the gain of the integral term)" + annotation (Placement(transformation(extent={{-84,28},{-64,48}}))); + Buildings.Controls.OBC.CDL.Continuous.Multiply mulkTd if with_D + "Product of k and Td" + annotation (Placement(transformation(extent={{-200,150},{-180,170}}))); + Buildings.Controls.OBC.CDL.Continuous.GreaterThreshold greThrkTd( + t=1E-6, + h=1E-6/2) + if with_D + "Check if k*Td is larger than 0" + annotation (Placement(transformation(extent={{140,160},{160,180}}))); + +protected + final parameter Real revAct= + if reverseActing then + 1 + else + -1 + "Switch for sign for reverse or direct acting controller"; + final parameter Boolean with_I=controllerType == Buildings.Controls.OBC.CDL.Types.SimpleController.PI or controllerType == Buildings.Controls.OBC.CDL.Types.SimpleController.PID + "Boolean flag to enable integral action" + annotation (Evaluate=true,HideResult=true); + final parameter Boolean with_D=controllerType == Buildings.Controls.OBC.CDL.Types.SimpleController.PD or controllerType == Buildings.Controls.OBC.CDL.Types.SimpleController.PID + "Boolean flag to enable derivative action" + annotation (Evaluate=true,HideResult=true); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant Dzero( + final k=0) if not with_D + "Zero input signal" + annotation (Evaluate=true,HideResult=true,Placement(transformation(extent={{-50,90}, + {-30,110}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant Izero( + final k=0) if not with_I + "Zero input signal" + annotation (Placement(transformation(extent={{-50,20},{-30,40}}))); + Buildings.Controls.OBC.CDL.Continuous.MultiplyByParameter uS_revAct( + final k=revAct/r) "Set point multiplied by reverse action sign" + annotation (Placement(transformation(extent={{-200,30},{-180,50}}))); + Buildings.Controls.OBC.CDL.Continuous.MultiplyByParameter uMea_revAct( + final k=revAct/r) + "Set point multiplied by reverse action sign" + annotation (Placement(transformation(extent={{-200,-50},{-180,-30}}))); + Buildings.Controls.OBC.CDL.Continuous.Add addPD + "Outputs P and D gains added" + annotation (Placement(transformation(extent={{20,124},{40,144}}))); + Buildings.Controls.OBC.CDL.Continuous.Add addPID + "Outputs P, I and D gains added" + annotation (Placement(transformation(extent={{80,80},{100,100}}))); + Buildings.Controls.OBC.CDL.Continuous.Subtract antWinErr if with_I + "Error for anti-windup compensation" + annotation (Placement(transformation(extent={{160,50},{180,70}}))); + Buildings.Controls.OBC.CDL.Continuous.MultiplyByParameter antWinGai1(k=1/Ni) + if with_I "Gain for anti-windup compensation without the proportional gain" + annotation (Placement(transformation(extent={{180,-30},{160,-10}}))); + Buildings.Controls.OBC.CDL.Continuous.Sources.Constant yResSig( + final k=y_reset) if with_I + "Signal for y_reset" + annotation (Placement(transformation(extent={{-140,-84},{-120,-64}}))); + Buildings.Controls.OBC.CDL.Continuous.Subtract addRes if with_I + "Adder for integrator reset" + annotation (Placement(transformation(extent={{-100,-90},{-80,-70}}))); + Buildings.Controls.OBC.CDL.Logical.Sources.Constant cheYMinMax( + final k=yMin < yMax) "Check for values of yMin and yMax" + annotation (Placement(transformation(extent={{140,120},{160,140}}))); + Buildings.Controls.OBC.CDL.Utilities.Assert assMesYMinMax( + message="LimPID: Limits must be yMin < yMax") "Assertion on yMin and yMax" + annotation (Placement(transformation(extent={{180,120},{200,140}}))); + Buildings.Controls.OBC.CDL.Utilities.Assert assMeskTd( + message="LimPIDWithInputGains: Limits must be k*Td > 0") + if with_D + "Assertion on k and Td" + annotation (Placement(transformation(extent={{180,160},{200,180}}))); + Buildings.Controls.OBC.CDL.Continuous.MultiplyByParameter gaiT(final k=1/Nd) if with_D + "Gain to compute time constant for derivative action" + annotation (Placement(transformation(extent={{-140,100},{-120,120}}))); + +equation + connect(trigger,I.trigger) + annotation (Line(points={{-160,-220},{-160,-140},{-40,-140},{-40,-12}},color={255,0,255})); + connect(u_s,uS_revAct.u) + annotation (Line(points={{-240,0},{-210,0},{-210,40},{-202,40}},color={0,0,127})); + connect(u_m,uMea_revAct.u) + annotation (Line(points={{0,-220},{0,-160},{-210,-160},{-210,-40},{-202,-40}},color={0,0,127})); + connect(errD.u2,uMea_revAct.y) + annotation (Line(points={{-142,64},{-150,64},{-150,-40},{-178,-40}}, color={0,0,127})); + connect(D.u,errD.y) + annotation (Line(points={{-52,70},{-118,70}}, color={0,0,127})); + connect(errI1.u1,uS_revAct.y) + annotation (Line(points={{-142,12},{-170,12},{-170,40},{-178,40}}, + color={0,0,127})); + connect(addPID.u1,addPD.y) + annotation (Line(points={{78,96},{50,96},{50,134},{42,134}},color={0,0,127})); + connect(lim.y,y) + annotation (Line(points={{142,90},{200,90},{200,0},{240,0}},color={0,0,127})); + connect(antWinErr.y, antWinGai1.u) + annotation (Line(points={{182,60},{190,60},{190,-20},{182,-20}}, color={0,0,127})); + connect(addPD.u2,Dzero.y) + annotation (Line(points={{18,128},{-10,128},{-10,100},{-28,100}}, + color={0,0,127})); + connect(D.y,addPD.u2) + annotation (Line(points={{-28,70},{-10,70},{-10,128},{18,128}},color={0,0,127})); + connect(addPID.u2,I.y) + annotation (Line(points={{78,84},{68,84},{68,0},{-28,0}},color={0,0,127})); + connect(addRes.y,I.y_reset_in) + annotation (Line(points={{-78,-80},{-60,-80},{-60,-8},{-52,-8}},color={0,0,127})); + connect(antWinErr.u2,lim.y) + annotation (Line(points={{158,54},{150,54},{150,90},{142,90}}, color={0,0,127})); + connect(errI1.y,errI2.u1) + annotation (Line(points={{-118,6},{-102,6}}, color={0,0,127})); + connect(controlError.u1,u_s) + annotation (Line(points={{-202,0},{-240,0}}, color={0,0,127})); + connect(cheYMinMax.y,assMesYMinMax.u) + annotation (Line(points={{162,130},{178,130}}, color={255,0,255})); + connect(Izero.y,addPID.u2) + annotation (Line(points={{-28,30},{58,30},{58,84},{78,84}}, + color={0,0,127})); + connect(errP.u1,uS_revAct.y) + annotation (Line(points={{-142,146},{-170,146},{-170,40},{-178,40}},color={0,0,127})); + connect(errD.u1,uS_revAct.y) + annotation (Line(points={{-142,76},{-170,76},{-170,40},{-178,40}},color={0,0,127})); + connect(addPD.u1, P.y) + annotation (Line(points={{18,140},{-28,140}}, color={0,0,127})); + connect(addPID.y, lim.u) + annotation (Line(points={{102,90},{118,90}},color={0,0,127})); + connect(addPID.y, antWinErr.u1) + annotation (Line(points={{102,90},{114,90},{114,66},{158,66}},color={0,0,127})); + connect(addRes.u1, yResSig.y) + annotation (Line(points={{-102,-74},{-118,-74}}, color={0,0,127})); + connect(u_m, controlError.u2) + annotation (Line(points={{0,-220},{0,-160},{-210,-160},{-210,-12},{-202,-12}}, + color={0,0,127})); + connect(uMea_revAct.y, errP.u2) + annotation (Line(points={{-178,-40},{-150,-40},{-150,134},{-142,134}}, color={0,0,127})); + connect(uMea_revAct.y, errI1.u2) + annotation (Line(points={{-178,-40},{-150,-40},{-150,0},{-142,0}}, color={0,0,127})); + connect(addPD.y, addRes.u2) + annotation (Line(points={{42,134},{50,134},{50,-100},{-110,-100},{-110,-86}, + {-102,-86}}, color={0,0,127})); + connect(errP.y, P.u2) + annotation (Line(points={{-118,140},{-74,140},{-74,134},{-52,134}}, color={0,0,127})); + connect(P.u1, k) + annotation (Line(points={{-52,146},{-70,146},{-70,188},{-212,188},{-212,180}, + {-240,180}}, color={0,0,127})); + connect(antWinGai1.y, antWinGai2.u1) + annotation (Line(points={{158,-20},{140,-20},{140,-14},{102,-14}}, + color={0,0,127})); + connect(antWinGai2.u2, k) + annotation (Line(points={{102,-26},{108,-26},{108,188},{-212,188},{-212,180}, + {-240,180}}, color={0,0,127})); + connect(antWinGai2.y, errI2.u2) + annotation (Line(points={{78,-20},{-110,-20},{-110,-6},{-102,-6}}, + color={0,0,127})); + connect(gaiI.u1, k) + annotation (Line(points={{-202,132},{-212,132},{-212,180},{-240,180}}, color={0,0,127})); + connect(gaiI.u2, Ti) + annotation (Line(points={{-202,120},{-240,120}}, color={0,0,127})); + connect(gaiI.y, errIWithGai.u1) + annotation (Line(points={{-178,126},{-100,126},{-100,44},{-86,44}},color={0,0,127})); + connect(errI2.y, errIWithGai.u2) + annotation (Line(points={{-78,0},{-70,0},{-70,20},{-100,20},{-100,32},{-86, + 32}}, color={0,0,127})); + connect(errIWithGai.y, I.u) + annotation (Line(points={{-62,38},{-60,38},{-60,0},{-52,0}}, color={0,0,127})); + connect(mulkTd.u1, k) + annotation (Line(points={{-202,166},{-212,166},{-212,180},{-240,180}},color={0,0,127})); + connect(greThrkTd.y, assMeskTd.u) + annotation (Line(points={{162,170},{178,170}}, color={255,0,255})); + connect(mulkTd.y, greThrkTd.u) + annotation (Line(points={{-178,160},{-168,160},{-168,184},{132,184},{132, + 170},{138,170}}, color={0,0,127})); + connect(mulkTd.u2, Td) + annotation (Line(points={{-202,154},{-206,154},{-206,60},{-240,60}},color={0,0,127})); + connect(Td, gaiT.u) + annotation (Line(points={{-240,60},{-180,60},{-180,110},{-142,110}}, color={0,0,127})); + connect(gaiT.y, D.T) + annotation (Line(points={{-118,110},{-84,110},{-84,74},{-52,74}}, color={0,0,127})); + connect(mulkTd.y, D.k) annotation (Line(points={{-178,160},{-168,160},{-168, + 184},{-80,184},{-80,78},{-52,78}}, color={0,0,127})); + annotation ( + defaultComponentName="conPID", + Icon( + coordinateSystem( + extent={{-100,-100},{100,100}}), + graphics={ + Rectangle( + extent={{-100,-100},{100,100}}, + lineColor={0,0,127}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Rectangle( + extent={{-6,-20},{66,-66}}, + lineColor={255,255,255}, + fillColor={255,255,255}, + fillPattern=FillPattern.Solid), + Text( + visible=(controllerType == Buildings.Controls.OBC.CDL.Types.SimpleController.P), + extent={{-32,-22},{68,-62}}, + lineColor={0,0,0}, + textString="P", + fillPattern=FillPattern.Solid, + fillColor={175,175,175}), + Text( + visible=(controllerType == Buildings.Controls.OBC.CDL.Types.SimpleController.PI), + extent={{-26,-22},{74,-62}}, + lineColor={0,0,0}, + textString="PI", + fillPattern=FillPattern.Solid, + fillColor={175,175,175}), + Text( + visible=(controllerType == Buildings.Controls.OBC.CDL.Types.SimpleController.PD), + extent={{-16,-22},{88,-62}}, + lineColor={0,0,0}, + fillPattern=FillPattern.Solid, + fillColor={175,175,175}, + textString="P D"), + Text( + visible=(controllerType == Buildings.Controls.OBC.CDL.Types.SimpleController.PID), + extent={{-14,-22},{86,-62}}, + lineColor={0,0,0}, + textString="PID", + fillPattern=FillPattern.Solid, + fillColor={175,175,175}), + Polygon( + points={{-80,82},{-88,60},{-72,60},{-80,82}}, + lineColor={192,192,192}, + fillColor={192,192,192}, + fillPattern=FillPattern.Solid), + Line( + points={{-80,68},{-80,-100}}, + color={192,192,192}), + Line( + points={{-90,-80},{70,-80}}, + color={192,192,192}), + Polygon( + points={{74,-80},{52,-72},{52,-88},{74,-80}}, + lineColor={192,192,192}, + fillColor={192,192,192}, + fillPattern=FillPattern.Solid), + Text( + extent={{-150,150},{150,110}}, + textString="%name", + textColor={0,0,255}), + Line( + points={{-80,-80},{-80,-22}}, + color={0,0,0}), + Line( + points={{-80,-22},{6,56}}, + color={0,0,0}), + Line( + points={{6,56},{68,56}}, + color={0,0,0}), + Rectangle( + extent=DynamicSelect({{100,-100},{84,-100}},{{100,-100},{84,-100+(y-yMin)/(yMax-yMin)*200}}), + fillColor={175,175,175}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None, + lineColor={0,0,0})}), + Diagram( + coordinateSystem( + extent={{-220,-200},{220,200}}), graphics={Rectangle( + extent={{-56,180},{-24,-16}}, + fillColor={215,215,215}, + fillPattern=FillPattern.Solid, + pattern=LinePattern.None), Text( + extent={{-52,184},{-28,156}}, + pattern=LinePattern.None, + fillColor={215,215,215}, + fillPattern=FillPattern.Solid, + lineColor={0,0,0}, + textString="PID")}), + Documentation( + info=" +
+PID controller in the standard form +
++yu = k/r (e(t) + 1 ⁄ Ti ∫ e(τ) dτ + Td d⁄dt e(t)), +
++with output reset, +where +yu is the control signal before output limitation, +e(t) = us(t) - um(t) is the control error, +with us being the set point and um being +the measured quantity, +k is the gain, +Ti is the time constant of the integral term, +Td is the time constant of the derivative term, +r is a scaling factor, with default r=1. +The scaling factor should be set to the typical order of magnitude of the range of the error e. +For example, you may set r=100 to r=1000 +if the control input is a pressure of a heating water circulation pump in units of Pascal, or +leave r=1 if the control input is a room temperature. +
++Note that the units of k are the inverse of the units of the control error, +while the units of Ti and Td are seconds. +
++The actual control output is +
++y = min( ymax, max( ymin, y)), +
++where ymin and ymax are limits for the control signal. +
++This block is identical to + +Buildings.Controls.OBC.CDL.Continuous.PIDWithReset, +except that the controller gains +k, Ti and Td are inputs rather than parameters. +
+
+Through the parameter controllerType
, the controller can be configured
+as P, PI, PD or PID controller. The default configuration is PI.
+
+Through the parameter reverseActing
, the controller can be configured to
+be reverse or direct acting.
+The above standard form is reverse acting, which is the default configuration.
+For a reverse acting controller, for a constant set point,
+an increase in measurement signal u_m
decreases the control output signal y
+(Montgomery and McDowall, 2008).
+Thus,
+
reverseActing = true
, but
+ reverseActing = false
.
+
+If reverseAction=false
, then the error e above is multiplied by -1.
+
+The controller anti-windup compensation is as follows: +Instead of the above basic control law, the implementation is +
++yu = k (e(t) ⁄ r + 1 ⁄ Ti ∫ (-Δy + e(τ) ⁄ r) dτ + Td ⁄ r d⁄dt e(t)), +
++where the anti-windup compensation Δy is +
++Δy = (yu - y) ⁄ (k Ni), +
++where +Ni > 0 is the time constant for the anti-windup compensation. +To accelerate the anti-windup, decrease Ni. +
++Note that the anti-windup term (-Δy + e(τ) ⁄ r) shows that the range of +the typical control error r should be set to a reasonable value so that +
++e(τ) ⁄ r = (us(τ) - um(τ)) ⁄ r +
++has order of magnitude one, and hence the anti-windup compensation should work well. +
+
+Whenever the value of boolean input signal trigger
changes from
+false
to true
, the controller output is reset by setting
+y
to the value of the parameter y_reset
.
+
+The derivative of the control error d ⁄ dt e(t) is approximated using +
++d⁄dt x(t) = (e(t)-x(t)) Nd ⁄ Td, +
++and +
++d⁄dt e(t) ≈ Nd (e(t)-x(t)), +
++where x(t) is an internal state. +
++The parameters of the controller can be manually adjusted by performing +closed loop tests (= controller + plant connected +together) and using the following strategy: +
+k
+(the total gain of the controller) until the closed-loop response
+cannot be improved any more.
+k
and Ti
(the time constant of the integrator).
+The first value of Ti
can be selected such that it is in the
+order of the time constant of the oscillations occurring with
+the P-controller. If, e.g., oscillations in the order of 100 seconds
+occur in the previous step, start with Ti=1/100
seconds.
+k
, Ti
, Td
(time constant of derivative block).
+yMax
and yMin
according to your specification.
+Ni
(Ni Ti is the time constant of
+the anti-windup compensation) such that the input to the limiter
+block (= lim.u
) goes quickly enough back to its limits.
+If Ni
is decreased, this happens faster. If Ni
is very large, the
+anti-windup compensation is not effective and the controller works bad.
++R. Montgomery and R. McDowall (2008). +\"Fundamentals of HVAC Control Systems.\" +American Society of Heating Refrigerating and Air-Conditioning Engineers Inc. Atlanta, GA. +
+", + revisions=" +true
.+Validation test for the block + +Buildings.Controls.OBC.Utilities.PIDWithInputGains. +
++For t ∈ [0, 0.6] both PID controllers have the same gains. +During this time, they generate the same output. +Afterwards, the gains, and hence also their outputs, differ. + +Buildings.Controls.OBC.CDL.Continuous.PIDWithReset. +
+", + revisions=" +