滞回

在本节中,我们将讨论滞回。这是为了理解某些特定的建模类型所必须的一个重要概念。还记得前面在状态事件的处理的讨论中,我们看到了抖动的例子。在那些例子里,我们可以使用noEvent运算符来解决抖动的问题。这是因为前述抖动的情况纯粹是由数值噪音产生的。那与行为的突然变化毫无关系。

在本节中,我们将考虑一个稍微极端的例子。请考虑以下模型:

model ChatteringControl "A control strategy that will 'chatter'"
  type HeatCapacitance=Real(unit="J/K");
  type Temperature=Real(unit="K");
  type Heat=Real(unit="W");
  type Mass=Real(unit="kg");
  type HeatTransferCoefficient=Real(unit="W/K");
  Boolean heat "Indicates whether heater is on";
  parameter HeatCapacitance C=1.0;
  parameter HeatTransferCoefficient h=2.0;
  parameter Heat Qcapacity=25.0;
  parameter Temperature Tamb=285;
  parameter Temperature Tbar=295;
  Temperature T;
  Heat Q;
initial equation
  T = Tbar+5;
equation
  heat = T<Tbar;
  Q = if heat then Qcapacity else 0;
  C*der(T) = Q-h*(T-Tamb);
end ChatteringControl;

倘若我们对模型进行仿真,便会得到下列结果:

../../../_images/CC1.png

然而,从开始仿真到产生上述结果却需要很长的时间。读者可以通过观察加热器在仿真中的输出,以进一步了解性能不佳的原因。

你会看到,在0.2秒左右之后,加热器不断地打开和关闭。这发生得如此频繁,以致于你要将图放大多次后才能看到这些转换。大量的状态转换让结果在正常比例下像一个填充满了的矩形。

这实际上是在控制系统中的现实问题。如果你仔细观察家里电炉的工作方式便会发现,电炉不会在高于或低于设定的室内温度时就不停地打开关闭。相反,电炉会等到温度变得高于或低于设定温度一定额度后,才会开始作出反应。

围绕着设定温度周围引入的“带”就叫做滞回。ChatteringControl模型的问题就在于它并没有任何滞回。相反,该模型不停地开关加热器以响应微乎其微的温度变化。

要建模滞回必须考虑一个棘手的问题,也就是滞回是“有状态的”。那么要确定系统的行为我们必须知道系统的历史。因此,我们并不能简单地使用if语句。其原因是if语句除去考虑系统的当前状态外,并不会考虑别的因素。为了实现滞回,我们需要用到when语句。考虑下列模型:

model HysteresisControl "A control strategy that doesn't chatter"
  type HeatCapacitance=Real(unit="J/K");
  type Temperature=Real(unit="K");
  type Heat=Real(unit="W");
  type Mass=Real(unit="kg");
  type HeatTransferCoefficient=Real(unit="W/K");
  Boolean heat(start=false) "Indicates whether heater is on";
  parameter HeatCapacitance C=1.0;
  parameter HeatTransferCoefficient h=2.0;
  parameter Heat Qcapacity=25.0;
  parameter Temperature Tamb=285;
  parameter Temperature Tbar=295;
  Temperature T;
  Heat Q;
initial equation
  T = Tbar+5;
  heat = false;
equation
  Q = if heat then Qcapacity else 0;
  C*der(T) = Q-h*(T-Tamb);
  when {T>Tbar+1,T<Tbar-1} then
    heat = T<Tbar;
  end when;
end HysteresisControl;

仔细观察上面的when语句,我们可以知道仅当 T>Tbar+1 或者 T<Tbar-1 变为真时,系统才会有响应。请注意,若上述表达式变为假,系统并不会有响应。这就是为何if语句在此并不适用。使用if语句或者if表达式时,只要条件表达式的值发生了变化,系统的行为就会改变。而使用when语句时,仅仅当条件为真时,when语句内的代码才会被激活。如果我们对该模型进行仿真并观察其温度,那么我们会看到温度保持在期望温度的滞环带内。

../../../_images/Hyst.png

更重要的是,我们观察系统输出的热量时便会发现,与先前例子不同的是,解热器的开与关之间有些许的时间间隔。

../../../_images/Hyst_Q.png

通过使用algorithm区域可以让实现滞回的逻辑变得更显然(正如我们前面在速度估测方法的讨论一样)。

model HysteresisControlWithAlgorithms "Control using algorithms"
  type HeatCapacitance=Real(unit="J/K");
  type Temperature=Real(unit="K");
  type Heat=Real(unit="W");
  type Mass=Real(unit="kg");
  type HeatTransferCoefficient=Real(unit="W/K");
  Boolean heat "Indicates whether heater is on";
  parameter HeatCapacitance C=1.0;
  parameter HeatTransferCoefficient h=2.0;
  parameter Heat Qcapacity=25.0;
  parameter Temperature Tamb=285;
  parameter Temperature Tbar=295;
  Temperature T;
  Heat Q;
initial equation
  T = Tbar+5;
  heat = false;
equation
  Q = if heat then Qcapacity else 0;
  C*der(T) = Q-h*(T-Tamb);
algorithm
  when T<Tbar-1 then
    heat :=true;
  end when;
  when T>Tbar+1 then
    heat :=false;
  end when;
end HysteresisControlWithAlgorithms;

注意这两个条件表达式是如何被分成两个独立的when语句的。如此这般,热源开闭的缘由也就显而易见了。由于这两个when语句都是对同一个变量heat进行赋值,因此两句都是在algorithm区域里定义的。