block PID "PID-controller in additive description form"
import Modelica.Blocks.Types.InitPID;
import Modelica.Blocks.Types.Init;
extends Interfaces.SISO;
parameter Real k(unit = "1") = 1 "Gain";
parameter SIunits.Time Ti(min = Modelica.Constants.small, start = 0.5) "Time Constant of Integrator";
parameter SIunits.Time Td(min = 0, start = 0.1) "Time Constant of Derivative block";
parameter Real Nd(min = Modelica.Constants.small) = 10 "The higher Nd, the more ideal the derivative block";
parameter Modelica.Blocks.Types.InitPID initType = Modelica.Blocks.Types.InitPID.DoNotUse_InitialIntegratorState "Type of initialization (1: no init, 2: steady state, 3: initial state, 4: initial output)"
annotation (
Evaluate = true,
Dialog(group = "Initialization"));
parameter Real xi_start = 0 "Initial or guess value for integrator output (= integrator state)"
annotation (Dialog(group = "Initialization"));
parameter Real xd_start = 0 "Initial or guess value for state of derivative block"
annotation (Dialog(group = "Initialization"));
parameter Real y_start = 0 "Initial value of output"
annotation (Dialog(
enable = initType == InitPID.InitialOutput,
group = "Initialization"));
constant SI.Time unitTime = 1 annotation (HideResult = true);
Blocks.Math.Gain P(k = 1) "Proportional part of PID controller"
annotation (Placement(transformation(extent = {
{-60, 60},
{-20, 100}})));
Blocks.Continuous.Integrator I(k = unitTime / Ti, y_start = xi_start, initType = if initType == InitPID.SteadyState then Init.SteadyState else if initType == InitPID.InitialState or initType == InitPID.DoNotUse_InitialIntegratorState then Init.InitialState else Init.NoInit) "Integral part of PID controller"
annotation (Placement(transformation(extent = {
{-60, -20},
{-20, 20}})));
Blocks.Continuous.Derivative D(k = Td / unitTime, T = max([Td / Nd,100 * Modelica.Constants.eps]), x_start = xd_start, initType = if initType == InitPID.SteadyState or initType == InitPID.InitialOutput then Init.SteadyState else if initType == InitPID.InitialState then Init.InitialState else Init.NoInit) "Derivative part of PID controller"
annotation (Placement(transformation(extent = {
{-60, -100},
{-20, -60}})));
Blocks.Math.Gain Gain(k = k) "Gain of PID controller"
annotation (Placement(transformation(extent = {
{60, -10},
{80, 10}})));
Blocks.Math.Add3 Add annotation (Placement(transformation(extent = {
{20, -10},
{40, 10}})));
initial equation
if initType == InitPID.InitialOutput then
y = y_start;
end if;
equation
connect(u,D.u) annotation (Line(
points = {
{-120, 0},
{-80, 0},
{-80, -80},
{-64, -80}},
color = {0, 0, 127}));
connect(u,I.u) annotation (Line(
points = {
{-120, 0},
{-64, 0}},
color = {0, 0, 127}));
connect(u,P.u) annotation (Line(
points = {
{-120, 0},
{-80, 0},
{-80, 80},
{-64, 80}},
color = {0, 0, 127}));
connect(D.y,Add.u3) annotation (Line(
points = {
{-18, -80},
{0, -80},
{0, -8},
{18, -8}},
color = {0, 0, 127}));
connect(I.y,Add.u2) annotation (Line(
points = {
{-18, 0},
{18, 0}},
color = {0, 0, 127}));
connect(P.y,Add.u1) annotation (Line(
points = {
{-18, 80},
{0, 80},
{0, 8},
{18, 8}},
color = {0, 0, 127}));
connect(Add.y,Gain.u) annotation (Line(
points = {
{41, 0},
{58, 0}},
color = {0, 0, 127}));
connect(Gain.y,y) annotation (Line(
points = {
{81, 0},
{110, 0}},
color = {0, 0, 127}));
annotation (
defaultComponentName = "PID",
Icon(
coordinateSystem(
preserveAspectRatio = true,
extent = {
{-100, -100},
{100, 100}}),
graphics = {
Line(
points = {
{-80, 78},
{-80, -90}},
color = {192, 192, 192}),
Polygon(
lineColor = {192, 192, 192},
fillColor = {192, 192, 192},
fillPattern = FillPattern.Solid,
points = {
{-80, 90},
{-88, 68},
{-72, 68},
{-80, 90}}),
Line(
points = {
{-90, -80},
{82, -80}},
color = {192, 192, 192}),
Polygon(
lineColor = {192, 192, 192},
fillColor = {192, 192, 192},
fillPattern = FillPattern.Solid,
points = {
{90, -80},
{68, -72},
{68, -88},
{90, -80}}),
Line(
points = {
{-80, -80},
{-80, -20},
{60, 80}},
color = {0, 0, 127}),
Text(
lineColor = {192, 192, 192},
extent = {
{-20, -60},
{80, -20}},
textString = "PID"),
Text(
extent = {
{-150, -150},
{150, -110}},
textString = "Ti=%Ti")}),
Documentation(info = "<html>\n<p>\nThis is the text-book version of a PID-controller.\nFor a more practically useful PID-controller, use\nblock LimPID.\n</p>\n\n<p>\nThe PID block can be initialized in different\nways controlled by parameter <strong>initType</strong>. The possible\nvalues of initType are defined in\n<a href=\"modelica://Modelica.Blocks.Types.InitPID\">Modelica.Blocks.Types.InitPID</a>.\nThis type is identical to\n<a href=\"modelica://Modelica.Blocks.Types.Init\">Types.Init</a>,\nwith the only exception that the additional option\n<strong>DoNotUse_InitialIntegratorState</strong> is added for\nbackward compatibility reasons (= integrator is initialized with\nInitialState whereas differential part is initialized with\nNoInit which was the initialization in version 2.2 of the Modelica\nstandard library).\n</p>\n\n<p>\nBased on the setting of initType, the integrator (I) and derivative (D)\nblocks inside the PID controller are initialized according to the following table:\n</p>\n\n<table border=1 cellspacing=0 cellpadding=2>\n <tr><td><strong>initType</strong></td>\n <td><strong>I.initType</strong></td>\n <td><strong>D.initType</strong></td></tr>\n\n <tr><td><strong>NoInit</strong></td>\n <td>NoInit</td>\n <td>NoInit</td></tr>\n\n <tr><td><strong>SteadyState</strong></td>\n <td>SteadyState</td>\n <td>SteadyState</td></tr>\n\n <tr><td><strong>InitialState</strong></td>\n <td>InitialState</td>\n <td>InitialState</td></tr>\n\n <tr><td><strong>InitialOutput</strong><br>\n and initial equation: y = y_start</td>\n <td>NoInit</td>\n <td>SteadyState</td></tr>\n\n <tr><td><strong>DoNotUse_InitialIntegratorState</strong></td>\n <td>InitialState</td>\n <td>NoInit</td></tr>\n</table>\n\n<p>\nIn many cases, the most useful initial condition is\n<strong>SteadyState</strong> because initial transients are then no longer\npresent. If initType = InitPID.SteadyState, then in some\ncases difficulties might occur. The reason is the\nequation of the integrator:\n</p>\n\n<pre>\n <strong>der</strong>(y) = k*u;\n</pre>\n\n<p>\nThe steady state equation \"der(x)=0\" leads to the condition that the input u to the\nintegrator is zero. If the input u is already (directly or indirectly) defined\nby another initial condition, then the initialization problem is <strong>singular</strong>\n(has none or infinitely many solutions). This situation occurs often\nfor mechanical systems, where, e.g., u = desiredSpeed - measuredSpeed and\nsince speed is both a state and a derivative, it is natural to\ninitialize it with zero. As sketched this is, however, not possible.\nThe solution is to not initialize u or the variable that is used\nto compute u by an algebraic equation.\n</p>\n\n</html>"));
end PID;