1024 【万泉河】PLC编程烟台方法UDT后遗症
三年前,写过一篇文章《【万泉河】PLC编程:反UDT同盟》
***************
其实并没有什么同盟, 也没必要搞什么同盟。 我只不过在明确的表达一种观点,亮明自己的主张,同时又不拒绝自己和别人使用。
比如我自己,虽然比较抵制使用UDT,但当实在无路可走的时候, 迫不得已还是使用了UDT。 而且一旦使用,就是大批量的使用。
是在做三菱PLC标准化的时候。
因为三菱的软件中,FB的性能稍微差一些, 不像西门子PORTAL的FB强大, 好多功能不具备。 尤其不能覆盖UDT所实现的部分数据打包的功能。 所以,迫不得已,为每一个FB库类型还辅助配备一个UDT。
UDT的本质也是对象,也要有实例化。 所以,其实在三菱的标准化中, 是使用FB+UDT实现了面向对象的架构。 其中,FB只是实现逻辑功能,而面向对象的功能部分,则依靠UDT来实现。 当然,三菱的UDT也仍然有不足,比如不能UDT嵌套,所以使用上有很多碍手碍脚。 只不过聊胜于无,也只好这样了。
最近在紧锣密鼓撰写针对三菱PLC标准化的新书《三菱PLC标准化烟台方法》,主体原理内容已经基本完成,现在在做应用实践例程部分的讲解。 即相当于前一本《PLC标准化编程原理与方法》倒数第二章的最后一节:<5.7标准化工程实践>部分的内容。
其实就是把原书的章节复制过来, 按照三菱的架构重新做一遍。 因而需要自己动手,再温习一下在三菱环境下的软件编程过程。然后就对原来的做法中UDT的使用,又有了新的改进想法。
(烟台方法只是一种思想方法,而不是一个一旦完成就完全固化不再改变的僵化的架构模式,已经重申过多次了,这里只是又一次体现。)
在原来的做法中,即我交付给三菱标准化学习营的学员的程序中,手动设备实例化的程序是这样的:
AI_0001.UU.HI_LIM:=100.0;
AI_0001.UU.LO_LIM:=0.0;
AI_0001.UU.IN_INT:=AI_0001_IN;
AI_0001.UU.OP_dwCmd:=AI_0001_OP_dwCmd;
AI_0001.UU.OP_HI_LIM:=AI_0001_OP_HI_LIM;
AI_0001.UU.OP_LIM_HYS_Abs:=AI_0001_OP_LIM_HYS_Abs; AI_0001.UU.OP_LIM_HYS_Perc:=AI_0001_OP_LIM_HYS_Perc;
AI_0001.UU.OP_LIM_LLA:=AI_0001_OP_LIM_LLA;
AI_0001.UU.OP_LIM_LLW:=AI_0001_OP_LIM_LLW;
AI_0001.UU.OP_LIM_ULA:=AI_0001_OP_LIM_ULA;
AI_0001.UU.OP_LIM_ULW:=AI_0001_OP_LIM_ULW;
AI_0001.UU.OP_LO_LIM:=AI_0001_OP_LO_LIM;
AI_0001.UU.OP_SIM_Value:=AI_0001_OP_SIM_Value;
AI_0001.UU.QdwState:=AI_0001_QdwState;
AI_0001.UU.QOUT:=AI_0001_QOUT;
AI_0001.UU.QwAlarm:=AI_0001_QwAlarm;
AI_0001.UU.VISIBILITY:=AI_0001_VISIBILITY;
AI_0001();
AI_0001_IN:=AI_0001.UU.IN_INT;
AI_0001_OP_dwCmd:=AI_0001.UU.OP_dwCmd;
AI_0001_OP_HI_LIM:=AI_0001.UU.OP_HI_LIM;
AI_0001_OP_LIM_HYS_Abs:=AI_0001.UU.OP_LIM_HYS_Abs; AI_0001_OP_LIM_HYS_Perc:=AI_0001.UU.OP_LIM_HYS_Perc;
AI_0001_OP_LIM_LLA:=AI_0001.UU.OP_LIM_LLA;
AI_0001_OP_LIM_LLW:=AI_0001.UU.OP_LIM_LLW;
AI_0001_OP_LIM_ULA:=AI_0001.UU.OP_LIM_ULA;
AI_0001_OP_LIM_ULW:=AI_0001.UU.OP_LIM_ULW;
AI_0001_OP_LO_LIM:=AI_0001.UU.OP_LO_LIM;
AI_0001_OP_SIM_Value:=AI_0001.UU.OP_SIM_Value;
AI_0001_QdwState:=AI_0001.UU.QdwState;
AI_0001_QOUT:=AI_0001.UU.QOUT;
AI_0001_QwAlarm:=AI_0001.UU.QwAlarm;
AI_0001_VISIBILITY:=AI_0001.UU.VISIBILITY;
这里只是1个模拟量模块的实例化的过程。注意看中间部分的AI_0001(),是对FB的调用,这里当然是简单的,因为整个程序块连输入的参数都没有。
而其实是因为它的参数是个UDT, 而对UDT的赋值(以及读取它的值),是没办法一句指令表达的,所以需要逐行逐句写。
即,在调用之前,对所有管脚赋值,在调用完成后,对所有需要的管脚读值。
这非常令人头疼。原本在S7-1500中, 一行FB调用就能实现的功能, 这里要分拆到20多行。
还好, 我程序是EXCEL里用模版自动生成的,就不需要关心每句程序的对错了。 要对都对,要错都错。所以,甚至在程序中也尽量不想看到他们。
所以,在生成程序时,这些脚本之间的换行都删掉了,在程序中,每一个实例只占一行,而其实一行超过1000字。 反正也不看。
所以在真正的程序中看来是这样:

