PID

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;