MBD软件开发之Function call trigger与Enable

MBD模型化开发中,Function Call Trigger触发 (包括Function Call,If Else, For, While Action等)是十分常见的存在,广泛用于控制时序调度和迭代执行。本质上在图形化编程中,是程序块调用的一种表现形式而已。

Function Call 和 Enable 两个,外观傻傻分不清楚,而且经常情况是用哪个都能表达功能。但其实质意义完全不一致:

  • 驱动 Enable SubSystem 的是一个真实信号,一个 On/Off 的布尔量;
  • 驱动 Function Call SubSystem的仅仅是一个调用关系,并非真实信号
  • Enable只是影响下游系统能不能执行的一个状态,而具体何时执行是看什么时候被Call的;虽然没有显式的Call,其实相当于每个步长有一个隐含的Call在执行它;
  • Function Call则直接代表了下游系统的代码马上被执行。


啰嗦一通,无非是想说明,下面要着重讨论的 Function Call与Enable有点像,但绝不可混为一谈。

实质上,每一个模块,每一个SubSystem,即使头上没顶着一个显式的Function Call,实际上也相当于受隐含的Function Call控制,这个隐含Function Call,就是Simulink内核根据数据流等等关系,自动确定的执行调度。

在Simulink和Stateflow中,与Function Call相关的有些配置项常出现,随便举几个常见例子。

  • 触发式系统中Trigger的设置 States When enabling:

  • Outport 的输出值:

  • Stateflow中的bind操作

这些情况下,一般来说都会跟着感觉走,而且一般也都能工作。所以时间虽然很久,对其所以然始终是不甚清晰。

最近遇到一个状态和调度稍微复杂点的系统,受这些个配置影响很大。遂花点时间实证了一把并写个记录。

为了把事情讲清楚,先说结论,然后对照结论再看下面的实证过程是否靠谱。

>>>结论

实际模型结构变化万千,基本原则并不复杂。

任何一个Function Call,都代表一个调度关系;但实际上分两类,绑定源头的和不绑定源头的。打个比方,就好像人民解放军只能听党的指挥,这就叫绑定源头的;而警察叔叔任何人打110都能调动,这就叫不绑定源头的。

接下来的问题是,在Simulink的世界里,这个源头就是“状态”。Simulink/Stateflow环境下,最一般的Stateflow中有状态;另一种情况一个UnitDelay模块保存上一时刻值,也是一个状态量。

那么更准确的表述是:

  • 在Simulink/Stateflow里,Function Call可以与一个有限状态绑定;或者不绑定(或者说与一个始终激活Active的状态绑定);
  • 如果绑定,那么Function Call专属于这个状态,其下游的模块(以及再下游的次级模块)的内部状态量与源状态是否激活休戚与共;
  • 如果不绑定(实质相当于与一个始终激活的状态绑定),则这个Function Call并不专属于任何状态,或者说任何状态都可以成为其源状态;
  • Simulink中的各种设置,例如对状态或者输出进行Reset或者Held,都是针对源状态绑定的情况;对不绑定的情况,怎么设置都不会有影响,因为道理上就没有源状态,也就无谓源状态的变化。
  • 对于 Enable SubSystem出来的Function Call,实质上隐含着与这个SubSystem的Enable/Disable状态绑定的,用Stateflow表达出来相当于:

>>>验证

测试模型的结构如下图。最上面的调度,用Stateflow实现,状态A和状态B各25步长,其中仅状态A产生Function Call“E”。被调的系统里只做个简单的计数累加,以其输出值作为观察对象。

(仿真步长 0.01s,Solver: Discrete)

图中3个红色圈出来的位置,按照下面的表排列组合,观察输出的结果(篇幅问题,下面只贴第1个端口的图,足够说明问题了,其它端口请自行仿真)

测试序号

bind

Trigger

Outport

#1

Yes

Reset

Reset

#2

Yes

Reset

Held

#3

Yes

Held

Held

#4

Yes

Held

Reset

#5

No

Held

Reset

#6

No

Reset

Reset

#7

No

Held

Held

#8

No

Reset

Held

  • #1

bind+Trigger Reset因此每次进入状态A后,受Function Call E影响的子系统都复位到初始值0开始;

Outport Reset,因此每周期里,在25Step处跳出状态A时,Function Call E影响下的输出端口就会复位到0;

  • #2

bind+Trigger Reset,因此每次进入状态A后,受Function Call E影响的子系统都复位到初始值0开始;

Outport Held,因此每周期里,在25Step处跳出状态A时,Function Call E影响下的输出端口仍会保持原值;

  • #3

bind+Trigger Held,因此每次进入状态A,受Function Call E影响下的子系统会保留上次Inactive退出的状态,并在此基础上继续运算;

Outport Held,因此每周期里,在25Step处跳出状态A时,Function Call E影响下的输出端口仍会保持原值;

  • #4

bind+Trigger Held,因此每次进入状态A,受Function Call E影响下的子系统会保留上次Inactive退出的状态,并在此基础上继续运算;

Outport Reset,因此每周期里,在25Step处跳出状态A时,Function Call E影响下的输出端口就会复位到0;

  • #5-8

因为Function Call E与源状态A之间并无绑定(bind)关系,是否在状态A中对Function Call E下游的系统状态没有影响。

此外,为搞得更清楚些,多做一步工作,把Stateflow换成同样周期和占空比的 Enable SubSystem+Function Call的形式:

得到的结果与 #1-#4完全一致,原因见前面的分析。

>>>代码生成

对于用Simulink/Stateflow做嵌入式控制系统开发的工程师而言,仿真结果其实倒非最重要,生成的代码是否有效才是关键。于是再多探究一步。

生成的代码未经配置,比较晦涩,详细的意义就不解释了,看个大概意思就好。

下面图中左边是Outport Held,右边是Reset。右边生成的代码中,在FunctionCallSubsystem2Disable函数中多了一句重新赋值的语句。

下面图中左边是Trigger Held,右边是Reset。右边生成的代码中,会多调用一次FunctionCallSubsystem2的Initialize函数中。

  • 17
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

电力电子空间

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值