Archived OpenModelica forums. Posting is disabled.

Alternative forums include GitHub discussions or StackOverflow (make sure to read the Stack Overflow rules; you need to have well-formed questions)


Forgot password? | Forgot username? | Register

PI controller

PI controller

Dears,

I am looking for advice, I want to have a very simple PI controller implemented as function:

function pi
  input Real y;
  output Real u;
  parameter Real K = 1 "Proportional gain";
  parameter Real Ti = 1 "Integral time";
algorithm
  u := K * y + Ti * der(u);
end pi;


I  try to use this pi-function in my test-model as

model test_pi
  import pi;
  Real y(start = 1);
  Real action;
equation
  action = pi(y);
end test_pi;

Unfortunately I am getting
[C:/OpenModelica1.9.1/work/pi.mo:5:3-5:40] Warning: Invalid public variable Ki, function variables that are not input/output must be protected.
[C:/OpenModelica1.9.1/work/pi.mo:4:3-4:43] Warning: Invalid public variable K, function variables that are not input/output must be protected.

What's the correct way to have params within function?

Thank you.

Best regards,
Peb

Re: PI controller

Well. You can't really have parameters in a function as there is no initialization. The warning is correct that only inputs and outputs may be public.

Make them either protected constants or simply protected:

Code:

function pi 

  input Real y;
  output Real u;
protected
  Real K = 1 "Proportional gain";
  Real Ti = 1 "Integral time";
algorithm
  u := K * y + Ti * der(u);
end pi;

Re: PI controller

It seems to me that integration under "function" is not working as I expected - maybe I am doing something wrong

function pi
  input Real y;
  output Real u;
protected
  Real K = 1;
  Real Ti = 1;
algorithm
  u := K * y + Ti * der(u);
end pi;

Now "variables K,Ti" seems OK but cannot run test_pi:

I got following
[C:/OpenModelica1.9.1/work/pi.mo:8:3-8:27] Warning: u was used before it was defined (given a value). Additional such uses may exist for the variable, but some messages were suppressed.

Simulation Output
test_pi_functions.c
gcc    -falign-functions -msse2 -mfpmath=sse     -I"C:/OpenModelica1.9.1//include/omc/c" -I. -DOPENMODELICA_XML_FROM_FILE_AT_RUNTIME  -c -o test_pi_records.o test_pi_records.c
gcc    -falign-functions -msse2 -mfpmath=sse     -I"C:/OpenModelica1.9.1//include/omc/c" -I. -DOPENMODELICA_XML_FROM_FILE_AT_RUNTIME  -c -o test_pi_01exo.o test_pi_01exo.c
test_pi_functions.c: In function 'omc_pi':
test_pi_functions.c:20: error: '$P$DER$Pu' undeclared (first use in this function)
test_pi_functions.c:20: error: (Each undeclared identifier is reported only once
test_pi_functions.c:20: error: for each function it appears in.)
mingw32-make: *** [test_pi_functions.o] Error 1
mingw32-make: *** Waiting for unfinished jobs....
Compilation process exited with code 2

Re: PI controller

Yes. derivative operator is forbidden in functions. Maybe you want to use a block instead of a function?
Also, keep in mind that the integrator needs der(u) in order to calculate u. Not the other way around.

Re: PI controller

I did my PI as

model pi
  Real y(start = 0);
  Real u(start = 0);
  parameter Real K = 1;
  parameter Real Ti = 1;
equation
  u = K * y + Ti * u;
  y = der(u);
end pi;

and I just want to try it:

model test_pi
  pi controller;
  Real fbck;
equation
  fbck = 1;
  controller.y = fbck;
end test_pi;

[:0:0-0:0] Error: Too many equations, over-determined system. The model has 1 equation(s) and 0 variable(s).

is there a way how to go around this?

Do you have any tricks how to handle integration under Modelica?

Re: PI controller

Flatten the model (instantiate model) and you see:

Code:

class test_pi

  Real controller.y(start = 0.0);
  Real controller.u(start = 0.0);
  parameter Real controller.K = 1.0;
  parameter Real controller.Ti = 1.0;
  Real fbck;
equation
  controller.u = controller.K * controller.y + controller.Ti * controller.u;
  controller.y = der(controller.u);
  fbck = 1.0;
  controller.y = fbck;
end test_pi;

You pretty much have:

Code:

controller.y := fbck;

controller.y := der(controller.u);

Modelica has a single assignment rule. Remove controller.t = fbck and the model translates. Note that it is unbalanced because controller.u is not given an initial value: u(start=0, fixed=true) solves that.

Edited by: sjoelund.se - Jan-29-15 11:33:37

Re: PI controller

(Note: I updated OpenModelica to check if you are in function context when you try to use der; users should get nicer error messages if they try to do this in the future)

Re: PI controller

I am really appreciate a help of you.

I would like to ask that if I can run simple model (e.g. PI) in "open-loop". I apply just input signal and await what's on output by running simulation and plotting it.

I did try:

model pi
  Real y(start = 0);
  Real u(start = 0, fixed = true);
  parameter Real K = 1;
  parameter Real Ti = 1;
equation
  u = K * y + Ti * u;
  y = der(u);
end pi;

model test_pi
  pi controller;
  Real fbck(start = 1, fixed = true);
equation
  controller.y = fbck;
end test_pi;

other way how to do it? I just want the integrator to be 0 at start - expect to see that input value is integrated... I want to keep "fbck" at some non-zero const value..

Simulation Output (crashed)

assert        | debug     | division by zero at time 0, (a=1) / (b=0), where divisor b expression is: 1.0 - controller.Ti Debug more
assert        | info     | simulation terminated by an assertion at initialization
Process crashed
Simulation process exited with code -1

Re: PI controller

You might want to look at the code of Modelica.Blocks.Continuous.PI:

Code:

block PI "Proportional-Integral controller"

    import Modelica.Blocks.Types.Init;
    parameter Real k(unit="1")=1 "Gain";
    parameter SIunits.Time T(start=1,min=Modelica.Constants.small)
      "Time Constant (T>0 required)";
    parameter Modelica.Blocks.Types.Init initType=Modelica.Blocks.Types.Init.NoInit
      "Type of initialization (1: no init, 2: steady state, 3: initial state, 4: initial output)"
                                                                              annotation(Evaluate=true,
        Dialog(group="Initialization"));
    parameter Real x_start=0 "Initial or guess value of state"
      annotation (Dialog(group="Initialization"));
    parameter Real y_start=0 "Initial value of output"
      annotation(Dialog(enable=initType == Init.SteadyState or initType == Init.InitialOutput, group=
            "Initialization"));

    extends Interfaces.SISO;
    output Real x(start=x_start) "State of block";

  initial equation
    if initType == Init.SteadyState then
      der(x) = 0;
    elseif initType == Init.InitialState then
      x = x_start;
    elseif initType == Init.InitialOutput then
      y = y_start;
    end if;
  equation
    der(x) = u/T;
    y = k*(x + u);
end PI;

Re: PI controller

I did  "PI controller model" as

model pi
  Real y;
  Real u;
  Real x;
  parameter Real K = 1;
  parameter Real Ti = 1;
equation
  der(x) = u;
  y = K * u + Ti * x;
end pi;

it seems to be working fine and even comparing to Modelica built-in controller

model test_pi
  pi controller(K = 10, Ti = 10);
  Modelica.Blocks.Continuous.PI mcontroller(k = 10);
equation
  mcontroller.u = 1;
  controller.u = 1;
end test_pi;

There are 0 guests and 0 other users also viewing this topic