システムとモデリング

SysML, Matlab/Simulink,他モデリング全般について。たまにプロジェクトマネジメント。

Open Modelicaで流量のPIDコントロール その1

こんばんは。Otepipiです。 今日はModelica標準ライブラリを使用して流量のコントロールを検討してみます。 図のように圧力の高いところから圧力の低いところに流体を流し、その流量を流量計で測定し、望ましい流量になるようにバルブの開度を変更するフィードバック制御をかけます。 f:id:Otepipi:20180729201338p:plain

今日はフィードバック制御をかける前段階まで実施していきたいと思います。

機器の設置

まず機器を設置するところからはじめます。

境界

境界はModelica標準ライブラリのFluid -> Souces -> Boudary_pTを使います。 f:id:Otepipi:20180729201703p:plain

圧力の高い方の境界には下のように25barの圧力を設定してみます。 f:id:Otepipi:20180729201853p:plain

逆に圧力の低い境界には10barで設定します。 f:id:Otepipi:20180729201943p:plain

これで⊿P=25bar-10bar=15barを駆動力として流体が移動するようになります。

バルブ

流量調整バルブはFluid -> Valves -> ValveLinerを選択します。 f:id:Otepipi:20180729202104p:plain
これは1を全開、0を全閉として0~1の制御信号を入力すれば、その数値に沿って線形に流体抵抗がかかるようになります。 また全開時の抵抗として、仮に流量40kg/sのとき1barの圧損がかかると設定してやります。 f:id:Otepipi:20180729202409p:plain

バルブの制御信号

本来はフィードバック制御をかけるのですが、今回は試運転としてステップ信号をかけることにします。 シミュレーション開始から5秒間は0を出力(バルブ全閉)、その後は1を出力(バルブ全開)するとします。 ステップ信号は'Blocks -> Sources -> Step`を選択します。
f:id:Otepipi:20180729202916p:plain
またステップ信号の動作を下のように設定します。
f:id:Otepipi:20180729203143p:plain

流量計

流量計は'Fluid -> Sensors -> MassFlowRate`を選択します。 f:id:Otepipi:20180729202525p:plain
これは特に設定はありません。

これで下図のように配置できたと思います。 f:id:Otepipi:20180729203229p:plain

結線

各部品をコネクタで接続します。 boundaryのコネクタは小さい円のものを使います。接続時下のような選択肢が出てきますが、とりあえず[1]を選択しましょう。
f:id:Otepipi:20180729203452p:plain
これで下図のように結線できたと思います。 f:id:Otepipi:20180729203531p:plain

モデルのチェック

結線しましたらツールバーからモデルチェックを行います。するとエラーとなり下のようなメッセージが表示されます。

component boundary contains the definition of a partial class Medium. Please redeclare it to any package compatible with Modelica.Media.Interfaces.PartialMedium.

おそらく、流体が何かを指定していないので計算できていないのだと推測できます。ただダイアグラムビューからは流体を指定できるそれらしい箇所が見つかりませんでした。今回これが王道かどうかはわかりませんが、ModelicaのExampleなどから下記のような対応を実施しました。

エラーになったとき、今回のモデルをテキストビューで確認すると下記のようになっていると思います。

