如果定期调用状态机(在MatLAB Simulink或PLC程序中),是否可以在同一plc周期/ simulink步骤中在状态之间进行转换?
在Twincat 3(PLC)中,有以下选项“内部循环”: https://infosys.beckhoff.com/content/1033/tf1910_tc3_uml/63050395607969163.html
使用此选项是否有任何限制?系统仍然可以实时运行吗?
编辑,因为我不能写很长的评论:
1-在您的示例中,如果状态为“循环中”状态,并负责生成电动机的设定点,直到达到所需的设定点(因此会花费很多时间)。程序可能在这种状态下被“卡住”,从而导致任务超限,并违反了实时限制。 建议的解决方案:控制最大变量“最大DO循环调用次数”:https://infosys.beckhoff.com/english.php?content=../content/1033/tf1910_tc3_uml/63050395607969163.html&id=,用于此状态的调用次数,还是可以/更好地在单独的PLC任务中实现此任务?
2-对于没有周期内状态的状态图,该程序将停止执行该图,保存状态,并在对当前活动状态进行一次评估后执行其余程序。 如果图表中的所有状态均为“循环中”,程序将在何处停止执行图表以执行其余程序?
唯一的解决方案是使某些状态处于非循环状态,并确保它们达到足够快的速度而不会导致任务超限吗?
答案 0 :(得分:1)
是的,这是可能的。它完全取决于您如何定义状态机代码。 Filippo的答案解释了如何使用“内部循环”选项。
另一种看待这种情况的方式是,在结构化文本中,通常使用Case结构实现状态机。
要在一个周期内具有多个状态,您将需要两个Case结构或两次运行相同的Case结构(例如,使用For或While循环)
例如,假设您想在移至错误状态后立即对错误状态采取行动。您的第一个Case语句会将状态转换为“错误”。
在第二个Case语句中,您将检查“错误”状态并立即采取措施。
答案 1 :(得分:0)
使PLC具备实时功能,所以要回答您的最后一个问题,是的,无论您使用哪种编程语言,系统都具有实时功能。
使用tf1910扩展名时,将在后台生成Beckhoff运行时的代码,该代码将每x ms 循环运行一次,具体取决于您的配置。
将Cycle-Internal操作转换为结构化语言可能如下:
想象一下,您有一个扩展了 StateMachine 软件组件的 Motor 软件组件。
StateMachine定义不同的(原始)状态,例如 Init,Ready,Busy,Idle,Error等。
V Boot()
|
|
<Init>
|
|
| Start()
|
|
<Ready> -----------<--------------+-------------<-----------+
| | |
| | |
| Execute() | |
| | |
| | |
| | Reset() |
<Prepare> | |
| | |
| | |
| | |
Wait() | Fault() | |
<Waiting> ---<-------->--- <Busy> ----------->----------- <Error> |
EndWait() | |
| |
| |
| |
| Done() |
| |
| |
| |
<Idle> ---------------------->------------------------------+
结果,电机也继承了这些状态。
现在,如果 Motor 处于 Init 状态,则调用Start()方法会将状态从 Init 更改为准备好了。
根据程序的体系结构,此更改可能会对程序流程产生直接影响(这意味着在当前周期)或在下一周期。 / p>
比方说,我们的StateMachine功能块将 Cycle-Internal 实现为布尔输入变量: bCycleInternal 它是当前状态,是一个枚举变量: eStateMachine
我们也可以说,根据eStateMachine的值(即状态机的当前状态),StateMachine调用特定的方法(例如,对于 Init Init(),对于 Ready Ready()等)
当bCycleInternal为true并且Start()方法将当前状态从 Init 更改为 Ready 时,Ready()在调用之后直接 相同周期中的Init()。 否则,如果bCycleInternal为false,则使用Start()方法Ready()将状态机的状态(或eStateMachine的值)从 Init 更改为 Ready 时。被称为下一个周期之前。