0822 【万泉河】好的PLC程序框架应该是不做初始化
看到题目,我相信一定又会有人跳起来:你懂不懂编程,你是不是没编过程序?程序当然要有初始化功能,比如断电重启动,比如系统需要复位,伺服需要回原点等等。
嗯,我知道你们很急,但你先别急。
我当然知道程序中有一些功能需要有初始化,然而我本文要表达的是你不要把它们做到框架里来。
我们经常见到一些总结归纳的PLC程序模版或者框架,绝大多数都会提到要有初始化的功能。
三、程序架构思路(庖丁解牛)
好的轮换程序得像洋葱一样分层清晰:
1.初始化(First Scan):上电或从STOP切到RUN时,干点“家务活”:
清零所有运行时间和启动次数。
设定一个合理的初始主泵和备泵(比如设Pump1主,Pump2主,Pump3备)。
复位所有故障状态(等待真实信号)。
停止所有泵输出命令。
2.模式选择 & 系统启停:这是老大,管总开关。
读`自动/手动`开关。
那么我们以伺服为例按照上面的做法初始化的情况。
比如我们在一台设备中初始设计时有5台伺服, 那么在PLC初上电启动时需要对这5台伺服电机做初始化寻原点处理。
然后在设备调试过程中, 发现原本某个动作也需要用伺服实现,即伺服电机需要加到6台。 那么除了正常的控制功能之外, 还需要在这套初始化程序逻辑中加入6#伺服电机的原点寻参。
然后,项目完成后,换一个项目,发现跟前一个项目有极大的相似性,所以决定在前项目为模版在其基础上修改完成新项目。然而只不过伺服电机配置又有变化,原本的2台不要了,又加入了一台新的。
如此,这套初始化程序又需要加加减减不断修改。
所以,所谓的初始化程序就压根不是固定的,无法模块化,总要随项目不断修改。 当然咯, 你的整个项目也都是需要到处打补丁修改。 除了集中初始化程序部分需要修改, 你对伺服电机的其它控制,定位,报警,调速,通讯等等功能也都是遍布在各处的,也都需要到处去修改。 也有可能,你为了程序的便捷,还在各处都分别做了循环。 所以,你认为即便设备数量有变化也没有大问题,只需要把循环的上限值改一下即可。 改大或者改小,只需要改一个数,只不过是改4-5处。
这对你自己来说可能并不觉得难,但如果这套程序需要交给你的同事,下级的刚入职的实习生来做, 那就难了。 他需要清清楚楚知道你这套系统的架构,知道这套设备的控制原理。 如果他想你应该封装成一个完整的模块,他希望用的时候只需要像普通电机一样, 给一个启动指令+位置参数,或者一个启动指令+速度给定,就能控制运行, 你则会毫不客气地批评他幼稚,不懂!
然后,你固然可以借培训教育他们的机会展示一下你丰富的技能以及丰富的现场经验,然而你也会发现, 培训他们的成本好像比较高, 没个一年半载,对他们都培训不成熟,都不能接手你的工作。
举一个例子, 比如你负责一个团队的运营,带领团队完成项目的攻关计划。 团队成员都听你指挥调度, 你安排他们每天日常工作,从出工到收工。然而你说不行, 他们还要吃饭呢,连早饭也要管,人不可能不吃早饭。 然后,你就需要从早餐开始, 安排好每个人的起床时间和集体用餐时间,如果其中有北方人和南方人,习惯的早餐不一样,你需要给他们分别准备,而也有可能有人根本不吃早餐,也还要统计有序。 这些相当于团队的初始化。每天早晨团队成员们需要初始化完成了才可以开始工作。
然而也不仅仅早餐,有人会反问怎么没包含刷牙?刷牙也很重要啊,不可能不刷牙啊。 好吧, 那你就再把他们的刷牙洗脸也统一管理起来。
这是不是很荒唐?
有人会产生疑问, 各种PLC的说明书中分明都有OB100, OB101,OB102的启动OB, 用于系统中需要的启动初始化管理,而且这三种启动OB还各不相同, 分别为暖启动,冷启动,热启动等等,执行的细节还各不相同。如果不让用,难道需要舍弃这些精妙的功能?
好吧,那下面就以启动OB为例举例一下应该如何实现设备的分OB调用。
其实很简单,以往也一直有烟台方法的学员问我如果设备控制中需要用到硬件中断触发,比如OB40,或者循环中断OB35, 应该怎么做设备模块。我通常都是一句话点醒一下他们就知道如何做了。 所以就一直没有机会单独整理成文章。 这样就一并解答了。
答案只有一句话:在FB的管脚上增加一个OB_No的管脚。
然后在不同OB中重复调用这个FB(以及相同的IDB), 调用的时候,只需要把OBNO的数值填进去即可。
举例说明一个FB:SERVOM,其它的控制管脚不表述,只关注OBNO:
这个管脚的默认值为1,代表OB1, 那么100时则为OB100后面还示例了梯形图模式下不同的OBNO值选择执行不同的内容。
而如果用SCL编程,则更简单了, 一个CASE语句即可:
CASE #OBNO OF
100: //OB100中执行的程序内容
;
101: //OB101中执行的程序内容
;
102: //OB102中执行的程序内容
;
30: //OB30中执行的程序内容
;
40: //OB40中执行的程序内容
;
1: //OB1中执行的程序内容
;
ELSE // Statement section ELSE
;
END_CASE;
FB中的所有静态变量可以在不同的OB线程之间共享使用,也正是通过如此,实现了跨线程的数据信息传递,而避免了使用全局变量。(一直以来很多人对全局变量躲不开的情节是不是就在这里?如果有人被击中,请在评论区回复。)
然后同类型的设备会有多台,那么FB的实例化多次,实现FB实例化调用的FC,也可以同样拥有OBNO的管脚,实例化时送给FB。
然后在各个OB中重复调用这个框架FC。(这才是程序的框架)
OB100中:
"FC1"(OBNO:=100);
同理OB40中:
"FC1"(OBNO:=40);
如此便轻松实现了初始化的统一调用。
这是最简单的实现方法。 然而,如果CPU支持,如果你拥有较高的编程技能, 还可以在FB中直接通过系统函数判断得到当下调用的OB, 就可以在内部程序中实现,而省了这一个管脚。
这部分与PLC的型号和品牌相关,读者们可以自行了解研究实现,实现后可以为每个品牌生成专用的模版。
更进一步, 在PCS7 CFC中每一个FB的属性中都可以分配所需要调用的OB,这话有点绕, 其实逻辑本身也有点烧脑。 看起来是在描述FB调用了OB,而实际上最终是所指定的OB调用了相关的FB。
这是我建议PLC从业者学习PCS7可以学到的重要内容,而不去学习PCS7的话,则永远没有机会了解到这些细节。
当然, 博途后来的版本也支持了CFC,但是否还支持这一块我并没有了解过。也不需要了。
前一篇文章《0818 【万泉河】工控工程师需要对垃圾程序脱敏》,不知道有多少工程师同行实现脱敏了。如果已经脱敏的话,那么会比较容易接受本文的另一种表达方式:
《程序架构有初始化模块是垃圾程序的典型标志》
参考文章:
0619 【万泉河】论一个好的程序框架的重要性
0818 【万泉河】工控工程师需要对垃圾程序脱敏
0914 【万泉河】给非标行业自动化工程师的一个学习建议:了解一下PCS7
1109 【万泉河】我推荐要学的PCS7来了。