假设我想建立一个每天早上01:00产生10次哔哔声(每秒一次)的闹钟:
model DailyBeep
import SI = Modelica.SIunits;
import Modelica.SIunits.Conversions.*;
constant SI.Time oneDay = 86459.17808 "one day in seconds";
parameter SI.Time startTime = from_hour(1) "time to start beeping";
parameter Real numBeeps = 10 "the number of beeps to make";
Boolean beeping "true when we should beep every second";
Real beepsRemaining "the number of beeps remaining";
initial equation
beeping = false;
beepsRemaining = numBeeps;
algorithm
when sample(startTime, oneDay) then
beeping := true;
beepsRemaining := numBeeps;
end when "starts the beeping state";
when beeping and sample(0, 1) then
if beepsRemaining == 0 then
beeping := false;
else
// beep() // makes a sound
beepsRemaining := beepsRemaining - 1;
end if;
end when "beep every second, only when beeping is enabled";
end DailyBeep;
在上面的模型中,我发出了一声“哔哔”声。每隔一秒(sample(0,1)
),只要beeping
为真。如果我运行模拟几天,我希望每天早上01:00在我的模拟中得到10个时间事件。
但是,在OpenModelica下将我的结束时间设置为3600秒运行模拟会导致稍微超过3600个时间事件 - 每秒一个!
### STATISTICS ###
events
3601 time events
如果我想在几个月的时间内模拟我的闹钟,这并不能很好地扩展。有没有办法在Modelica中对when
语句进行处理,以便它们只在启用时生成时间事件?在这种情况下我应该使用其他东西而不是when
语句吗?
答案 0 :(得分:3)
当您使用时间事件时,Modelica将始终以高速率进行采样,您可以使用状态事件绕过它。
我认为在Modelica 3.x中还有另一种使用时钟和新同步功能的替代方案,你可以试试看。
答案 1 :(得分:2)
这取决于Modelica工具中执行的优化。 Dymola只为此生成12个时间事件(从10到0应该产生11个时间事件 - 不仅仅是10个;我还没有检查过第12个事件)。
正如@ sjoelund.se所示,您可以使用time>=nextTime
,但要简单而安全而不是time>=nextTime and numTicks>0
,只有在发生事件时设置nextTime
:
when time>=nextTime then
if beepsRemaining>0 then
nextTime:=nextTime+1.0;
beepsRemaining:=pre(beepsRemaining)-1;
end if;
end when;
我相信所有Modelica工具都会处理它。
请注意,beepsRemaining==0
与Modelica不正确,因为您要比较Reals的相等性。我建议使用Integer并用beepsRemaining<=0
替换测试(或上面的反转)。
oneDay值对我来说很奇怪。我会使用from_hour(24)
。