zoukankan      html  css  js  c++  java
  • WinCC批次设计-基于用户归档

     什么是批次

       药品是一批一批的生产,批次用于区分药品的不同生产批。一个生产批次包括以下信息:批次名、产品名、产品规格、所使用的配方、其他设定参数以及批次的开始时间和结束时间,另外还有生产过程中记录的数据。

      以上数据并不全部存储在一起,而是在数据库中分成多个表存储。大致会分为配方、过程数据、批次、事件这样几个表。配方是某一种类型产品的生产参数,过程数据记录生产过程中实时的数据,批次表记录批次相关的信息以及未包括在配方中的设定参数,而批次的开始时间和结束时间记录在事件表中。事件表是以时间为序的一个序列,通过查询这个序列可以得到批次的开始时间和结束时间。

    如何记录一个批次

    基于以下设计的批次存储于用户归档。用户归档的本质是一个数据库。批次表的定义如下:

    Batch
    字段 类型 描述
    BatchName 字符串 批次名
    BatchType 数字(整型) 批次类型
    ProductName 字符串 产品名
    ProductType 字符串 产品规格
    RecipeID 字符串 配方ID
    parameter1   参数1
    parameter2   参数2
    parameterN   参数N

    向用户归档中添加数据需通过参数变量和控制变量。如果一个WinCC程序中管理了多台设备,则每台设备对应的变量名要加上设备前缀,这里用“XX_”代替。批次的用户归档中参数变量如下,除了XX_RecipeID和XX_BatchType外都是外部变量:

    Batch用户归档参数变量
    变量名 类型 描述
    XX_BatchName 文本变量8位字符集 批次名
    XX_BatchType 无符号的8位值 批次类型
    XX_ProductName 文本变量8位字符集 产品名称
    XX_ProductType 文本变量8位字符集 产品规格
    XX_RecipeID 文本变量8位字符集 配方ID
    XX_parameter1   非配方生产参数,这里用parameter指代,实际按需命名。
    XX_parameter2   非配方生产参数,这里用parameter指代,实际按需命名。
    XX_parameterN   非配方生产参数,这里用parameter指代,实际按需命名。

    批次的用户归档中控制变量如下:

    Batch用户归档控制变量
    变量名 类型
    XX_UA_Batch_ID 有符号的32位值
    XX_UA_Batch_Job 有符号的32位值
    XX_UA_Batch_Field 文本变量8位字符集
    XX_UA_Batch_Value 文本变量8位字符集

    关于如何使用控制变量操作用户归档,以及封装的操作函数,详见《WinCC配方设计-基于用户归档》中的“如何用控制变量操作用户归档”,这里不再介绍。

    批次表中带有一些参数的记录,这些参数可能是批次开始前的设置值,例如设定产量、生产速度,也可能是批次结束时记录的生产结果,例如实际产量、不合格数。实际操作过程中,可能先输入批次,再设定参数和配方,起初记录的批次可能只有批次名,其他字段的数据都是空值,所以在批次生产结束时,需要再更新一次批次表中的记录,以记录最终的生产结果。

    批次表中不能出现两个重复的批次,记录批次前要用SQL查询是否已存在同名批次,不存在则新建记录,否则更新同名的批次。记录批次函数的代码如下:

    Function RecordBatch(prefix, DSN)
        dim BatchName
        BatchName = HMIRuntime.Tags(prefix& "BatchName").Read
    
        if Trim(BatchName) = "" then '如果批次名为空,则不记录批次
            RecordBatch = -1
            Exit Function
        end if 
    
        Dim cnn, rs, SQL
        Set cnn = CreateObject("ADODB.Connection")
        Set rs = CreateObject("ADODB.Recordset")
    
        '检查是否存在同名批次
        SQL = "select BatchName from "& DSN &" where BatchName = '" & BatchName & "' "
        ConnectDatabase cnn,rs,SQL
        If rs.recordcount>0 Then
            RecordBatch = Update_UA(prefix& "UA_Batch", "BatchName", BatchName)
        else
            RecordBatch = Insert_UA(prefix& "UA_Batch")
        end if
        rs.Close
        cnn.Close
        Set rs = Nothing
        Set cnn = Nothing
    End Function
    

      

    如何记录一个事件

    事件数据库也基于用户归档存储。事件表定义如下:

    Event
    字段 类型 描述
    EventTime 时间日期 时间戳
    BatchName 字符串 批次名
    BatchType 数字(整型) 批次类型
    EventMsg 字符串 事件消息
    StartLogFlag 数字(整型) 开始记录标志
    UserName 字符串 登录用户
    HMIUserName 字符串 设备登录用户
    ProductionState 数字(整型) 生产状态

    向事件数据库写入数据需要通过参数变量和控制变量进行。每台设备要有如下一组对应Event用户归档的变量,如果一个WinCC程序中管理了多台设备,则每台设备对应的变量名要加上设备前缀,这里用“XX_”代替。

    有些变量建立在WinCC内部,在变量作用域中标为“内部”,有些变量来自PLC,在变量作用域中标为“外部”。

    Event用户归档参数变量
    变量名 类型 描述 变量作用域
    XX_EventTime  日期/时间  触发事件时将用脚本写入当前的时间戳。 内部
    XX_BatchName 文本变量8位字符集 批次名,与批次表共用外部变量。 外部
    XX_BatchType 无符号的8位值  批次类型,与批次表共用变量。 外部或内部
    XX_EventMsg  文本变量8位字符集 事件消息  内部
    XX_StartLogFlag  二进制变量  开始记录标志 外部或内部
    @CurrentUserName  文本变量16位字符集 当前WinCC登录的用户名,系统中自带,不需建立,也不需要前缀。  内部
    XX_HMICurrentUser 文本变量16为字符集 设备上触摸屏上登录的用户。 外部
    XX_ProductionState 无符号的8位值  设备的生产状态。 外部

    操作用户归档还需要一组控制变量控制变量如下:

    Event用户归档控制变量
    变量名 类型
    XX_UA_Event_ID 有符号的32位值
    XX_UA_Event_Job 有符号的32位值
    XX_UA_Event_Field 文本变量8位字符集
    XX_UA_Event_Value 文本变量8位字符集

    使用用户归档操作函数,定义记录事件函数,代码如下:

    Function RecordEvent(prefix, eventMsg)
    	dim SWDT, utcTime
    	Set SWDT = CreateObject("WbemScripting.SWbemDateTime")
    	SWDT.SetVarDate Now, True
    	utcTime = SWDT.GetVarDate (False)
    	HMIRuntime.Tags(prefix& "EventTime").Write utcTime
    	HMIRuntime.Tags(prefix& "EventMsg").Write eventMsg
    	RecordEvent = Insert_UA(prefix& "UA_Event")
    End Function
    

     

    参数:

    • prefix:设备的前缀,例如“XX_”。
    • eventMsg:需要记录的事件。

    返回值:

    •  0:记录成功。
    • -1:记录失败。

    何时触发事件和批次的记录

    在开始生产时,设备中会有某个指示启停的变量被置1,结束生产时则被置0。如果有多种批次类型,每个批次类型有不同的启停变量。在VBS全局动作中,把这些变量做为触发器,当变量改变就会触发执行一段代码,这段代码调用StartEndCycle()函数,该函数内再调用RecordEvent()和RecordBatch()函数。

    假设有3个批次类型,对应的变量名如下:

    批次启停变量
    变量名 描述
    XX_StartFlag1 批次类型1启动变量
    XX_StartFlag2 批次类型2启动变量
    XX_StartFlag3 批次类型3启动变量

    将不同的批次类型对应的类型标志、变量名、事件消息添加到数组,对数组遍历,使用相同的代码依次检查每个启停变量,然后触发事件和批次记录。全局VBS动作中的代码如下:

    'File Name:XX_StartEndCycle
    Function action
        If HMIRuntime.Tags("@ServerName").Read <> HMIRuntime.Tags("@LocalMachineName").Read Then
            Exit Function
        End If
        
        'BatchType, TagName, StartMsg, EndMsg
        Dim batchItems
        batchItems = Array(_ 
            Array(1,"StartFlag1",TranslateText("开始类型1批次记录", 2052),TranslateText("结束类型1批次记录", 2052)),_
            Array(2,"StartFlag2",TranslateText("开始类型2批次记录", 2052),TranslateText("结束类型2批次记录", 2052)),_
            Array(3,"StartFlag3",TranslateText("开始类型3批次记录", 2052),TranslateText("结束类型3批次记录", 2052))_
            )
        Call StartEndCycle("XX_", batchItems)
    End Function
    

      

    StartEndCycle()代码如下:

    Sub StartEndCycle( prefix, batchItems )
        If Trim(HMIRuntime.Tags( prefix & "BatchName" ).read) = "" Then '如果批次名为空,则退出函数
            HMIRuntime.Tags( prefix & "BatchType" ).Write 0
            Exit Sub
        end if 
    
        Dim batchItem
        For Each batchItem In batchItems
            If Not TagQcIsBad(prefix & batchItem(1)) Then
                If HMIRuntime.Tags( prefix & batchItem(1) ).Read = 1 Then       '检查触发变量是否为1
                    HMIRuntime.Tags( prefix & "BatchType" ).Write batchItem(0)  '设置批次类型
                    HMIRuntime.Tags( prefix & "StartLogFlag").Write 1
                    Call RecordEvent( prefix, batchItem(2) )                    '记录事件
                    Call RecordBatch( prefix, "UA#"&prefix&"Batch" )
                else
                    If HMIRuntime.Tags( prefix & "BatchType" ).Read = batchItem(0) Then   '检查是否是该批次类型
                        HMIRuntime.Tags( prefix & "StartLogFlag" ).Write 0
                        Call RecordEvent( prefix, batchItem(3) )                '记录事件
                        Call RecordBatch( prefix, "UA#"&prefix&"Batch" )
                        HMIRuntime.Tags( prefix & "BatchType" ).Write 0
                    End If
                End If 
            End If 
        Next
    End Sub
    

      

    批次操作流程

    1. 开始生产一批药之前,首先给制药设备输入这批药的批次号、产品名称、产品规格,以及输入生产的参数和配方。输入批次号时需通过程序查询批次表中是否存储同名的批次,不能有两个重名的批次号。以上内容的输入不分先后顺序,在开始生产之前都可以修改。这时输入的内容并未记入数据库。

    2. 设备开始生产之前可能需要试机,这段时间需保持批次启停指示变量为0,设备应运行在调试模式;或者设计为手动启停批次,使得机器的运转启停不影响批次的启停。完成试机之后,将设备转为自动运行模式,机器启动以后批次指示变量置为1;需手动启动批次的,则在设备的操作屏上点击“启动批次”按钮,将批次启停指示变量置1。

    3. 批次启停指示变量改变后,WinCC的全局动作中的代码将被触发,从而记录批次和事件。此时数据库中还没有这个批次的记录,代码将在批次数据库中新建一条记录,把批次号、产品名称、配方等内容记录到数据库。同时向事件数据库中新增一条数据,记录了批次开始的时间戳。

    4. 在正常生产时,不应再编辑批次号、产品名称等内容,须要通过代码限制界面中的内容输入。

    5. 完成生产之后,随着生产结束自动将批次启停指示变量置为0,或者在设备操作屏上点击“结束批次”手动将变量设为0。

    6. 批次启停指示变量的变化将再次触发全局VBS动作。批次函数中的代码将查询到批次数据库中已存在这个批次号的记录,然后更新数据库中这个批次的内容,最终把批次结果的参数写入到数据库中。而事件数据库中将再新增一条数据,记录批次结束的时间戳。

    7. 为了避免生产完之后设备调试时意外覆盖之前的批次记录,应在生产完之后手动清空批次变量中的值,空的批次不会被记录到数据库,输入重名的批次名也不被程序允许。

    批次输入界面

    批次输入界面如下:

    控件输出值绑定的变量 

    产品名称、产品规格、产品批号和当前配方都是“输入/输出域”控件,在控件的“输出值”属性处分别绑定了变量:ProductName, ProductType, BatchName, RecipeID。示例如下图:

    生产状态是文本列表控件,“输出值”属性绑定了变量ProdutionState,如下:

      以上变量都没有添加变量前缀“XX_”,因为会通过画面窗口控件调用这个画面,在画面窗口的属性中添加前缀,画面的所有变量将自动带上前缀。

    启动批次后禁止操作控件

    灰色的文本控件代表只读,而白色的控件代表可读写。产品名称、产品规格和产品批号三个控件在未启动批次时可编辑,批次启动以后不能被编辑,并且控件颜色变为灰色。批次清空按钮也只能在批次未运行时可按下,批次运行时按钮将被禁用。

    在控件的“允许操作员控制”属性中,设置动态对话框,当前StartLogFlag为0时将改属性设为“是”,为1时设为“否”。

     

     在产品名称、产品规格和产品批号三个控件的“背景颜色”属性中设置动态对话框,当StartLogFlag为0时为白色,为1时为灰色。

     

    输入批次号

     点击产品批号“输入/输出域”控件后,弹出对话框要求输入产品批号,然后对输入的批号检查是否重复。

    Sub OnClick(ByVal Item)                
        Dim BatchName
        BatchName = Trim(Inputbox(TranslateText("请输入产品批号:",2052),TranslateText("输入框",2052),Item.OutputValue))
        If BatchName<>"" Then
            If FindDuplicateBatchName("UA#XX_Batch",BatchName)=0 Then
                HMIRuntime.tags("BatchName").Write BatchName
            End If
        End If
    End Sub
    

      

    检查重复批次的代码如下:

    Function FindDuplicateBatchName(UAName,BatchName)
        FindDuplicateBatchName = 0
        Dim cnn, rs, SQL
        Set cnn = CreateObject("ADODB.Connection")
        Set rs = CreateObject("ADODB.Recordset")
        SQL = "select BatchName from "&UAName&" where BatchName='" & BatchName & "'"
        ConnectDatabase cnn,rs,SQL
        
        If rs.recordcount>0 Then
            Msgbox TranslateText("产品批号重复!", 2052)
            FindDuplicateBatchName = 1
        End If
        rs.Close
        cnn.Close
    End Function
    

      

    如何查询批次

    未完待续...

     

  • 相关阅读:
    正则表达式中?=和?:和?!的理解
    Python isinstance() 函数
    什么是REST架构
    [iOS常见问题] 关于使用QQ做第三方登录的问题!
    js与webview 常用交互代码
    AFNetworking 使用 核心代码
    NSString / NSData / char* 类型之间的转换
    集合视图 代码
    IOS面试问题总结
    UIViewController的生命周期及iOS程序执行顺序
  • 原文地址:https://www.cnblogs.com/yada/p/12447058.html
Copyright © 2011-2022 走看看