热力控制

在这一章中,我们将考虑另一个系统。这个系统包括了受控对象、控制器、传感器和执行器。这个应用场景是分为三区的房子的热控制。受控对象将是房子本身。传感器为温度传感器。执行器则为房内的火炉。利用这些模型,我们将探索不同的控制策略。

我们也将如同上节一般,遵循架构驱动的方法来构建该系统。然而,在开始时我们会使用一组接口。然后,在讨论其局限性后,我们重新使用不同的方法,以获得更大的灵活性。

初步方法

架构

让我们从下列架构开始:

Initial architecture

我们在这里看到了和上一节同样的基本组件:受控对象模型、传感器、控制器和执行器。其实,这是一个非常典型的架构。在某些情况下,人们可以受控对象模型分解成几个子系统和/或加入多个控制器和控制回路。只是,许多闭环系统的控制问题具有类似的结构。

各种应用里的不同点一般在于,上述部件之间交换的特定信号有不同。在本例里,我们可以从上述结构原理图上看出,接口定义如下:

  • 执行器接收到目标温度,然后通过与受控对象的热连接注入热

  • 传感器模型也带有热连接器(和受控对象相连)。而且它还包含了测量温度的输出信号。

  • 受控对象有两个热连接。一个热连接代表炉子热量和受控对象的连接。另一个是传感器的位置。

  • 控制器以(从传感器)测得的温度作为输入,并输出一个指定热输出(到执行器)

此基本系统的Modelica代码如下:

within ModelicaByExample.Architectures.ThermalControl.Architectures;
partial model BaseArchitecture "A basic thermal architecture"
  replaceable Interfaces.PlantModel plant
    annotation (Placement(transformation(extent={{-10,-10},{10,10}})));
  replaceable Interfaces.ControlSystem controller
    annotation (Placement(transformation(extent={{-10,30},{10,50}})));
  replaceable Interfaces.Sensor sensor
    annotation (Placement(transformation(extent={{32,-10},{52,10}})));
  replaceable Interfaces.Actuator actuator
    annotation (Placement(transformation(extent={{-50,-10},{-30,10}})));
equation
  connect(plant.room, sensor.room) annotation (Line(
      points={{10,0},{32,0}},
      color={191,0,0}, smooth=Smooth.None));
  connect(sensor.temperature, controller.temperature) annotation (Line(
      points={{53,0},{70,0},{70,40},{12,40}},
      color={0,0,127}, smooth=Smooth.None));
  connect(actuator.furnace, plant.furnace) annotation (Line(
      points={{-30,0},{-10,0}},
      color={191,0,0}, smooth=Smooth.None));
  connect(controller.heat, actuator.heat) annotation (Line(
      points={{-11,40},{-70,40},{-70,0},{-52,0}},
      color={0,0,127}, smooth=Smooth.None));
end BaseArchitecture;

初始实现

受控对象

受控对象的模型如下:

Three zone plant model

我们在这里可以看到,其中暖炉加热的区域与测温的第三区是分隔开的。暖炉模型是一个简单的热源:

A conventional actuator

执行器以指令热量水平作为输入,然后注入相应的热量到系统里。

类似地,传感器也很简单:

A conventional sensor

这种传感器不引入任何误差。相反,这个传感器提供精确温度这一连续信号。

我们将使用以下PI控制器来控制温度:

The control system

初步结果

将上述实现填充入架构,模型看起来如下:

Initial system configuration

请注意各个子系统的图标已经改变了。这是因为当我们进行了redeclare后,子系统便会使用相关联的新类型的图标。这个系统的Modelica语言代码是:

within ModelicaByExample.Architectures.ThermalControl.Examples;
model BaseModel "Base model using a conventional architecture"
  extends Architectures.BaseArchitecture(
    redeclare Implementations.ThreeZonePlantModel plant(
      C=2, G=1, h=2, T_ambient=278.15),
    redeclare
      ModelicaByExample.Architectures.ThermalControl.Implementations.ConventionalPIControl
      controller(setpoint=300, T=1, k=20),
    redeclare Implementations.ConventionalActuator actuator,
    redeclare Implementations.ConventionalSensor sensor);
end BaseModel;

如果我们对系统进行仿真,会得到以下的结果:

../../../_images/TCB.png

我们可以看到,这种方法效果非常好。实现这种程度控制所需的暖炉热量如下:

../../../_images/TCBh.png

开关控制

到目前为止,这种做法好像已经相当成功。我们有一个很好的架构,我们可以用其来考虑不同的执行器、传感器、控制器甚至受控对象模型。我们开发的控制系统在这种情况性能似乎不错。

