MES的另一个常见应用是过程数据的上传。
车间现场的设备会产生大量过程数据,需要上传到MES,主要基于以下两个考虑:
1、
过程数据经过整理,可以用于统计分析。
2、
结果数据上传到MES后,MES会根据结果来判断产品的后续工序。
通常来说,不同行业有自己的专属工具,特别是自动测试台架有很强的定制性,软件也往往是高度定制的。
下面我尝试以实例说明,来探讨过程数据上传的通用设计。
某测试台架产生测试数据后,将关键数据写入PLC,上传到MES,MES根据传入数据的结果来决定将产品送入包装工位还是返修工位。
大致的设计思路是:
1、
MES将PLC的原始数据按照某种规则转换成标准的过程数据结构。
2、
MES判断结果,并执行对应的业务流程。
比如说,PLC的数据结构是:
字段
|
起始位
|
长度
|
示例
|
说明
|
String Length
|
0
|
3
|
011
|
PLC有效字符长度11
|
Result
|
3
|
1
|
P
|
测试结果,P表示成功,其它值表示失败
|
Item1
|
4
|
2
|
20
|
测试项1的值
|
Item2
|
6
|
3
|
120
|
测试项2的值
|
String End
|
9
|
2
|
OK
|
结束字符
|
现在我们在数据库中建一个表来表达通用的数据结构:
字段名
|
数据类型
|
说明
|
STATION
|
VARCHAR2(20 BYTE)
|
工位
|
ITEMNO
|
NUMBER(2,0)
|
参数序列
|
ITEMNAME
|
VARCHAR2(200 BYTE)
|
参数名
|
ITEMLENGTH
|
NUMBER(3,0)
|
参数长度
|
ITEMUNIT
|
VARCHAR2(20 BYTE)
|
参数单位
|
STATUSMARK
|
NUMBER(1,0)
|
值为1表示此参数用于判定测试结果
|
STATUSVALUE
|
VARCHAR2(20 BYTE)
|
判定测试通过的有效数据
|
那么此PLC数据结构在此表中这样定义:
STATION
|
ITEMNO
|
ITEMNAME
|
ITEMLENGTH
|
ITEMUNIT
|
STATUSMARK
|
STATUSVALUE
|
1234
|
1
|
Test Status
|
1
|
|
1
|
P
|
1234
|
2
|
Item1
|
2
|
G
|
|
|
1234
|
3
|
Item2
|
3
|
MM
|
|
|
有了这个结构作为参照,当我们接收到PLC的原始数据后,我们就可以解析出测试结果,以及测试项1、测试项2的值。
附加上产品序列号、测试工位、测试时间、测试人员这些基本数据,我们就得到完整的测试过程数据。
下面我们进一步就可以把过程数据保存到数据库中。
在数据库中建立一个主表,一个从表,其中主表保存产品序列号、测试工位、测试时间、测试人员、测试结果。从表保存所有测试项的名称、值和单位。
在数据库中再建立一个触发器,监控主表的创建,一旦有新的数据,则立即查询测试结果,根据结果的不同来执行对应的业务逻辑。
下面是实现数据解析及结果处理的示例代码(Oracel数据库):
DECLARE
uploadstring VARCHAR2(2000);
leftstring
VARCHAR2(2000);
itemname
VARCHAR2(20);
itemvalue
VARCHAR2(2000);
itemunit VARCHAR2(2000);
itemlength
INTEGER;
statusmark
VARCHAR2(1);
statusvalue
VARCHAR2(1);
passfail
INTEGER;
CURSOR mycur IS
SELECT
t.itemno,
t.itemname,
t.itemlength,
t.itemunit,
t.statusmark,
t.statusvalue
FROM t -- à t是定义结构的表
WHERE t.station = I_STATION
ORDER BY t.itemno;
BEGIN
uploadstring
:= I_UPLOADSTRING;
leftstring
:= uploadstring;
itemname
:= 0;
itemvalue
:= uploadstring;
itemunit := '';
itemlength
:= 0;
statusmark
:= 0;
statusvalue
:= '';
passfail
:= 1;
-- 1. get all items 查询得到所有数据
FOR rec IN mycur
LOOP
itemname := rec.itemname;
itemlength := rec.itemlength;
statusmark := rec.statusmark;
statusvalue := rec.statusvalue;
itemvalue := SUBSTR(leftstring, 1,
itemlength);
--
1.1 check test status mark 找到判断结果的参数
IF statusmark = 1
THEN
if itemvalue = statusvalue
THEN
passfail := 1;
ELSE
passfail := 0;
END
IF;
END IF;
leftstring := SUBSTR(leftstring,
length(itemvalue)+1,1000);
END LOOP;
-- 1.2 add test data master 插入数据到主表
SP_INS_TESTDATAMST
(
I_ESN,
I_STATION,
I_TIME,
I_OPERATOR,
passfail,
O_MSTID -- à 主表流水号
);
COMMIT;
--
2 add test data detail插入数据到从表
leftstring := uploadstring;
FOR
rec2 IN mycur
LOOP
itemname := rec2.itemname;
itemlength := rec2.itemlength;
statusmark := rec2.statusmark;
statusvalue := rec2.statusvalue;
itemunit := rec2.itemunit;
itemvalue := SUBSTR(leftstring, 1,
itemlength);
--
1.1 check NOT test status mark
IF statusmark = 0
THEN
SP_INS_TESTDET
(
O_MSTID,
itemname,
itemvalue,
itemunit
);
COMMIT;
END IF;
leftstring := SUBSTR(leftstring,
length(itemvalue)+1,1000);
END LOOP;
END;
|
没有评论:
发表评论