AdvancedHMI Software
General Category => Support Questions => Topic started by: BarryTemp on August 27, 2013, 09:01:48 AM
-
WARNING: Please be gentle, very much a NOOOOOOOB. Sorry for the long post.
Archie, this product is sheer brilliance.
I have a Compact Logix L32E and a Micrologix1400 SerB.
The code in both PLC's is to put the accumulator of a timer into array "Test[0]" till "Test[200]" for the Compact Logix and "N223:0" till N223:200" for the MicroLogix as fast as possible.
I can connect to both PLC's and receive the tag name and the tag data into 2 separate data grids. I read 201 integers per PLC.
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
I currently run off a timer executing every 5 Seconds which calls ReadCompactLogix() and ReadMicroLogix()
Private Sub ReadCompactLogix()
Dim sTemp As String
Dim iLoop As Integer
EthernetIPforCLXComm1.AsyncMode = True
For iLoop = 0 To 200
sTemp = "Test[" + iLoop.ToString + "]"
EthernetIPforCLXComm1.ReadAny(sTemp, 1)
Next
EthernetIPforCLXComm1.AsyncMode = False
End Sub
Private Sub ReadMicroLogix()
Dim sTemp As String
Dim iLoop As Integer
EthernetIPforPLCSLCMicroComm1.AsyncMode = True
For iLoop = 0 To 200
sTemp = "N223:" + iLoop.ToString
EthernetIPforPLCSLCMicroComm1.ReadAny(sTemp, 1)
Next
EthernetIPforPLCSLCMicroComm1.AsyncMode = False
End Sub
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
I then use the DataReceived event handler as follows:
Private Sub EthernetIPforCLXComm1_DataReceived(ByVal sender As Object, ByVal e As Drivers.Common.PlcComEventArgs) Handles EthernetIPforCLXComm1.DataReceived
Dim sTemp As String
Dim iLoop As Integer
Try
sTemp = e.PlcAddress
Dim iLength As Integer = sTemp.Length
Dim sLoop As String = Mid(sTemp, 6, iLength - 6)
iLoop = CInt(sLoop)
dgvCompactLogix.Item(0, iLoop).Value = e.PlcAddress
dgvCompactLogix.Item(1, iLoop).Value = e.Values(0)
'Calculate the time to return all the variables
If iLoop = 200 Then
If dgvCompactLogix.Item(1, 200).Value > dgvCompactLogix.Item(1, 0).Value Then
txtCompactLogix.Text = dgvCompactLogix.Item(1, 200).Value - dgvCompactLogix.Item(1, 0).Value
Else
txtCompactLogix.Text = dgvCompactLogix.Item(1, 200).Value - dgvCompactLogix.Item(1, 0).Value + 9999
End If
End If
Catch ex As Exception
End Try
End Sub
Private Sub EthernetIPforPLCSLCMicroComm1_DataReceived(ByVal sender As Object, ByVal e As Drivers.Common.PlcComEventArgs) Handles EthernetIPforPLCSLCMicroComm1.DataReceived
Dim sTemp As String
Dim iLoop As Integer
Dim iStringLength As Integer
Dim iStringPosition As Integer
Try
sTemp = e.PlcAddress
iStringLength = sTemp.Length
iStringPosition = InStr(sTemp, ":")
Dim sLoop As String = Mid(sTemp, iStringPosition + 1, iStringLength - iStringPosition)
iLoop = CInt(sLoop)
dgvMicroLogix.Item(0, iLoop).Value = e.PlcAddress
dgvMicroLogix.Item(1, iLoop).Value = e.Values(0)
'Calculate the time to return all the variables
If iLoop = 200 Then
If dgvMicroLogix.Item(1, 200).Value > dgvMicroLogix.Item(1, 0).Value Then
txtMicroLogix.Text = CInt(dgvMicroLogix.Item(1, 200).Value) - CInt(dgvMicroLogix.Item(1, 0).Value)
Else
txtMicroLogix.Text = CInt(dgvMicroLogix.Item(1, 200).Value) - CInt(dgvMicroLogix.Item(1, 0).Value) + 32765
End If
End If
Catch ex As Exception
End Try
End Sub
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Data is returned to the respective grids.
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++Question 1: NumberOfElements
I was hoping to address the array by using the 200 value below. By doing this, it only returns "Test[0]" and "N50:0" only. How do I correctly address NumberOfElements?
Private Sub cmdCompactLogixArray_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdCompactLogixArray.Click
EthernetIPforCLXComm1.AsyncMode = True
EthernetIPforCLXComm1.ReadAny("Test[0]", 200)
EthernetIPforCLXComm1.AsyncMode = False
End Sub
Private Sub cmdMicroLogixArray_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdMicroLogixArray.Click
EthernetIPforPLCSLCMicroComm1.AsyncMode = True
EthernetIPforPLCSLCMicroComm1.ReadAny("N50:0", 200)
EthernetIPforPLCSLCMicroComm1.AsyncMode = False
End Sub
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++Question 2: Subscribe method
In another post, Archie gives an example.
Public Class frmSubscribe
Private SubscriptionID As Integer
Private Sub frmSubscribe_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
EthernetIPforCLXComm1.UnSubscribe(SubscriptionID)
End Sub
Private Sub frmSubscribe_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
EthernetIPforCLXComm1.IPAddress = "192.168.101.253"
SubscriptionID = EthernetIPforCLXComm1.Subscribe("MyTag", 1, 250, AddressOf SubscribedDataReturned)
End Sub
'* Show the value when it is returned
Private Sub SubscribedDataReturned(ByVal sender As Object, ByVal e As MfgControl.AdvancedHMI.Drivers.Common.PlcComEventArgs)
'Me.Text = e.Values(0)
TextBox1.Text = e.Values(0)
End Sub
End Class
Modifications Made to Archies code was EthernetIPforCLXCom1 replaced with EthernetIPforCLXComm1 (Running Ver 3.41 of driver)
There is an error and I do not know how to fix it.
SubscribedDataReturned has a blue squiggle under it and the error is:
Method "Private Sub SubscribedDataReturned(ByVal sender As Object, ByVal e As MfgControl.AdvancedHMI.Drivers.Common.PlcComEventArgs)" does not have a signature compatible with 'Delegate Sub ReturnValues(values() as String)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++Question 3: Performance
In my real life application, I need to read 250 integers as quickly as possible (i.e. every 2 seconds would be great).
What is the best way to handle this? As per timer above OR to use the Subscribe method OR ?????
-
I definitely recommend using the latest version (3.58 as of this posting) because the EthernetIP drivers have been revamped making them more stable and faster.
When reading arrays or consecutive elements, it is much faster to read with a single read:
Dim values() as string
values=EthernetIPforCLXCom1.Read("Test[0]",201)
' values(0) is Test[0]
' values(1) is Test[1]
' etc
Depending on your network speed and processor, you should be able to perform that read at least every 500ms. It is the same for the MicroLogix
Dim values() as string
values=EthernetIPforPLCSLCMicroCom1.Read("N223:0",201)
There are 3 read methods:
Synchronous:
Simplest read method, however ties up UI (User Interface) thread leaving the form unresponsive while waiting for a response from PLC. With the Ethernet driver, typical response is about 5ms, so the thread tie up is practically unnoticeable.
Asynchronous:
Require a call to initiate and an event handler to receive the data. The call to initiate (BeginRead) will return immediately and not tie up the UI thread. This is most obvious in slower communications such as RS232. Ethernet is typically fast enough that there is no noticeable difference between synchronous and asynchronous unless reading very large amounts of data.
Subscriptions:
The are the most complex, but lets the driver handle all of the work and optimize the reads. Currently only one elements at a time can be subscribed to. Does not allow multiple elements in an array to be read with a single subscription. Subscriptions update at the rate of the PollRateOverride as set in the driver properties. Too many subscriptions at a fast rate can consume a lot of bandwidth and slow things down. All of the built in controls use subscriptions in order to ensure the most optimized reading. For example, if one BasicLabel us set to display MyTag[0] and another set to display MyTag[1], the driver will make a single request from the PLC, split the results and send it to the appropriate BasicLabel.
-
Sorry, I am 17 versions behind, we are slow in South Africa.
So if I want to use the subscribe method, I will have to create 250 instances of the Subscribe function. When will the subscribe method handle arrays?
It sounds like the best option for me would be to use Asynchronous read with NumberOfElements with the DataReceived event handler?
Thanks again for this product.
Barry
-
Array handling for subscriptions isn't planned until version 4. If using asynchronous reads with version 3.41, use them with care. There was a major issue when performing a lot of reads in code along with controls on the form. Sometimes it would not return any data and sometimes you would get the sequence number instead of the data. This was the motivation to revamping 3.5 in order to resolve these problems. In 3.5, the Asyncmode property was removed and replaced with Read(synchronous) and BeginRead(asynchronous)
You're not completely 17 versions behind. The versions jumped from 3.43 to 3.5.1. From there up to 3.5.8, it was mainly a series of bug fixes to the new drivers.
-
Thanks for the feedback. I am now using version 358 and there is a dramatic improvement in driver performance. WOW.
It is great that the NumberOfElements function is working.
====================================================================================================================
As per your post, I did the following:
Dim sTemp As String
Dim iLoop As Integer
Dim values1(300) As String
values1 = EthernetIPforPLCSLCMicroCom1.Read("N50:0", 200)
For iLoop = 0 To 199
sTemp = "N50:" + iLoop.ToString
dgvMicroLogix.Item(0, iLoop).Value = sTemp
dgvMicroLogix.Item(1, iLoop).Value = values1(iLoop)
Next
It errors at iLoop = 82
====================================================================================================================
BUT doing this works and returns all the variables:
Dim sTemp As String
Dim iLoop As Integer
Dim values1(300) As String
Dim values2(300) As String
values1 = EthernetIPforPLCSLCMicroCom1.Read("N50:0", 101)
values2 = EthernetIPforPLCSLCMicroCom1.Read("N50:100", 101)
For iLoop = 0 To 100
sTemp = "N50:" + iLoop.ToString
dgvMicroLogix.Item(0, iLoop).Value = sTemp
dgvMicroLogix.Item(1, iLoop).Value = values1(iLoop)
Next
For iLoop = 100 To 199
sTemp = "N50:" + iLoop.ToString
dgvMicroLogix.Item(0, iLoop).Value = sTemp
dgvMicroLogix.Item(1, iLoop).Value = values2(iLoop - 100)
Next
====================================================================================================================