但有一点值得注意的是,在这种情况下暖炉热量必须为连续。不过,家庭取暖系统通常不采用这种类型的控制策略。相反,这类系统倾向于使用所谓的开关控制。在这种控制策略里,暖炉是非“开”即“关”。

我们有这个灵活的架构。为了解决这个问题,我们也许应该创建控制器和执行器模型的实现。其中控制器命令是一个布尔值,去指示是否暖炉的开启或关闭。但是,如果我们开始这么做的话,很快就会遇到以下问题:

A control strategy with on/off control

需要注意的是,从我们的控制器输出Boolean值,但我们的ControlSystem接口里的命令信号heat却为Real值。我们在执行器处也有同样的问题:

该接口提供Real值的执行机构。但我们再一次看到,如果暖炉要求“开启”或“关闭”命令时,我们就有不匹配。

所以,问题就变成:如何处理不同子系统要求不同接口这种情况

可扩展方法

expandable连接器定义解决了这个问题。通过这种方法,不论控制策略输出BooleanReal,我们的子系统接口都不会改变。在这种情况下,改变的是连接器实例中的内容。

要了解这些expandable连接器是如何工作的,我们将重新设计架构模型。新架构包括expandable连接器,然后我们会考虑架构模型如何可用于连续以及“开关”的控制策略。

可扩展连接器

让我们可以构造更灵活架构模型的关键功能是expandable connector。举个例子,先前我们定义了如下的Actuator接口:

within ModelicaByExample.Architectures.ThermalControl.Interfaces;
partial model Actuator "Actuator subsystem interface"

  Modelica.Blocks.Interfaces.RealInput heat "Heating command" annotation (
      Placement(transformation(
        extent={{-20,-20},{20,20}},
        origin={-120,0})));

  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_b furnace
    "Connection point for the furnace"
    annotation (Placement(transformation(extent={{90,-10},{110,10}})));
end Actuator;

此接口包含两个连接器,heat连接器和furnace连接器。furnace连接器为热连接器,它使暖炉与受控对象产生热相互作用。heat连接器为来自控制器的Real值输入信号。该信号指定所需的热量输出大小。事实上,在我们切换到需要Boolean信号的控制方法时,接口模型的上述信号为Real值这点正是问题所在。为了解决这个问题,我们将使用下面的接口定义执行器:

within ModelicaByExample.Architectures.ThermalControl.Interfaces;
partial model Actuator_WithExpandableBus
  "Actuator subsystem interface with an expandable bus"

  ExpandableBus bus
    annotation (Placement(transformation(extent={{-110,-10},{-90,10}})));

  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_b furnace
    "Connection point for the furnace"
    annotation (Placement(transformation(extent={{90,-10},{110,10}})));
end Actuator_WithExpandableBus;

这里我们看到furnace连接器仍然存在。但是heat连接器已经不见了。相反,它已被替换为新的连接器实例:类型为ExpandableBusbusExpandableBus连接器的定义是:

within ModelicaByExample.Architectures.ThermalControl.Interfaces;
expandable connector ExpandableBus "An example of an expandable bus connector"
end ExpandableBus;

换句话说,连接器是空的。但重要的是expandable限定词的存在。如果总线总是需要某些特定信号,这些信号就应该列在其连接器的定义之内。而事实上,ExpandableBus类没有任何变量或子连接器。这意味着总线内的信息量没有最低要求。不过总线可以通过扩展来包含更多的信息。

当然,我们可以使用继承来添加新信号。但是,继承会引入了一个新类型。而接口定义中使用的类型规定了连接器的类型。所以,通过继承并不能真正有效创造更复杂的接口。

注意,Modelica内并有一个没有正式的“总线”定义。这个术语经常用于上述情况去表示携带多条信息的连接器。

可扩展连接器的功能比较特殊。可扩展总线的信号由其上的连接决定。通过向可扩展总线添加连接,信号便会隐含地添加在连接器上。这时的Modelica编译会观察与上述连接器相连的所有连接器,并将这些连接器全部扩展。这样一来,所有的连接器才可以互相匹配。稍后,我们将进一步介绍上述过程。但在这之前,我们需要首先有讨论的实际模型。

受控对象模型的接口没有受使用expandable连接器的影响。但传感器和控制器的接口如下:

within ModelicaByExample.Architectures.ThermalControl.Interfaces;
partial model Sensor_WithExpandableBus
  "Sensor subsystem interface using an expandable bus"

  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a room
    "Thermal connection to room"
    annotation (Placement(transformation(extent={{-110,-10},{-90,10}})));

  ModelicaByExample.Architectures.ThermalControl.Interfaces.ExpandableBus bus
             annotation (Placement(transformation(extent={{90,-10},{110,10}})));
