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

  

如何查询批次

未完待续...

 

原文地址:https://www.cnblogs.com/yada/p/12447058.html