基于模型的PLC程序设计三 层次状态机

这次我们再在前面的例子上加深一步,写个含有父状态的状态机,同时用ST语言描述。

控制描述

有一个电机,按下启动按钮后低速启动,按下加速按钮后切换成高速,按下减速按钮后再切换成低速,如果按停止按钮,直接停止。用状态机描述如下:
基于模型的PLC程序设计三 层次状态机

这个状态机我们简要说明一下。和上一篇有点不一样。包换了一个父状态running,在running里含有两个子状态runSlow和runFast,分别通过按钮speed_up、speed_down切换。前面我们讲过,只要子状态**,它的父状态必然**。如果父状态**,那么也必需有一个子状态**,这里我们设定runSlow为默认的状态,因为它的上面有个无条件转移线。

生成ST程序

我们先把需要用的变量列出来。他们都为bool型的,分别是输入变量start,stop,speedUp, speedDown, 和两个输出runSlow, runFast, 然后再加一个状态变量state,另加4个常量分别表示4个状态,stateStop, stateRunning, stateRunSlow, stateRunFast。这里我们简要讲一下变量的命名规则,写PLC程序的,变量的命名都喜欢用Pascal命名法或匈牙利命名法。尤其是匈牙利命名法,已在PC编程中被淘汰了,为啥呢?因为现在的IDE都支持类型提示,用变量名来显示类型,多此一举。如果以后修改了变量的类型,还要再次改变变量名称。我们用的博途IDE也是支持类型推导的,把鼠标放变量上,它会告诉你啥类型。没必要这么做。所以这里我们用峰驼命名法,首字母小写,后面每个单词的首字母大写。下面我们接着讨论写状态机。

变量声明

基于模型的PLC程序设计三 层次状态机

具体的程序
基于模型的PLC程序设计三 层次状态机

程序说明

这个程序使用两个变量来切换状态。#baseState 和 #childState。
#baseState 是用来切换stop和running状态的,而#childState 是用来切换runSlow和runFast的。我们先说明stop和running的状态切换。

  1. stop和running的切换
    我们看static的变量声明区,#baseState的初始化值是常量#stateStop,说明状态机一**,就处于stop状态。第5行程序是切换条件,如果#start为true,那么#baseState的值就是#stateRunning,那么程序就会执行case语句中#stateRunning这个分支,状态机的活动状态就从stop状态转移到running状态。#stateRunning中嵌套了一个case,它有两个选择,一个是stateRunSlow,另一个是stateRunFast。#childState的默认值是#stateRunSlow,说明程序将默认执行#stateRunSlow。第23行是从running状态转移到stop状态的条件。
  2. runSlow 和 runFast的切换
    这两个状态的切换原理和上面的一致,就不多花时间解释了。

历史状态

如果当前状态是处于runFast状态,按下stop按钮后,状态转移至stop状态,然后在按start按钮,希望切换至上次离开时的状态,也就是runFast状态,而不是默认状态,那么该怎么做呢?我们只要删除25行程序就可以了,#childState变量将保存上次的值。历史状态的用途是有时我们按了急停按钮后,处理完设备故障,然后想接着执行上次的状态,就使用历史状态。比如CNC,有人触发了保护光栅,设备停机,复位后继续,而不是回原点。