2016年4月18日

浅谈MES的通用设计之:过程数据的上传


MES的另一个常见应用是过程数据的上传。
车间现场的设备会产生大量过程数据,需要上传到MES,主要基于以下两个考虑:
1、        过程数据经过整理,可以用于统计分析。
2、        结果数据上传到MES后,MES会根据结果来判断产品的后续工序。
通常来说,不同行业有自己的专属工具,特别是自动测试台架有很强的定制性,软件也往往是高度定制的。
下面我尝试以实例说明,来探讨过程数据上传的通用设计。
某测试台架产生测试数据后,将关键数据写入PLC,上传到MESMES根据传入数据的结果来决定将产品送入包装工位还是返修工位。
大致的设计思路是:
1、        MESPLC的原始数据按照某种规则转换成标准的过程数据结构。
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;




没有评论: