状态机在PLC中的应用
状态机在PLC中的应用,其中描述了操作票模式以及解释器模式
PLC基础
我们先来看一个简单的程序。
一个输入控制一个输出,这时候我们如果需要将输出保持,就需要一些改造。
这个时候我们发现当X0 OFF时,Y0还是处于ON状态,即达到了保持的目的。
但我们不能一直让Y0保持ON,还是需要对Y0的状态进行控制的,这时要加入一个断开的控制。
这就是比较经典的启动、保持、停止电路。
但是在PLC程序中,我们比较少用这样的写法,这个写法算是电气时代的遗留,给电气工程师过度之用。
下面看看PLC中的写法。
这样X0为启动,X1为停止,Y0为输出,语义就相对清晰了。下面我们加上注释。语义会更明显。
语义不明,即逻辑不明,是写程序和调试程序最大的敌人。
现在有了基础结构,我们用这个结构写一个跑马灯程序。
这是一个间隔10S的跑马灯程序。为了进一步说明,我们用状态图对上面的程序进行表达。
在这里,我们对定时器进行了抽象,即定时器与动作在逻辑上是等价的。在实际应用中,这个动作,可以是定时器,也可以是气缸动作,也可以是伺服运动等等,甚至可以是多个动作组成的动作集合。
到这里我们完成了PLC的基础部分,用这个逻辑,我们可以无限延展下去,一般的程序,完全可以用这个逻辑扩展。
那我们看看可不可以在上图的基础上,进一步抽象。我们换一种表达方式。二维图表。
状态1 | 状态2 | 状态3 | |
---|---|---|---|
动作1 | 条件1->状态2 | ||
动作2 | 条件2->状态3 | ||
动作3 | 条件3->状态1 |
在这里我们看到了与状态图不太一样的视角,但是两种表达是等价的。那这个图表对我们有什么用呢?
我们在这个图表上进一步抽象,给每一步动作加上一个序号看看。
序号 | 状态1 | 状态2 | 状态3 | |
---|---|---|---|---|
100 | 动作1 | 条件1->状态2 | ||
110 | 动作2 | 条件2->状态3 | ||
120 | 动作3 | 条件3->状态1 |
那这幅表格对我们写程序有什么意义呢,我们可以根据这个表格,对我们上面的程序进行一下改造。
这样我们将程序改造成,序号、状态、条件、序号转移,写在一起;而动作单独分开。
这样的好处是,我们可以直接从表格出发,直接写程序,逻辑更严谨的同时,也不会增加心智负担。
并且我们将动作与之分离,动作改写更加方便,尤其是多个动作组成的动作组等情况。
我们来看看这种情况用ST表达的样式。
在表达上更加简洁和直观,如果有从高级编程语言兼职PLC的,可以参考一下,不见得一定用梯形图来表达。
这个模式,被称为操作票模式,序号即是操作票,我个人更愿意称之为状态机竖着写。
那么状态机是什么?
状态机
“一般来说,在理论上,你需要知道如何计算”时间复杂度“和”空间复杂度“(time and space complexity);如果你要写一个解析器,可能还需要知道状态机(state machine)的概念;除此之外,并不需要知道特别多的理论。”——《黑客与画家》
在plc编程中,极少需要讨论数据结构以及算法的复杂度问题,也不是本文讨论的主题。我们主要看状态机。
状态机由状态寄存器和组合逻辑电路构成,能够根据控制信号按照预先设定的状态进行状态转移,是协调相关信号动作、完成特定操作的控制中心。有限状态机简写为FSM(Finite State Machine),主要分为2大类:
第一类,若输出只和状态有关而与输入无关,则称为Moore状态机
第二类,输出不仅和状态有关而且和输入有关系,则称为Mealy状态机
以上是百科给的相关资料,我们在PLC只研究第二类。
状态机综述
- 状态机是有向图形,由一组节点和一组相应的转移函数组成。
- 状态机通过相应一系列事件而“运行”。
- 每个事件都在属于“当前”节点的转移函数的控制范围内,其中函数的范围是节点的一个子集。
- 函数返回“下一个”(也许是同一个)节点。
- 这些节点中至少有一个必须是终态。当到达终态,状态机停止。
有限状态机是一种概念性机器,它能采取某种操作来响应一个外部事件。具体采取的操作不仅能取决于接收到的事件,还能取决于各个事件的相对发生顺序。之所以能 做到这一点,是因为机器能跟踪一个内部状态,它会在收到事件后进行更新。为一个事件而响应的行动不仅取决于事件本身,还取决于机器的内部状态。另外,采取的行动还会决定并更新机器的状态。
这样一来,任何逻辑都可建模成一系列事件/状态组合。
下面这个就是状态机的有向图形的表达形式,之前我们已经见过了。
状态机四要素
现态、条件、动作、次态
- 现态:是指当前所处的状态
- 条件:又称为“事件”,当一个条件被满足,将会触发一个动作,或者执行一次状态转移。
- 动作:条件满足后执行的动作。动作执行完毕后,可以迁移到新的状态,也可以仍旧保持原状态。动作不是必需的,当条件满足后,也可以不执行任何动作,直接迁移到新的状态。
- 次态:条件满足后要迁往的新状态。“次态”是相对于“现态”而言的,“次态”一旦被激活,就转变成新的“现态”了。
在上文中,事件有两种,一种是启动事件;另外一种是定时器的计时事件。
上文中条件满足时,没有触发动作,都是进行的状态转移。动作都是在现态下执行的。
状态机表示方法
- 一组状态集(states)
- 一个起始状态(start state)
- 一组输入符号集(alphabet)
- 一个映射输入符号和当前状态到下一状态的转换函数(transition function)的计算模型
- 状态、状态转换函数、与动作映射列表
本文中的状态集合为:(状态1,状态2,状态3)
起始状态,在这里并没有明确表达,在ST表达中,我们给了一个默认的0,即开机之后,未启动之前,状态值为0,这算是本文的起始状态,也是有向图中的第一个起始点。
一组输入符号集,在本例中,集合中只有一个元素,启动。实际工作中,这个集合可能比较大,几十几百都有可能。
计算模型,这里我们是通过梯形图或者ST语言来表达的。
映射列表,这个可以看作是状态机的核心,因为如果写不出状态机的映射列表,那么就说明对业务梳理的不到位,有含糊的地方,在写程序的时候,就会不知所措。
我们可以用有向图,也可以用二维表来表示映射列表。
状态1 | 状态2 | 状态3 | |
---|---|---|---|
动作1 | 条件1->状态2 | ||
动作2 | 条件2->状态3 | ||
动作3 | 条件3->状态1 |
现在再看这个表格,不知道大家有没有更清晰一些。
之前我们是从上向下的分析这个表格,写出了操作票模式的程序,那我们可不可以从左到右理解这个表格?我们横着写试试。
状态机在PLC中的应用之横着写
这是按照横着阅读映射列表写出来的程序,但是这个有一点不好的地方在于,状态和动作(此处为计时器)是耦合在一起的,如果遇到的是一个多个动作的集合,程序就会显得很啰嗦。
下面是改造。
通过增加一个解释字,我们将应用层与驱动层进行了分离。
应用层,这个层主要用来管理状态,事件,以及状态转移。
驱动层,只按照解释字进行动作,不用去管应用层的逻辑。
这样就大大的降低了心智成本。
这种写法就是解释器模式,我个人喜欢称之为状态机横着写,当然在每个人都有不同的称呼,比如有人称之为卡条件等等。
我们再看看解释器模式在ST中的表达。
至此,我们关于状态机在PLC中的两种应用模式就讨论完了。
当然状态机不止这两种,比如,我们在本例中,由于写得比较简单,所以实质上这个状态机也可以用独热码表示。
独热码在PLC中我们可以用一个字进行表示,然后用移位指令进行状态管理,也是可以的。
BUG
没错,写程序,怎么可能没有bug呢。
在本文中,由于只专注于讨论状态机,那么关于启动相关的状态,我们是忽略的,这就导致多次点击启动,会出现同时出现多状态的情况,这个需要在实际工作中注意。这里不做讨论,当然最后的ST表达的解释器模式实际上是解除了这个bug的,大家有兴趣可以自行尝试。
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)