刘阳
2024
-
1. 前言
当前的PLC处理能力和通讯能力已经得到长足发展,PLC也可以完成一些轻型的类IT的任务。但是毕竟传统意义上的PLC编程方式是以结构化编程方式为主。用结构化编程思路完成类IT的任务显得有些力不从心甚至会带来混乱和编程的灾难。
SECS通讯软件是生产设备与工厂IT系统的通讯接口。这个通讯接口可以完成生产设备与工厂IT系统之间的数据传输。通过这些数据传递实现生产数据上传、数据跟踪、设备远程控制、设备参数设定、设备模式管理、设备物料管理、配置报告、事件收集、终端服务等任务。由于其强大的功能,SECS通讯已经长期和广泛的应用在半导体生产领域。伴随着半导体的生产收集了大量的数据,并在这些数据分析的基础上改进半导体生产工艺从而提升半导体良品率和探索更先进的生产制成。可以讲没有SECS通讯就没有当前半导体行业的蓬勃发展。SECS通讯在半导体行业的成功使得它拓展了应用范围,现在更多的生产制造领域也使用SECS通讯。
SECS通讯的功能强大也带来一个问题,就是SECS通讯软件编程比较复杂。传统实现SECS通讯的方法是在工控机上利用面向对象的语言进行编程。众所周知面向对象的编程可以解决更复杂的编程问题,因此SECS软件在面向对象的编程环境下显得容易一些。
能不能用PLC实现SECS通讯系统软件呢?笔者尝试用西门子1500PLC实现SECS通讯系统软件。博途环境的1500编程从根本上来讲是结构化的编程环境。如何利用这个编程环境实现复杂的SECS通讯软件的功能是一项挑战。本文要探索的是在1500PLC编程的环境下,在一些关键编程点上用面向对象的编程思路进行编程,从而使本来复杂的编程得到简化。
-
2 厘清概念
-
2.1 面向对象的编程思路
-
所有面向对象的编程思路都需要首先创建类。在类中有一些数据、有一些方法(在PLC中方法称为程序块)。类的方法对类的数据进行操作。
类创建完毕就可以以类为模板创建实例这就是对象。每个被创建的对象包括类的非共性数据和类的共性方法。
面向对象的编程方法有3个特点:封装、继承、多态。
这些内容在下文中都有所述及。
2.2什么可以作为对象
在PLC程序中,哪些被控对象可以作为面向对象编程中的对象呢?一个典型的面向对象的程序语言JAVA认为:万物皆可对象。不过就我的经历看,在PLC程序中可以抽象为对象的有几个共同的特点:
- 需要多个输入或者输出点位来涵盖这个对象或者有多个传感器、执行器组成,总之需要抽象为对象的不是简单的事物。
- 对象的各个构成元素共同完成一个控制目的。
- 在一个PLC程序中,对象有相同的控制方法,并且可以抽象为同一类型对象的被控对象很多。
简单几个例子进行说明:
- 开度可调节的阀门由模拟量输入、模拟量输出组成;这些输入输出共同完成对阀门的控制。在一个化工装置中,这样相同的阀门有几十上百个,它们有相同的控制方式。这个位置阀门可以看作是一个对象。
- 一个PID控制器也可以看作是一个对象。因为它有输入、输出、PID参数等多个元素组成。PID算法相同,并且在一个PLC程序中可以使用多个PID控制。
- 机场行李输送系统的一条皮带可以看作一个对象。皮带由变频器,物料传感器,组合灯组成,这些要素共同完成对皮带的启停控制,并且这样的皮带在一个项目中可以多达上百条。
- 汽车组装线上一个车架提升机构也是一个对象。提升机构由变频器、极限位置传感器组成,这些设施共同完成车架提升这一功能。在几百米的组装线上,相同功能的提升机构不止一个。
- 通讯的对话也可以看作一个对象。对话由发起方消息和回复方消息组成,他们共同构成通讯中一个对话。这个对话实现一个通讯目的。SECS通讯软件都是由几十个上百个这样的对话组成。
- 在伺服控制中,一个速度轴或者位置轴也可以看作一个对象
2.3 继承性
还有一个问题是继承性。举几个例子:
假定已经为一个位置阀门和PID开发并测试好各自的程序。一个新的需求产生:由位置阀门自动控制罐体液位。那么可以用已经开发好的2个工艺对象组合在一起再增加一些新内容就是一个新的更大的对象。这个新的更大的对象可以讲继承了2个小对象的所有内容。
位置轴包括速度轴的所有功能,那么位置轴就可以继承速度轴的内容。
已经开发好一个通讯对话程序。再开发一个通讯会话程序。这个会话是由若干对话组成。开发会话程序时就可以继承对话程序中的所有内容。
还是对话的例子。SECS通讯软件包括上百个对话。每个对话都有各自不同的内容和功能。如果把每个功能视为一个对象。那么这个对象中就可以视作继承了对话对象的全部内容。
通过几个例子可以对继承性有一个新理解:所谓继承就是大功能(子类)继承了小功能(父类)的所有内容。
一些高级语言不支持多重继承,但是在PLC中不必要担心这个问题。因为继承性是编程者的思想,不会受到编程环境的约束。
在SECS通讯系统软件中,一些对象有多达5层的继承。
3. 1500PLC实现面向对象的方法
如何用西门子PLC中实现面向对象的编程?本章要讨论2种常见的模式。一个是FB+IDB,另一个实现模式是FC+PLC数据类型。
3.1 西门子PLC编程的历史沿革
谈到在西门子PLC中实现面向对象的编程方法就不得不谈到PLC编程的历史演变。从DOS操作系统的STEP5软件对S5 PLC进行编程到WINDOWS操作系统的STEP7软件对S7-300/400进行编程,再到当今博途环境的1500PLC。这几十年发展的足迹清晰,方向可辨。
笔者曾经在西门子公司参与到为奔驰汽车整车组装线编写PLC程序标准。这套程序标准有面向对象的思路。虽然当时用的是S7-400的PLC,但是显然这套程序是来自于S5的程序。因为这套程序没有使用如今流行的“功能块(FB)+背景数据块(IDB)”的方式,而是用“功能(FC)+全局数据块(gDB)”的方式去实现“FB+IDB”的功能。“FB+IDB”是一种面向对象的实现模式,下面就从“FB+IDB”说起。
3.2 FB+IDB
上文提及类或者对象是由封装好的“数据+方法”组成。FB+IDB具备了这3个要素:封装、数据、方法(函数或者功能)。
定义好一个FB后,只要根据这个FB生成不同的IDB就可以处理不同的对象。
比如化工装置的位置阀门,就可以用一个FB中的程序处理,如果一个项目有100个阀门,要生成100个IDB,每个IDB对应一个物理阀门。这些阀门的运行不会因为使用同一个FB而互相干扰。
FB+IDB可以实现面向对象的编程思路。这种模式有一个优点就是数据和方法封装在一个FB内,但是这种模式有一个局限就是类中的方法只有1个,就是这个FB本身。
如果程序需要一个对象中有多个方法怎么办?这就需要另一种面向对象的编程模式:FC+PLC数据类型。
3.3 FC+PLC数据类型
SECS通讯中本机需要回复主机的消息。因此可以把回复主机消息看作一个对象。
在回复消息之前需要对本对象初始化,这需要一段程序,可以封装在一个FC当中,这个FC命名为SECS_R_Begin。在消息内容生成完毕后,还需要发送生成好的消息,那么此时需要对象具备发送消息的能力,这个功能可以封装在另外一个FC中命名为SECS_R_End。那么这个对象就具备了2个方法:初始化方法和发送方法。
对象中有了方法,还需要数据。数据模板来自PLC数据类型。需要创建一个合适的数据类型(SECS_R_Class)供以上2个方法使用。
同时在2个方法的INOUT区域声明创建的PLC数据类型。在给2个方法编程时,自然会用到INOUT区声明的SECS_R_Class类型。实际上这就实现了对象的方法对对象的数据进行操作。
对象实例数据可以在FB的静态区定义,也可以在全局数据块中定义。这2个区域都是静态区域。下面2图分别在gDB和IDB创建的对象。
如果对象的存活时间不会跨越PLC周期,对象数据也可以在临时区声明。
在调用2个方法填写数据INOUT引脚时,同一个对象一定要使用相同的数据实例。
以上就是FC+PLC数据类型的实现面向对象的编程方法。相对于FB+IDB方法,FC+PLC数据类型的方法更灵活。缺点是对象的要素没有封装在一起,方法和方法之间以及方法和PLC数据类型之间都是在博途的不同位置定义的,定义过于分散,我们只能在编程文档中将这些要素虚拟的封装在一起。当然V17以后的博途增加了软件单元的功能。我们可以把一个类封装在一个软件单元中。但是用这种办法进行封装,如果类过多,也会造成困扰,况且这也不是软件单元的主要用法。
3.4 继承的实现方法
针对以上2种面向对象编程的实现模式,继承也有不同的实现模式。
3.4.1 在FB静态区
如果把一个FB看作一个类,可以在它的静态区通过2种方法实现继承。举例,下图是FB,SECS_RPT_RPT_R的静态区,功能块的功能是通过回复消息向主机回复一个报告。
- 在FB静态区声明PLC数据类型
回复报告的功能是需要继承回复消息的功能。因此可以在静态区声明SECS_R_Class,也就是继承了SECS_R_Class类
在功能块SECS_RPT_RPT_R中可以调用SECS_R_Class子类的方法以实现一定功能和目的。
- 通过多重背景数据块继承了内部FB内容。
在静态区声明了一个多重背景“EXE”。EXE的功能是控制所调用FB的流程。在SECS软件中的所有功能性FB都会调用此EXE,因此EXE可以视为一个类。同样可以在功能块SECS_RPT_RPT_R中调用EXE方法。
3.4.2 在PLC数据类型中
上文述及一个SECS会话包括若干个对话。把对话视作对象,会话类可以继承对话的内容。下图中关注2个数据类型:SECS_I_Class、SECS_I_Class_w_Pre。
SECS_I_Class是一种对话类,SECS_I_Class_w_Pre是一种会话类。通过将对话类数据类型声明在会话类中,会话类实现了对话类的继承。
3.5 多态的的实现方法
1500PLC有2个非常卓越的数据类型:Variant类型和Ref类型。有了这2个数据类型,在1500PLC中实现多态就易如反掌。
用Variant类型定义的形式参数,在填写实际参数时可以是任意类型。
Ref引用类型可以指向Variant引脚的填写的任意类型。
用2个例子说明。
例1:数字转换为字符串
在通讯中经常需要用到数字转换为ASIIC码字符串。FC:SECS_STD_Val2Str用于实现这个的功能。该功能的引脚Value用于数值输入,类型是Variant。
如果没有Variant类型,那么需要针对每种数字类型(8种整形和2个浮点类型)都要编写一个功能。有了Variant类型可以将这10种类型的程序封装在一个功能中,优化了软件的结构。
例2:在SECS通讯中,需要向主机传输状态值(SV),而状态值的类型是不确定的。下图功能SECS_SV_Value的SVn引脚都是Variant类型。在PLC范围内任意拖拽一个变量到SVn引脚处即可完成状态值的定义。
如果没有Variant类型,状态值的定义将是一项极其繁杂的工作。
3.6 其他
虽然1500PLC可以动态创建数据块,但是到目前为止,还无法动态根据数据类型创建对象(数据块)。也许在未来的博图版本中这个功能会开放出来。
4 结束语
当我们遇到复杂的编程问题(比如SECS系统软件的编程工作)时,总是希望降低编程的难度。既然面向对象的编程可以降低编程的难度,那么我们在考虑复杂问题编程时可以借鉴面向对象的编程思想规划程序。然后运用上述的几种模式,在博途这种结构化的编程环境下实现面向对象的编程。
在1500PLC中实现SECS系统软件编程的工作就是在这样的指导思想下完成的。幸运的是博途的编程环境以及提供的素材是可以实现面向对象的编程思想。通过测试发现运行在1500PLC中的SECS系统软件具有优异的性能。压力测试小于50ms,其他性W能X:也1满3足9S1E0C3S8标0准9的3要1求。