Blog

Iconics, VBA, VBScript, and Writing to OPC Tags

Iconics, VBA, VBScript, and Writing to OPC Tags

Background

DMC has often had to download a high number of values from a SQL server to an OPC server. In the past, this had usually been done with VBA code that was called from an Iconics HMI screen. The code looped through about 600 tags in less than a minute. The VBA code was always executing locally (on the same PC) as the OPC server it was writing to.

For a particular application, the HMI architecture switched to using WebHMI. Therefore, the VBA code needed to be converted to VBScript for compatibility with WebHMI. When a Graphworx WebHMI display is opened in a web browser on a thin client, the VBScript is executed on the thin client and not local to the OPC server, which is running on the WebHMI server.

As we implemented and tested our original VBScript, we experienced extremely slow execution time. The remote execution of the VBScript (whether in a client browser or on a remote Graphworx runtime) was taking more than 10 times as long as when we ran the same script locally on the server where the OPC server resided.

Original Approach

The original approach to writing to an OPC tag in the VBScript is captured in the subroutine below. Notice that one tag is accessed in the client.RequestDataPoint() function. When this subroutine is executed, it creates a subscription to an OPC tag that is not already subscribed to as an object on the display. It writes to the OPC tag and then releases the subscription as it exits the subroutine. According to Iconics, the releasing of the subscription has a time delay associated with it that is longer when the script is being executed on a remote client. Therefore, the extremely slow execution time experienced in the recipe download script was due to the extended delay of releasing the subscription of an OPC tag at the end of each single write.

' Write OPC tag. Return false if error is detected
Sub OPC_Write (Tag, Value)

  Set client = CreateObject("GenClientWrapper.Client") 
  
  ' Try to add tag
  On Error Resume Next
  Dim dp 
  Set dp = client.RequestDataPoint(Tag, 100, 0) 

  If dp Is Nothing Then
   MsgBox "Tag " & Tag & " not found!", vbCritical, "Sub: OPC_Write"
  Else
   dp.Value = Value
  End If
End Sub

Resolution Approach

The new approach to writing to an OPC tag in the VBScript is captured in the subroutine below called “OPC_Write2.” The key difference with this approach is that tag subscriptions are aggregated into a global array and held throughout the whole download sequence. Tag subscriptions are not released until the whole download script has completed, and thus no noticeable subscription release delay is experienced between individual tag writes or even at the end of the download sequence.

Data is passed to the subroutine in the same manner as the older subroutine, but some additional arguments are passed in with the tag and value. “myDataPoints” is a global array of 600 and myIndex is a global variable that is incremented every time “OPC_Write2” is called. The size of “myDataPoints” is set so that it is larger than the total number of tags to be written. Each piece of data to be written to an OPC tag is added to the array with Set myDataPoints(myIndex) = myClient.RequestDataPoint(Tag, 100, 0). “myIndex” is then incremented every time OPC_Write2 is called so that the next time OPC_Write2 is called myClient.RequestDataPoint() is assigned to the next index in the array. Because myClient.RequestDataPoint() is being assigned to a global array we maintain the scope of the function. This means that the subscription is maintained and the delay that was experienced when unsubscribing to a tag and checking for pending writes will no longer occur.

Sub OPC_Write2 (Tag, Value, ByRef myClient, ByRef myDataPoints, ByRef myIndex)
	
	' Try to add tag
	On Error Resume Next
	Set myDataPoints(myIndex) = myClient.RequestDataPoint(Tag, 100, 0) 

	If myDataPoints(myIndex) Is Nothing Then
		MsgBox "Tag " & Tag & " not found!", vbCritical, "Sub: OPC_Write"
	Else
			 myDataPoints(myIndex).Value = Value
	End If

	myIndex = myIndex + 1

End Sub

Learn more about DMC's Iconics programming services.

Comments

There are currently no comments, be the first to post one.

Post a comment

Name (required)

Email (required)

CAPTCHA image
Enter the code shown above: