2016年7月6日

MES应慎谈大数据

突然之间,工业4.0”中国制造2025”大数据智能制造智慧工厂等词汇变得流行起来,仿佛不谈新词汇就变得落伍了,仿佛传统MES已经不适应新时代了。
可是真的是这样的吗?真的有几个人能把这些新词汇说清楚吗?
以我个人多年做MES项目的经验,我觉得中国制造现在还处在工业2.0,顶多在工业2.5,多数的企业还远远没有实现自动化,更不要说智能化。
要想直接走工业4.0,实现弯道超车,这是一个很丰满的理想,但是却受到基础设施、成本、人才、管理体系等诸多因素的制约,因而很难落地。
比如以自动化为例,目前的主流技术框架很难与大数据对接。
我们知道MES位于计划层与控制层之间,MES现场制造数据主要来自于客户端与现场设备,而相当多的设备是由PLC控制的。
以中国主流的西门子300/400 PLC举例来说,PLC首先要保障的是业务的稳定,其次才是数据的收集处理,而PLC在组建网络时受到诸多条件的限制。
首先,PLC通过OPCIT系统通信时,会受到传输数据容量的限制。通过OPC设置为单边、异步通信,每次通信不能超过200个字节。
其次,PLC之间通过PN/PN COUPLER组网时,通信稳定性很有保障,但是交换区的容量只有256字节。
第三,PLC的掉电保持容量非常有限,300系列最多只有700KB,因此当PLC用于数据缓存处理时,能保持的数据容量就受到了限制。
第四,PLC的工作内存也很有限,一般在数M字节,因而也很难在PLC上做大量数据配置。
我们看到的许多谈制造大数据的文章,往往介绍了许多业务重要程序一般的数据,因此尽管采集的数据多,但对业务的影响其实有限。
就控制现场而已,首先要保证的是数据的有效性、一致性,其次才会考虑采集尽可能多的数据。
目前PLC还是最有效的现场控制方式,但PLC在数据处理方面的局限性在短期内还没有很好的解决办法,因此很难从技术方面既保证一致性又做到大数据处理。
与其空谈大数据,不如一步一个脚印,先把自动化做好做实,再来实现智能化和大数据。



2016年5月27日

用双指针实现PLC堆栈设计

  
关键技术:PLC 堆栈
关键算法:指针

某基地在设计MES现场调度模块时,架构了一个部署在车间现场的IT PLC,作为MESME PLC通讯的中间介质,用于处理握手信号并缓存业务数据。
此调度模块要实现以下业务数据的缓存:订单缓存、过站记录缓存、在制品队列缓存。其中订单缓存用于上线,过站记录缓存用于物料拉动,在制品队列缓存用于防错。
缓存的意义是为了防止应用系统环境(应用服务器/数据库/OPC/消息队列服务器)对现场(OEM PLC)作业的影响,毕竟PLC层面的交互要稳定及时得多。

IT的层面来说,用数据库做队列和堆栈设计是非常容易的,通常通过一个过滤条件再加一个排序条件就可以从数据库中检索数据并加载到内存。
但是用PLC做缓存堆栈会受到诸多限制,尤其是要考虑扫描周期和掉电保持数据容量的影响。
比较方便实现的一个做法是:建立一个数组,按照先进先出的规则对数据进行处理,每次更新数据时对数组里的数据用FOR循环进行MOVE。但是当数据长度较大时(如缓存120个订单),并且数据类型以字符型为主时,这种操作对扫描周期会造成较大影响。

本文描述了另一种建立堆栈的方式:利用双指针构建。
首先我们在DB块里建立如下表所示的堆栈结构:
偏移量
TAG
TAG长度
备注
0
HEAD
2
订单起始位
2
STEP
2
订单数据长度
4
P1
2
首订单指针
6
P2
2
末订单指针
8
QTY
2
有效订单个数
10
ORDER1
80
订单1
90
ORDER2
80
订单2
170
ORDER3
80
订单3
250
ORDER4
80
订单4

下表建立了WO1/WO2/WO3/WO44个订单的堆栈:
偏移量
TAG
TAG长度
备注
0
HEAD
2
10
订单起始位
2
STEP
2
80
订单数据长度
4
P1
2
1
首订单指针
6
P2
2
4
末订单指针
8
QTY
2
4
有效订单个数
10
ORDER1
80
WO1
订单1
90
ORDER2
80
WO2
订单2
170
ORDER3
80
WO3
订单3
250
ORDER4
80
WO4
订单4

WO1下发成功后,且又从MES接收到新订单WO5后,可用的订单序列是WO2/WO3/WO4/WO5,堆栈结构如下表所示:
偏移量
TAG
TAG长度
备注
0
HEAD
2
10
订单起始位
2
STEP
2
80
订单数据长度
4
P1
2
2
首订单指针
6
P2
2
1
末订单指针
8
QTY
2
4
有效订单个数
10
ORDER1
80
WO5
订单4
90
ORDER2
80
WO2
订单1
170
ORDER3
80
WO3
订单2
250
ORDER4
80
WO4
订单3

从表格可以看到,首订单指针已经下跳了一格,由1变成2,而末订单指针则由4跳回了1

首订单的寻址算法为:
首订单偏移量 = HEAD + (P1 - 1) * STEP
代入上表值,即90 = 10 + (2-1) * 80

WO2下发成功后,将首订单指针指向WO3(P1=P1+1,当P1=5时重置P1=1),并将有效订单个数QTY-1
偏移量
TAG
TAG长度
备注
0
HEAD
2
10
订单起始位
2
STEP
2
80
订单数据长度
4
P1
2
3
首订单指针
6
P2
2
1
末订单指针
8
QTY
2
3
有效订单个数
10
ORDER1
80
WO5
订单3
90
ORDER2
80
WO2
已下发订单
170
ORDER3
80
WO3
订单1
250
ORDER4
80
WO4
订单2

下一个订单WO3的寻址算法为:
170 = 10 + (3-1) + 80
堆栈里订单的逻辑序列为:WO3/WO4/WO5

此时订单的有效个数QTY=3,小于最大缓存数量4,因此允许从MES接收新订单WO6WO6写入位置的寻址算法为:
末订单偏移量 = HEAD + P2 * STEP // P2 < 4
末订单偏移量 = HEAD  // P2 = 4
代入上表值,即90 = 10 + 1*80
写入新订单数据后,将P2下移一位,P2 = P2 + 1,当P2 = 5时,将P2复位成1
然后将有效订单个数QTY+1,如下表如示:
偏移量
TAG
TAG长度
备注
0
HEAD
2
10
订单起始位
2
STEP
2
80
订单数据长度
4
P1
2
3
首订单指针
6
P2
2
2
末订单指针
8
QTY
2
4
有效订单个数
10
ORDER1
80
WO5
订单3
90
ORDER2
80
WO6
新接收订单,队列位置4
170
ORDER3
80
WO3
订单1
250
ORDER4
80
WO4
订单2

经由上述方法,即在数据块里建立了一个由P1P2这两个指针界定的订单队列,并用HEAD/STEP/P1/P2进行寻址,用QTY判断要不要接收新订单。
可以另外编写两个FC,分别用于实现订单下发和订单接收。
这种方法由于使用指针进行寻址,无需对堆栈进行MOVE操作,因此对CPU扫描周期的影响较小。
但是这种方法的缺点是:当现场出现异常作业时,容易出现指针混乱,从而引发业务数据混乱。应对的方法是:每次作业都和MES进行同步,并且记录日志进行追踪。