end Sensor_WithExpandableBus;
within ModelicaByExample.Architectures.ThermalControl.Interfaces;
partial model ControlSystem_WithExpandableBus
  "Control system interface using an expandable bus connector"
  ExpandableBus bus annotation (Placement(transformation(extent={{-10,-110},{10,
            -90}}), iconTransformation(extent={{-10,-110},{10,-90}})));
end ControlSystem_WithExpandableBus;

请注意控制器接口变得多么简单。这是因为通过使用expandable连接器,我们可以把从传感器接收到的温度测量以及发送到执行器的热量命令放在在同一总线上。因此,我们只需要一个接口。开发人员仍可以直接使用多个总线去组织信号,使信号更好地反映物理存在或避免混乱。在此,我们使用单一连接器的目的纯粹是为了告诉读者这样做是可能的。

使用可扩展的连接器,我们可以创建以下改进版的架构:

Expandable architecture

可扩展实现

有了这个更灵活的架构,让我们先重建原有的连续控制系统配置:

Continuous control using the expandable architecture

若我们绘制这个系统的仿真结果,会得到如下的响应:

../../../_images/TCE.png

请注意,所测温度对应于信号controller.bus.temp。其中bus是可扩展的连接器的一个实例。进一步回忆的ExpandableBus定义不含有一个叫temperature的信号。所以现在的问题是,该信号是怎么去到连接器上的?问题就出在传感器模型的实现。传感器模型的框图如下:

Temperature sensor model using expandable bus

对应的Modelica代码是:

within ModelicaByExample.Architectures.ThermalControl.Implementations;
model TemperatureSensor "Temperature sensor using an expandable bus"
  extends Interfaces.Sensor_WithExpandableBus;
protected
  Modelica.Thermal.HeatTransfer.Sensors.TemperatureSensor sensor
    annotation (Placement(transformation(extent={{-10,-10},{10,10}})));
equation
  connect(sensor.T, bus.temperature) annotation (Line(
      points={{10,0},{100,0}},
      color={0,0,127},
      smooth=Smooth.None));
  connect(room, sensor.port) annotation (Line(
      points={{-100,0},{-10,0}},
      color={191,0,0},
      smooth=Smooth.None));
end TemperatureSensor;

重要的是高亮显示的那行。

在该图中,我们可以看到,温度传感器组件的输出信号连接在总线上。但是,我们观察connect声明可以看出,信号不仅仅是连接到总线上。此信号连接在总线上一个名为temperature的量上。temperature连接器并不存在于ExpandableBus的定义里。相反,它是由connect语句本身创建的!这也恰恰是expandable限定词所允许的。

一般情况下,我们不希望所有连接器均为expandable。若我们先验地知道所有信号的的名称和类型,那么就应该明确的列出。这样做会允许Modelica语言的编译器进行一些重要的检查,以确保模型的正确性。值得注意的是,添加所述expandable限定词到连接器会使不小心创建无用信号成为可能(例如由于打错字)。这种错误在没有添加限定词的时候,本来可以由编译器找出。

重配置

现在,我们已经演示了如何使用可扩展的方法对系统的连续控制版本进行建模。现在,让我们重新关注到“开关”版本。

我们已经看到如何配置可扩展连接器版的温度传感器子系统。剩下的就是控制器和执行器的模型。执行器模型框图如下所示:

Actuator attached via expandable connector

同样,看Modelica的代码时要注意对bus连接器信号的引用:

within ModelicaByExample.Architectures.ThermalControl.Implementations;
model OnOffActuator "On-off actuator implemented with an expandable bus"
  extends Interfaces.Actuator_WithExpandableBus;
  parameter Real heating_capacity "Heating capacity of actuator";
protected
  Modelica.Thermal.HeatTransfer.Sources.PrescribedHeatFlow heater
    annotation (Placement(transformation(extent={{-10,-10},{10,10}})));
  Modelica.Blocks.Math.BooleanToReal command(realTrue=heating_capacity,
      realFalse=0)
    annotation (Placement(transformation(extent={{-60,-10},{-40,10}})));
equation
  connect(heater.port, furnace) annotation (Line(
      points={{10,0},{100,0}}, color={191,0,0},
      smooth=Smooth.None));
  connect(command.y, heater.Q_flow) annotation (Line(
      points={{-39,0},{-10,0}}, color={0,0,127},
      smooth=Smooth.None));
  connect(command.u, bus.heat_command) annotation (Line(
      points={{-62,0},{-100,0}}, color={255,0,255},
      smooth=Smooth.None));
end OnOffActuator;

再次,注意强调的那行。该行引用bus连接器的名为heat_command的元素。和上面一样,该信号不存在于ExpandableBus的定义内。该信号是隐式创建的。因为它在上述高亮显示connect语句中被引用了。