多个实例排起队反而整齐了。
由此, 哪怕是80个模拟量,也只是80行。 而其实,真的要算起来,恐怕1600多行都不止了。
那些嘲笑我不会用循环的同行,单单80个调用实现循环很容易。 然而给参数赋值的1600-80=1520行程序怎么搞,你们关心过吗?可我一直关心的是这个。
所以,前面的方式虽然是实现了,但心里一直有缺憾的。 还是喜欢FB的管脚,能一个调用帮我把该输入的参数实参赋值给实例。
于是,这回又改进了一下FB的设计,把原本已经收纳到UDT中的部分管脚, 即那些需要在实例化时指定的参数,增加到管脚中:
类
标签名
数据类型
VAR_INPUT
IN_INT
Word[Signed]
VAR_INPUT
HI_LIM
FLOAT (Single Precision)
VAR_INPUT
LO_LIM
FLOAT (Single Precision)
VAR_IN_OUT
UU
UDT2_AI
具体对这些UDT的数据处理,在程序中的前处理段和后处理段补几个赋值语句即可。
而实例化调用的时候,则简化为一句话:
AI_0001(IN_INT:=AI_0001_IN ,HI_LIM:=100.0 ,LO_LIM:=0.0 );
总算消除了一点点原来方法留下的后遗症。 或许整个程序的尺寸规模,也能减小不少。
看起来爽净多了,我心里面也爽快多了。所以赶紧记录发表出来。
同时,此文的目的,也对已有的三菱标准化学员,除了教给你们新的实现方法之外, 也提醒大家,未来书出版之后见到了内容会跟拿到的程序介绍的功能和方法有很多不一样的地方, 不要惊讶, 技术一直在发展中,烟台方法也一直在发展进步中。
当然,我希望你们拿到烟台方法的案例以后,在自己的应用行业内也已经应用发展出自己的成果了。
最后,其实还有一点, 80模拟量的系列例子程序,三菱品牌的一直没做,但大家也大概可以知道做出来是啥样子了。 而其它品牌的例子,请见以前的文章。