AdvancedHMI Software
General Category => Support Questions => Topic started by: bobobo on October 10, 2015, 11:10:15 AM
-
Hi
My application gets unresponsive and for error tracking I made an experiment and got a result that I think indicates a bug in the component or driver...
I started a new Adv.HMI 3.99a project. I added only a basiclabel to see that plc communication is working.
Then I added a Datasubscriber2, a standard Timer (interval 1000) and a textbox.
Dim rate As Integer
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
TextBox1.Text = rate
rate = 0
End Sub
Private Sub DataSubscriber21_DataReturned(sender As Object, e As Drivers.Common.PlcComEventArgs) Handles DataSubscriber21.DataReturned
rate = rate + 1
End Sub
The displayed rate indicates (approx) how many calls DataReturned gets per second:
1 valid PLCaddress in DataSubscriber: 4 events/s
2 valid PLCaddresses : 12 events/s
3 valid PLCaddresses : 24 events/s
2 valid PLCaddresses and 1 invalid PLCaddress : increasing slowly over 40sec to rate of 300-330events/s
13 valid PLCaddresses: 360 events/s
13 valid PLCaddresses and 1 invalid : increasing to about 2000 events/s
All above numbers with PollRateOverride (driver) at 500, and PollRate in DataSubscriber at 0.
(With one PLCaddress in DataSubscriber and a PollrateOverride at 100 I get 20 events/s (correctly 5 times above test)
With PollrateOverride 1000 I get 2 events/s.
Equal result if I change PollrateOverride to 0 and set 100/500 and 1000 at DataSubscriber PollRate.)
What do you think?
-
Keep in mind that Windows Timers are non-determistic, so you will get some jitter in your 1 second timer. This test will give you a bit more truer reading:
Private sw As New Stopwatch
Private EventsPerSecond As Integer
Private RunningAverage, AverageCount As Integer
Private Sub MainForm_Load(sender As Object, e As EventArgs) Handles MyBase.Load
sw.Start()
End Sub
Private Sub DataSubscriber21_DataReturned(sender As Object, e As Drivers.Common.PlcComEventArgs) Handles DataSubscriber21.DataReturned
If sw.ElapsedMilliseconds >= 1000 Then
Label1.Text = EventsPerSecond
RunningAverage += EventsPerSecond
AverageCount += 1
If AverageCount >= 10 Then
Label2.Text = RunningAverage / AverageCount
RunningAverage = 0
AverageCount = 0
End If
EventsPerSecond = 0
sw.Reset()
sw.Start()
Else
EventsPerSecond += 1
End If
End Sub
You will need to add 2 labels to your form.
The expected result should be
1000/PollRateOverride * (NumberOfElements in PLCAddressValueItems)
I tested with a 500 PollRateOverrides and 3 items and my running average was 6.x
1000/500 * (3) = 6
-
I added an additional invalid tag and I am still getting 6.x in my running average.
I am testing on the unreleased version of 3.99b and the EthernetIPforCLX driver which could possibly have an effect.
Which driver are you using?
-
Here is another variation on the test:
Private sw2 As New Stopwatch
Private Sub DataSubscriber21_DataReturned(sender As Object, e As Drivers.Common.PlcComEventArgs) Handles DataSubscriber21.DataReturned
If e.PlcAddress = "DINTTag" Then
Label4.Text = sw.ElapsedMilliseconds
sw.Reset()
sw.Start()
End If
End Sub
This will give you the number of ms in between updates of a particular tag
-
As most of the time, really impressive quick answers!
Results with the code from your first test:
With 3 valid tags: 23.0
With 2 valid and one invalid: 334
...
-
Which driver are you using?
-
Sorry, I wrote it in the first post, but then edited the text and accidently removed that info...
Twincat driver.
-
I did a quick test with the TwinCAT driver and see the abnormal results. I'll dig into this to locate the problem
-
When I removed the first basiclabel from the form, so that I only have the Datasubscriber21, Label1, Label2 and TwinCatCom1 the number dropped from 23 to 17-17.3 with 3 valid addresses.
So it seems that also addresses not in the Datasubscriber trigger the DataSubscriber.Datareturned ...?
-
Try this to see what effect it has:
- In Solution Explorer, open AdvancedHMIDrivers\TwinCAT\TwinCATCom.vb
- Go to line 729 and insert this one line of code as shown:
'*************************************************************
'* Next step is to prepare for Group Reads
'*************************************************************
GroupedSubscriptionReads.Clear() 'Add this line
Dim i As Integer
-
After your suggested change it seems to work as long as I only enter addresses to subscribe from in the designer property manager.
I would like to add variables from my code (since number of elements is not working it would be handy to subscribe to arrays by for-loops)
but then it starts making trouble again.
If I add ".var1" and ".var2" in the property manager and then add this code:
Private Sub MainForm_Load(sender As Object, e As EventArgs) Handles MyBase.Load
DataSubscriber21.PLCAddressValueItems.Add(New AdvancedHMIDrivers.PLCAddressItem(".var3"))
DataSubscriber21.PLCAddressValueItems.Add(New AdvancedHMIDrivers.PLCAddressItem(".var4"))
sw.Start()
End Sub
I set a breakpoint and Watch TwinCATCom1.SubscriptionList it looks like this:
(0): ".var1"
(1): ".var1"
(2): ".var1"
(3): ".var2"
(4): ".var2"
(5): ".var2"
(6): ".var3"
(7): ".var3"
(8): ".var4"
The list seems to grow exponantially the more variables I add from code.
In above example I also get 45 insted of 8 or 16 datareturned-events per second with pollrateoverride 500.
This code has the same behaviour:
Public Sub New()
' This call is required by the designer.
InitializeComponent()
Dim PlcAddressItem3 As AdvancedHMIDrivers.PLCAddressItem = New AdvancedHMIDrivers.PLCAddressItem()
Dim PlcAddressItem4 As AdvancedHMIDrivers.PLCAddressItem = New AdvancedHMIDrivers.PLCAddressItem()
PlcAddressItem3.LastValue = Nothing
PlcAddressItem3.NumberOfElements = 1
PlcAddressItem3.PLCAddress = ".var3"
PlcAddressItem3.ScaleFactor = 1.0R
PlcAddressItem3.ScaleOffset = 0.0R
PlcAddressItem3.SubscriptionID = 0
PlcAddressItem4.LastValue = Nothing
PlcAddressItem4.NumberOfElements = 1
PlcAddressItem4.PLCAddress = ".var4"
PlcAddressItem4.ScaleFactor = 1.0R
PlcAddressItem4.ScaleOffset = 0.0R
PlcAddressItem4.SubscriptionID = 0
DataSubscriber21.PLCAddressValueItems.Add(PlcAddressItem3)
DataSubscriber21.PLCAddressValueItems.Add(PlcAddressItem4)
' Add any initialization after the InitializeComponent() call.
End Sub
Private Sub MainForm_Load(sender As Object, e As EventArgs) Handles MyBase.Load
sw.Start()
End Sub
-
Edit TwinCATCom.vb, go to line 489 and make this modification:
If UsedSymbols.Count > 0 Then
For k = 0 To SubscriptionList.Count - 1
If String.Compare(SubscriptionList(k).Symbol.Name, plcAddress, True) = 0 And SubscriptionList(k).dlgCallBack = callback Then
SubExists = True
Exit For
End If
Next
End If
-
It was not enough to change this row:
If String.Compare(SubscriptionList(k).Symbol.Name, plcAddress, True) = 0 And SubscriptionList(k).dlgCallBack = callback Then
But I tried to change also the first if-statement to this:
If UsedSymbols.Count > 0 Then
For k = 0 To SubscriptionList.Count - 1
If String.Compare(SubscriptionList(k).Symbol.Name, plcAddress, True) = 0 And SubscriptionList(k).dlgCallBack = callback Then
SubExists = True
Exit For
End If
Next
End If
Then there is no duplicates made in the subscription list.
I still have too many calls to DataReturned in my main application (test application seems to be ok now). But I ssupect my own written AlarmSubsctiption routine, so I have to dig more into it.
Another issue:
After working a while in the application (Happened in both my main app and my test app) I get following "Object does not match target type" in the Collection editor for plcadress in DataSubscriber2. I have got it working again in a few different ways, but the most effective and so far permanent solution has been to comment this row out:
'<System.ComponentModel.TypeConverter(GetType(PLCAddressItemTypeConverter))> _
from PLCAddressItem.vb
In the test app I have not made any new controls or changes to Adv.HMI code besides what have been discussed above in this forum-thread, but anyway I got the "Object does not match target type"
-
This is an issue with Visual Studio when modifying the drivers. Simply by exiting Visual Studio and opening again will resolve this.
-
What do you think about my change to the IF statement? Does it make sense with regards to your intended use for each variables?
-
I was comparing the code you posted to what I posted and I do not see any difference? Am I missing something?
-
Argh. Copy paste error by me.
I changed first IF to check subscriptionlist.count instead of usedsymbols.count
Several copies of each plcaddress were added to the subscriptionlist before usedsymbols got above 0.
(sent from Phone)
-
You are right. I'm not even sure what the purpose of the first IF statement was. I think it can be eliminated all together.
-
I found that above changes makes the subscriptionlist in TwincatCom1 to be correct, but the subscriptionlist in subscriptionhandler is still populated with lots of duplicates.
Public Sub SubscribeTo(ByVal PLCAddress As String, ByVal callBack As EventHandler(Of SubscriptionHandlerEventArgs), ByVal propertyName As String)
'* Check to see if the subscription has already been created
Dim index As Integer
While index < m_SubscriptionList.Count AndAlso (m_SubscriptionList(index).CallBack <> callBack Or m_SubscriptionList(index).PropertyNameToSet <> propertyName)
index += 1
End While
'* Already subscribed and PLCAddress was changed, so unsubscribe
If (index < m_SubscriptionList.Count) AndAlso m_SubscriptionList(index).PLCAddress <> PLCAddress Then
m_CommComponent.Unsubscribe(m_SubscriptionList(index).NotificationID)
m_SubscriptionList.RemoveAt(index)
End If
'* Is there an address to subscribe to?
If (PLCAddress IsNot Nothing) AndAlso (String.Compare(PLCAddress, "") <> 0) Then
Try
If m_CommComponent IsNot Nothing Then
'* If subscription succeedded, save the subscription details
Dim temp As New SubscriptionDetail(PLCAddress, callBack)
temp.PropertyNameToSet = propertyName
If PLCAddress.ToUpper.IndexOf("NOT ") = 0 Then
temp.Invert = True
End If
m_SubscriptionList.Add(temp)
InitializeTryTimer(500)
Else
OnDisplayError("CommComponent Property not set")
End If
Catch ex As MfgControl.AdvancedHMI.Drivers.Common.PLCDriverException
'* If subscribe fails, set up for retry
InitializeSubscribeTry(ex, PLCAddress)
End Try
End If
End Sub
I don't see where this code stops duplicates except for the comment?
-
The last If-Then should probably be wrapped in another condition:
'* Make sure subscription doesn't already exist
If index >= m_SubscriptionList.Count Then
'* Is there an address to subscribe to?
If (PLCAddress IsNot Nothing) AndAlso (String.Compare(PLCAddress, "") <> 0) Then
-
Now i receive the correct number of datareturned-events in my main application!
112 events per second instead of a couple of thousands...
:)
Thanks for help
-
Thanks for the patience and feedback to help get that corrected.