技术论坛

 模式状态机的一种设计方法

返回主题列表
作者 主题
xiatianyun
奇侠

经验值:5075
发帖数:794
精华帖:10
楼主    2024-01-17 22:39:32
主题:模式状态机的一种设计方法 精华帖 

上个月刚接触西门子OMAC的PACLML示例,我试着做了个程序来验证,效果不错。


先来说说示例的观感,个人认为这仅仅是西门子为了实现模式状态机的一个小示例,不算可以直接使用的东西,当然离库很远。示例设计得没有什么章法,仅仅实现了而已,设计细节没有多少值得借鉴得地方。

最大的用处是让我了解了什么是模式状态机,当然了,肯定也只是PACKML的一部分内容。我不了解PACLML,只是从一些资料知道PACKML其实是涵盖了整个项目结构的内容,不光是模式状态机了。


以前也做过状态机,使用Case对不同状态进行处理和转移。最大问题是入口case比较难以把握,稍不留神就会错误触发。状态的转移也完全依赖现有状态里面的判断。具体如何不便不好描述。


说示例没有多少借鉴的地方其实有点昧良心了,给我最大的启示是状态转移和状态处理是分离的。也许最复杂的部分是状态的收集和处理,示例没有这方面的内容。我本人项目中也没有做专门的工作,只是使用了原有底层模块的状态简单处理。


最容易实现的是状态转移了,所以我就做了最容易的部分。


并且实现后发现其实是完全可以适用于很多离散行业场景的。这里记住,PACKML是包装行业的规范,它定义的状态并不适用于其他行业。其他行业有各自的状态定义,这个自己来。


示例对于状态的记录采用字符串,包括命令、SC,这个我觉得使用数值更好,占用空间少,易于编程。


至于诊断信息则用于调试过程,我把诊断和状态转移块分离了,需要诊断信息可以用单独的块接住状态机传出的诊断信息即可,多少条任意。但状态机只传出当前的信息,并不保存之前的信息,并且都是编码信息,需要诊断块自行解码。


当调试好后,诊断块都可以在项目中删除不用。


先记到这,有时间再写具体实现。

------------------------------------------------------

2024.01.23

本来已经意兴阑珊了,可偏偏是个精,都还没开始呢。

好吧,只能继续了。


资料里面大量篇幅关于高层设备如何划分之类的,看看就可以了。有机会从整体来设计当然不一样了,但很多时候我们都只是一个螺丝钉,并不注重整体架构。有时是形势逼人,有时觉得自己可以整体把控了,无奈这个整体又太过渺小。

只记得资料里有句话很有意思,大意是如果你不能正确划分设备编号的话,那就从底层开始编号吧,而不是一开始就从高层来。对,正解。


放张图:


这是西门子1847里面的截图,当然我没有1847,而是从壶琰棠发布的视频解的图。

具体我就不分析了,只看我的结论:

1、有一个全集,包括了所有的状态。

2、全集不一定非得有一个模式对应,可能有也可能没有。

3、模式1向模式2转移需要的条件:模式2里面存在当前模式1的当前状态A.

4、状态是有等级的,L0<L1<L2......,高等级可以超越低等级。也就是说处于高等级时可以屏蔽低等级的命令或SC。

5、命令和SC其实没有区别,我一律称作SC。资料里面SC叫做状态完成state complete,我叫做状态改变

state change.

6、......


如何设计:

仔细观察Excute状态:

1、有三个出口、三个入口。

2、如果用链表表示,则入口可以不用关心,只需要出口。不过博途不支持链表(指针......),改用数组,一样的道理。

3、数组的单元是个结构:状态本体、出口。

4、状态是个整数,表示状态标识,出口也是个整数(后来改用word)。


看级别,把级别也看做状态,则和普通状态没有区别。

只是级别另外做成单独的数组,单元类型和普通状态是同一个类型。


如果这样,如何表示从一个级别的状态转移到另一个级别的状态呢?

后来设计成处理出口SC编码,做成Word类型,高字节表示级别,低字节表示SC标识。

范围是不是够呢?一个字节表示256种状态,应该够了吧。特别是级别。

预定义四个出口够了吧?做成符号常量不是更方便些。这样,模式数量、状态数量、级别数量、SC数量等等都如此定义。


这样,答题设计就有了,总体上变成了填表了。

逻辑设计很简单,不需要多少代码。


但是工作量大的是诊断工作。

如何定义呢?我也是边实现边定义,没有事先定义。现在还没有机会整理诊断编码。

但是有一点是肯定的,就是诊断大多是给调试使用,给人看的,大量的文本占用空间,就不集成在模式状态机里面了,模式状态机仅输出诊断信息,只当前诊断,不存之前的信息。


如果需要就用单独的块接住往诊断缓冲区放。


工作流程就是画出状态图:不同模式的状态图,模式少的话就用一张图。然后填数字,然后填表。需要把SC编码变成16进制码,借助Excel来做容易些。

放张我设计过程中的截图,上面的SC编码没有级别编码,需要进一步转换。




配置表:

1、诊断文本列表,可以在PLC,也可以在HMI中处理,随便,其实调试后可以不用。


2、模式状态机配置表


3、状态或级别配置表内容:


上图以级别表为例,状态表类似。

当处于某个状态时,需要和配置表中SCCode一致的SC才能使状态发生转移,不符合则会被拒绝。


逻辑处理部分,初始化检查表内容是否适合,我只设计了检查SCCode和Next是否配套,接着生成模式Pattern,也即各个模式下存在全集状态的一个记录,是个位域,DWord。对了,我都忘了我设计的项目状态超过32个了,这个咋整?


初始化后根据传入的SCCode先在级别表里面检查是否有合适当前级别的SC,从高级别开始到当前级别终止检查。如果有则直接转入Next状态,没有则继续在当前State里面检查。

都没有则拒绝执行转移。


代码简单就不放了。


现在的重点是如何设计好的状态收集、如何处理才能使SCCode不会被错误覆盖造成状态不能转移。


------------------------

后记:

如果一个项目里有多个状态机,使用全局UDT和全局常量就不合适了。比如说一个状态机比较小,就需要和最大的状态机一样大的配置表,比较占空间。


我的做法是把状态机集成到模块中,不是单独模块。配置表也集成到模块中,全局常量变成了局部常量了,UDT也变成匿名结构。




您收到0封站内信:
×
×
信息提示
很抱歉!您所访问的页面不存在,或网址发生了变化,请稍后再试。