AdvancedHMI Software
General Category => Support Questions => Topic started by: kf4ozb on July 17, 2013, 11:16:12 AM
-
Hiya Archie,
I have a form that has approximately 24 Comboboxes on it that I am populating using the new ReadSynchronous function (Which to this point seems to have fixed the previous sequence numbers being returned, Great job to those who contributed to the fix! ). That being said I do seem to be getting a lot of read failures that return a value of -20. I doubt this has anything to do with the new function. More likely it's due to my network.
I traced this back to the WaitForResponse function. Basically, if I understand the function, you are waiting for 1 second for a response. If no response is received you return the error value of -20.
My questions are. What network topology was the current MaxTicks value optimized for? Do you have an algorithm for determining a value based on different topologies?
Thanks again!
-
Do you also have other controls on the form that is displaying data? It seems that too many requests can go to the PLC and it begins to ignore some of them.
I can't test this right now, but this is something to try. In the driver code, find the PollUpdate subroutine. In that subroutine, there is a call to ReadAny. Try changing that to ReadSynchronous
-
I'm not using a control to read the information. I'm using the ReadSynchronus function. However; I do have it in a for loop with no delay,( other than the processing time it takes to iterate through the loop). I will try adding a sleep at the end of the for loop to give the PLC some breathing room and report back the results.
Do you have any recommendations for the time spacing between requests?
Thanks,
Mickey
Here is the code:
Dim t As String
Dim Read As Boolean
For i = 0 To 23
Read = False
While Not Read
Try
't = frm_csMain.EthernetIPforCLXComm1.ReadAny(Formula_List(i))
t = frm_csMain.EthernetIPforCLXComm1.ReadSynchronous(Formula_List(i), 1)(0) ' Updated to ReadSynchronus as bug fix from Advanced HMI 3.4
If t = "$00$00$00$00$00$00$00$00$00$00" Then t = ""
If isFormulaValid(t, CompoundNumber) Then 'Check to see if formula read is a vaild formula
Read = True
If t <> "" Then 'If Valid and set disable control
With ControlArray(i)
.Enabled = False
.SelectedText = t
End With
Else
ControlArray(i).Enabled = True
End If
End If
Catch ex As Exception
MsgBox(ex.ToString)
Exit For
End Try
''''''ADDING THIS TO SEE IF IT FIXES THE ISSUE'''''''
Sleep (100)
''''''END ADDITION'''''''
End While
Next
-
Just by nature, the ReadSynchronous waits until a response in received before returning from the cal, therefore a delay should not be needed.
One thing to keep in mind about Synchronous reading is that your operator interface will be unresponsive during your read loop.
Is this loop the only read that is occurring? Do you possibly have other forms that are open that could be reading at the same time?
-
Hmm. Well now that you mention it. My main form stays visible and it has about 14 indicators on it, that would continue to poll the system. If I disable the subscriptions to the communications driver, it should stop the advancedHMI components from polling the plc. Correct? Can you still make ReadSynchronous calls 'manually' with the subscriptions disabled, or do I need to use another driver on my sub form?
Thanks for the input!
-
If you DisableSubscriptions on your driver, you can still do read and writes in your own code. Maybe the thing to try is to DisableSubscriptions when your read loop starts, then re-enable them after it is complete.
-
That's what I was thinking. I'll try that and report back.
-
I did some quick testing on version 3.41 with 5 BasicLabels on a form with a PollRateOverride of 10ms. I then put a 20ms timer that read a single value followed by an array of 200 DINT. It ran for a few hours without a single miss in reading.
That version is now posted on sourceforge. If you get a chance, try it out to see if it resolves your issue.
-
Archie,
I was setting up a spare PLC to test this program on and I accidentally stumbled across a condition that causes this read failed status code -20 EVERY time. Apparently, if you try to read an address with ReadSynchronous that does not exist this error is thrown. I'm looking through your components now to see how you handle tags that do not exist.
I don't know if this is the root cause of the -20 error that I've been experiencing. I don't really think that it is, because if it were I would receive this error every time I clicked the schedule button, which runs my code.
I'll let you know what else I find.
-
Ok.. I understand now why I'm getting -20 instead of the error the tag is invalid. I went through the EthernetIPforCLXComm source and found that in the Subroutine 'DataLinkLayer_DataReceived' a comparison is made to see if the data received was an internal request. A ReadSynchronus call is sent with the InternalRequest property set to false.
The code that is being run when this occurs is below:
'*****************************
'* Failed Status was returned
'*****************************
Dim d() As String = {DecodeMessage(StatusByte) & " CIP Status " & StatusByte}
If Not PLCAddressByTNS(e.TransactionNumber And 255).InternalRequest Then
If Not DisableEvent Then
Dim x As New MfgControl.AdvancedHMI.Drivers.Common.PlcComEventArgs(d, PLCAddressByTNS(e.TransactionNumber And 255).TagName, e.TransactionNumber And 255)
If m_SynchronizingObject IsNot Nothing Then
Dim Parameters() As Object = {Me, x}
m_SynchronizingObject.BeginInvoke(drsd, Parameters)
Else
'TODO : This should raise the Com Error event
RaiseEvent DataReceived(Me, x)
End If
End If
Else
For i As Integer = 0 To SubscriptionList.Count - 1
If SubscriptionList(i).PLCAddress.TagName = PLCAddressByTNS(e.TransactionNumber And 255).TagName Then
m_SynchronizingObject.BeginInvoke(SubscriptionList(i).dlgCallBack, New Object() {d})
End If
Next
End If
The lines in Green are the code that is being evaluated when I receive the -20 error. Ultimately, it seems to me different information is returned when the request is external vs an internal request. The question is then, how do I get a more detailed reason of why the read failed? Can this be done just by making the Internal Request Property True?
-
Is this still happening with the version 3.41?
The internalRequest is used to indicate that it is a read for updating subscriptions. The main difference is that it will send the resulting data out to the subscriptions, which in turn updates the controls.
-
It's happening with 3.41. I have not seen this error using basic labels or any other components. It only occurs when I'm using a ReadSyncrhonous, and previous to the update a ReadAny call. I have seen these components display "Error getting Tag" and then eventually populate data though.
The frequency varies. I've had instances where I get the error multiple times back to back, and other instances where only one error occurs. As stated previously I stumbled accross a way to cause the error every single time the read is called, simply try to read a tag that does not exist. (i.e. Me.EthernetIPforCLXComm1.ReadSynchronous("aHMI_ROCKS", 1)(0) cause the -20 error if "aHMI_ROCKS" is not defined in the PLC) I don't think this is the cause of the intermittent -20 error I'm experiencing, because the error is intermittent and if you try to read a non-existent tag it fails continuously.
I believe the components are designed with some error decoding and handling that you don't get when you just use a read command. Which is fine, if I know how to decode these errors and subsequently handle them.
-
I suspect what is happening is the reads from multiple driver instances are sending more commands than the controller can process.
If you have a MainForm with BasicLabels being updated and another form that you are calling the ReadSynchronous in code, try to reference the driver instance on the MainForm
MainForm.EthernetIPforCLXComm1.ReadSynchronous("MyTag",1)(0)
That way everything will channel through the same instance and be better regulated in sending the requests to the PLC.
Or you could hide the MainForm and it will stop the read updates to the BasicLabels.
-
That's what I'm doing. I only have the one driver. I just change it's IP to read from different PLC's.
-
I am running out of ideas since I cannot replicate it on my setup. If you want, you can send me your project along with your RSLogix program. You can strip out all of the ladder code because I would only need the tags.
I do have a version 3.5.1 that is not ready for release. It should get around this problem. Maybe this weekend I can release part of it as an alpha version for you to test out.