由传感器模型我们可以看到,测得的温度输出到bus连接器的一个名为temperatureReal信号里。由执行器模型我们则看到,执行器需要的控制器命令来自一个名为heat_commandBoolean信号。因此,我们应该会看到控制器模型使用这两个信号。控制器的框图如下:

PI controller connected to expandable bus

但图内不包含足够的细节去让我们得知所引用bus连接器信号的准确名称。为此,我们需要看实际的源代码:

within ModelicaByExample.Architectures.ThermalControl.Implementations;
model ExpandablePIControl "PI controller implemented with an expandable bus"
  extends Interfaces.ControlSystem_WithExpandableBus;
  parameter Real setpoint "Desired temperature";
  parameter Real k=1 "Gain";
  parameter Modelica.SIunits.Time T "Time Constant (T>0 required)";
protected
  Modelica.Blocks.Sources.Trapezoid setpoint_signal(
    amplitude=5, final offset=setpoint, rising=1,
    width=10, falling=1, period=20)
    annotation (Placement(transformation(extent={{-20,-40},{0,-20}})));
  Modelica.Blocks.Math.Feedback feedback
    annotation (Placement(transformation(extent={{30,-10},{10,10}})));
  Modelica.Blocks.Continuous.PI PI(final T=T, final k=-k)
    annotation (Placement(transformation(extent={{-10,-10},{-30,10}})));
equation
  connect(setpoint_signal.y, feedback.u2)
    annotation (Line(
      points={{1,-30},{20,-30},{20,-8}},
      color={0,0,127}, smooth=Smooth.None));
  connect(PI.u,feedback. y) annotation (Line(
      points={{-8,0},{11,0}},
      color={0,0,127}, smooth=Smooth.None));
  connect(bus.temperature, feedback.u1) annotation (Line(
      points={{0,-100},{60,-100},{60,0},{28,0}},
      color={0,0,0}, smooth=Smooth.None));
  connect(PI.y, bus.heat) annotation (Line(
      points={{-31,0},{-60,0},{-60,-100},{0,-100}},
      color={0,0,127}, smooth=Smooth.None));
end ExpandablePIControl;

再次,注意高亮行。这些connect语句不仅隐式将temperatureheat_command信号加入bus连接器,而且这两个名称传感器和执行器模型所需的信号相匹配

将所有子系统组合起来,我们得到系统的框图如下:

System using bang-bang control

系统模型的源代码甚为简单:

within ModelicaByExample.Architectures.ThermalControl.Examples;
model OnOffVariant "Variation with on-off control"
  extends ExpandableModel(
    redeclare replaceable
      Implementations.OnOffActuator actuator(heating_capacity=500),
    redeclare replaceable
      Implementations.OnOffControl controller(setpoint=300));
end OnOffVariant;
../../../_images/TCE_BB.png

然而,这些模型仍有一个问题。若我们观察暖炉的负载循环,就可以更清楚地看出这个问题:

../../../_images/TCE_BBh.png

这正是我们在前面小节滞回中展示的相同问题。正因为控制策略缺乏任何迟滞,我们才所看到的暖炉不断打开和关闭。如果再加上迟滞,控制器模型就变为:

Bang-bang controller with hysteresis

其余部分均保持不变。我们将使用相同的传感器和执行器模型。我们仍然使用相同的总线信号,因为这仍然是一个开关控制器。所以,系统级模型的唯一变化(相对于OnOffVariant模型)就是所使用的不同控制器模型。我们可以看到,Modelica的这些配置管理功能可以很好地在系统模型内表述这点:

within ModelicaByExample.Architectures.ThermalControl.Examples;
model HysteresisVariant "Using on-off controller with hysteresis"
  extends OnOffVariant(redeclare Implementations.OnOffControl_WithHysteresis
      controller(setpoint=300, bandwidth=1));
end HysteresisVariant;

使用迟滞控制,我们的模拟结果如下:

../../../_images/TCE_Hy.png

但最重要的区别是,滞后不会导致之前在开关控制器中看到的抖振:

../../../_images/TCE_Hyh.png

结论

这是我们能够使用Modelica配置管理功能,采取基于架构的方法来建立系统模型的第二个例子。当存在基于相同架构有很多变体需要分析时,架构方法非常有用。使用redeclare特性,能够容易地替换子系统的不同设计,或者对应不同的工程分析使用具有所需细节度的子系统。

在本例中,我们看到了对比标准连接器而言expandable连接器如何提供了更大的灵活性。不过,这也带有一定的风险。Modelica语言编译器通常会进行类型检查。但在使用了可扩展连接器后,类型检测就不那么严格了。