model PIDtest
  Modelica.Fluid.Sources.Boundary_pT boundary(redeclare package Medium = Medium, nPorts = 1, p = 2.5e6) annotation(
    Placement(visible = true, transformation(origin = {-64, -14}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
  Modelica.Fluid.Valves.ValveLinear valveLinear1( dp_nominal = 100000, m_flow_nominal = 40)  annotation(
    Placement(visible = true, transformation(origin = {-10, -14}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
  Modelica.Fluid.Sources.Boundary_pT boundary1(nPorts = 1, p = 1e6) annotation(
    Placement(visible = true, transformation(origin = {84, -16}, extent = {{-10, 10}, {10, -10}}, rotation = 180)));
  Modelica.Fluid.Sensors.MassFlowRate massFlowRate1 annotation(
    Placement(visible = true, transformation(origin = {34, -14}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
  Modelica.Blocks.Sources.Step step1(height = 1, offset = 0, startTime = 5)  annotation(
    Placement(visible = true, transformation(origin = {-34, 26}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
equation
  connect(massFlowRate1.port_b, boundary1.ports[1]) annotation(
    Line(points = {{44, -14}, {74, -14}, {74, -16}, {74, -16}}, color = {0, 127, 255}));
  connect(valveLinear1.port_b, massFlowRate1.port_a) annotation(
    Line(points = {{0, -14}, {24, -14}, {24, -14}, {24, -14}}, color = {0, 127, 255}));
  connect(boundary.ports[1], valveLinear1.port_a) annotation(
    Line(points = {{-54, -14}, {-20, -14}, {-20, -14}, {-20, -14}}, color = {0, 127, 255}, thickness = 0.5));
  connect(step1.y, valveLinear1.opening) annotation(
    Line(points = {{-22, 26}, {-10, 26}, {-10, -6}, {-10, -6}}, color = {0, 0, 127}));
  annotation(
    uses(Modelica(version = "3.2.2")));
end PIDtest;

これに対して。まず冒頭でpackage Medium = Modelica.Media.Water.ConstantPropertyLiquidWater;と宣言することで、今回の流体が水だと宣言します。 次に、各機器のパラメーターにredeclare package Medium = Mediumを追加します。 すると以下のようになります。

model PIDtest
 package Medium = Modelica.Media.Water.ConstantPropertyLiquidWater;
  Modelica.Fluid.Sources.Boundary_pT boundary(redeclare package Medium = Medium, nPorts = 1, p = 2.5e6) annotation(
    Placement(visible = true, transformation(origin = {-64, -14}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
  Modelica.Fluid.Valves.ValveLinear valveLinear1(redeclare package Medium = Medium, dp_nominal = 100000, m_flow_nominal = 40)  annotation(
    Placement(visible = true, transformation(origin = {-10, -14}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
  Modelica.Fluid.Sources.Boundary_pT boundary1(redeclare package Medium = Medium, nPorts = 1, p = 1e6) annotation(
    Placement(visible = true, transformation(origin = {84, -16}, extent = {{-10, 10}, {10, -10}}, rotation = 180)));
  Modelica.Fluid.Sensors.MassFlowRate massFlowRate1(redeclare package Medium = Medium) annotation(
    Placement(visible = true, transformation(origin = {34, -14}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
  Modelica.Blocks.Sources.Step step1(height = 1, offset = 0, startTime = 5)  annotation(
    Placement(visible = true, transformation(origin = {-34, 26}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
equation
  connect(massFlowRate1.port_b, boundary1.ports[1]) annotation(
    Line(points = {{44, -14}, {74, -14}, {74, -16}, {74, -16}}, color = {0, 127, 255}));
  connect(valveLinear1.port_b, massFlowRate1.port_a) annotation(
    Line(points = {{0, -14}, {24, -14}, {24, -14}, {24, -14}}, color = {0, 127, 255}));
  connect(boundary.ports[1], valveLinear1.port_a) annotation(
    Line(points = {{-54, -14}, {-20, -14}, {-20, -14}, {-20, -14}}, color = {0, 127, 255}, thickness = 0.5));
  connect(step1.y, valveLinear1.opening) annotation(
    Line(points = {{-22, 26}, {-10, 26}, {-10, -6}, {-10, -6}}, color = {0, 0, 127}));
  annotation(
    uses(Modelica(version = "3.2.2")));
end PIDtest;

これでシミュレーションできるようになります。なぜredeclare~が必要なのかはわかりません……

シミュレーション

ツールバーからシミュレーションを行うことで下図のように無事シミュレーションすることができました。 開始から5秒後にバルブが全開になり、600 kg/sの流量で水が流れる様子が確認できます。

f:id:Otepipi:20180729210145p:plain

無事にフィードバック制御の前段階までできましたので今日はここまでにしたいと思います。