AdvancedHMI Software
General Category => Support Questions => Topic started by: Randy on August 16, 2013, 12:03:06 PM
-
There is a problem with EthernetIPforCLXCom.vb ComErrorHandler
Responded(e.TransactionNumber) (2nd line)
e.TransactionNumber is a UShort but Responded is only dimensioned to 255
Several times now my program has stopped (in the VB2010 Express IDE with standard error handler settings) at Responded(e.TransactionNumber) because e.TransactionNumber > 255. So there may be 2 issues, one with the out of bounds and the other with the failure of error handling to kick this error back to a real error handler.
Some other less important issues:
With a 1756-L61 and 1756-ENBT/A I keep getting many Open Errors (after last night 45000) as reported by the PLC web page Diagnostic overview.
This is what I am doing:
PLC.REAL_N = 1560
PLC.DINT_N = 1000)
frmLoad.EthernetIPforCLXCom1.Write("HMI.TRIGGER", 1)
Thread.Sleep(150)
sHMI_REAL = frmLoad.EthernetIPforCLXCom1.Read("HMI.REAL", PLC.REAL_N)
sHMI_DINT = frmLoad.EthernetIPforCLXCom1.Read("HMI.DINT", PLC.DINT_N)
It seems to work OK, but the Open Errors don't give me a lot of confidence.
I am running this once a second. I am a bit surprised at the high PC CPU usage this requires during the read, but it does work.
It takes about 200 msec for the reads.
I have also found that a Read of a Bool array doesn't work. I don't know if this hasn't been implemented or is a bug.
When you put out the next version, it would make me more confident if it didn't have any compiler warnings.
Keep up the great work. This is a really cool project.
-
In the ComError, this is how the line is supposed to read:
Responded(e.TransactionNumber And 255) = True
Is the 200ms you come up with including the sleep(150)? A typical single read should take less than 10ms. If you Wireshark the packets, you should be able to see the time in between the 2 reads that will give you an accurate read time.
-
The 200 msec is just for the reads, not including the sleep. Those are arrays of 1560 and 1000 elements.
-
With a 1756-L61 and 1756-ENBT/A I keep getting many Open Errors (after last night 45000) as reported by the PLC web page Diagnostic overview.
This is what I am doing:
PLC.REAL_N = 1560
PLC.DINT_N = 1000)
frmLoad.EthernetIPforCLXCom1.Write("HMI.TRIGGER", 1)
Thread.Sleep(150)
sHMI_REAL = frmLoad.EthernetIPforCLXCom1.Read("HMI.REAL", PLC.REAL_N)
sHMI_DINT = frmLoad.EthernetIPforCLXCom1.Read("HMI.DINT", PLC.DINT_N)
It seems to work OK, but the Open Errors don't give me a lot of confidence.
I am running this once a second. I am a bit surprised at the high PC CPU usage this requires during the read, but it does work.
It takes about 200 msec for the reads.
I tried to replicate this using the following code with a 1 second timer. It ran for 3 hours and reported over 43000 messages sent and received without any Open or Close errors:
Private Sub Timer1_Tick(sender As System.Object, e As System.EventArgs) Handles Timer1.Tick
EthernetIPforCLXCom1.Write("HMITag", 1)
Threading.Thread.Sleep(150)
Me.Text = EthernetIPforCLXCom1.Read("RealTag")
Me.Text &= " " & EthernetIPforCLXCom1.Read("DINTTag")
End Sub
Are you maybe running through a remote connection or something that would cause delays in the network? The latest release only allows 150ms to get a response from each packet. After 2 tries, it times out and closes the connection. I will increase that to 250ms for the next release.
The reading of large arrays has to receive the information in partial packets. If you are reading 1500 elements, it may require 5 or 6 packets to get all of the information, therefore 50ms+ can be expected on a very lightly loaded network.
-
I also tried the Boolean array and it is working for me. How many bits are you reading?
This is the code I tested with:
Dim d() As String = EthernetIPforCLXCom1.Read("BoolArray[0]", 5)
-
I used your example and now I can read BOOL arrays too! Originally I couldn't find any examples of reading arrays and found that giving the name of the array worked for DINT and REAL. I never understood that I needed to specify the first element with "Bracket 0 Bracket". So what I was doing for DINT and REAL worked, but not for BOOL. The Open Errors I was seeing was just a coincidence and not a problem with AHMI. The PLC I was using had some produced/consumed tags and its partner PLC was disconnected. I mistakenly thought the errors were coming from AHMI since I had never seen them before then. My 200 msec read times are for 22 CIP blocks, if I did the math right (480 bytes / block) In the ethernet world that seems like an eternity for such little data (10.5 kbytes), but in the PLC CIP world, maybe that is normal. I have also found that my thread.sleeps are causing high cpu usage. I don't understand that yet, but AHMI seems to be working fine. I plan on using a lot of coding for PLC communications instead of the built in components. If there are some code examples of reading/writing tags & arrays and other coding tips and tricks I would appreciate it if you can point me in that direction. Thanks for your help.
-
The fastest time I have been able to get from one packet to reading another is 6ms. That was on a test PLC with essentially no program. I would guess that time can increase as the PLC program grows in size and has more to process. I have also seen cases where Ethernet IO was used on compactLogix and the HMI was on the same network. This drastically affected the speed.
As for tips, the most common question asked is how to read program scope tags. This is the format for that:
PROGRAM:ProgramName.MyTag
Subscriptions are the most efficient method to get data because the driver has built in logic to combine multiple subscriptions into single reads and they also update on a background thread, so they do not tie up the UI thread like a Read does. The latest version now has a DataSubscriber component that makes subscriptions much easier.
-
I am using another thread to do the array reads. It appears to work OK. There is no theoretical problem with doing that is there?
-
The latest release of the ControlLogix driver was restructured to handle reading from multiple threads. Versions prior to 3.5 will run into problems, but 3.51 and later should work fine.
-
I found a new problem in ExtractData
This is another case where the program just stopped at that line and didn't kick back to an errorhandler.
Case &HD3 '* BOOL Array
Dim x, i, l As UInt32
Dim CurrentBitPos As UInt16 = BitIndex
For j As Integer = 0 To ((returnedData.Length - startIndex) / 4) - 1
x = BitConverter.ToUInt32(returnedData, (j * 4 + startIndex))
While CurrentBitPos < BitsPerElement
l = (2 ^ (CurrentBitPos))
result(i) = (x And l) > 0
i += 1
CurrentBitPos += 1
End While
CurrentBitPos = 0
Next
IndexOutofRangeException
i = 31
in line:
result(i) = (x And l) > 0
in above code
Dim result(ElementsToReturn) As String
ElementsToReturn = 30
I got there with this:
For i = 0 To 10
Dim dT() As String = frmLoad.EthernetIPforCLXCom1.Read("HMI.BOOL[" & i & "]", 1)
Next
BOOL is an array in a UDT called HMI
-
I have not found a way to set a single element of a multielement array. For example:
Dim BI() As Integer = {1}
Dim BSng() As Single = {1}
Dim BStr() As String = {"1"}
Dim k As Integer
k = frmLoad.EthernetIPforCLXCom1.Write("HMI.BOOL[0]", 1)
k = frmLoad.EthernetIPforCLXCom1.Write("HMI.BOOL[0]", 1, BI)
k = frmLoad.EthernetIPforCLXCom1.Write("HMI.BOOL[0]", 1, BSng)
k = frmLoad.EthernetIPforCLXCom1.Write("HMI.BOOL[0]", 1, BStr)
None of these methods work. k always returns 0.
Actually the first method worked a time or two, but not reliably, and once the bit was set, I could never set it back to 0.
I have also experienced some weirdness when single stepping through the program. Sometimes it works OK, but then will often stop at a end synclock or at
DLL(MyDLLInstance).WriteTagValue(tag, StringVals, numberOfElements, SequenceNumber)
with a NullReferenceException was unhandled.
it looks like DLL.EIPEncap.SessionHandle = 0
-
I have also experienced some weirdness when single stepping through the program. Sometimes it works OK, but then will often stop at a end synclock or at
DLL(MyDLLInstance).WriteTagValue(tag, StringVals, numberOfElements, SequenceNumber)
with a NullReferenceException was unhandled.
it looks like DLL.EIPEncap.SessionHandle = 0
It is tricky to single step with an Ethernet/IP driver because it times out fairly quickly and the PLC closes the connection. So if you take more than about 5 seconds stepping through, the read/write will fail.
-
I found a new problem in ExtractData
This is another case where the program just stopped at that line and didn't kick back to an errorhandler.
Case &HD3 '* BOOL Array
Dim x, i, l As UInt32
Dim CurrentBitPos As UInt16 = BitIndex
For j As Integer = 0 To ((returnedData.Length - startIndex) / 4) - 1
x = BitConverter.ToUInt32(returnedData, (j * 4 + startIndex))
While CurrentBitPos < BitsPerElement
l = (2 ^ (CurrentBitPos))
result(i) = (x And l) > 0
i += 1
CurrentBitPos += 1
End While
CurrentBitPos = 0
Next
IndexOutofRangeException
i = 31
in line:
result(i) = (x And l) > 0
in above code
Dim result(ElementsToReturn) As String
ElementsToReturn = 30
I got there with this:
For i = 0 To 10
Dim dT() As String = frmLoad.EthernetIPforCLXCom1.Read("HMI.BOOL[" & i & "]", 1)
Next
BOOL is an array in a UDT called HMI
I tried 2 different scenarios with reading BOOL arrays and both worked correctly. Is there maybe other reads occurring at the same time?
For i = 0 To 10
Dim dT() As String = EthernetIPforCLXCom1.Read("BOOLArray[" & i & "]", 1)
Me.Text &= dT(0)
Next
Dim x() As String
x = EthernetIPforCLXCom1.Read("BoolArray[0]", 50)
-
I have not found a way to set a single element of a multielement array. For example:
Dim BI() As Integer = {1}
Dim BSng() As Single = {1}
Dim BStr() As String = {"1"}
Dim k As Integer
k = frmLoad.EthernetIPforCLXCom1.Write("HMI.BOOL[0]", 1)
k = frmLoad.EthernetIPforCLXCom1.Write("HMI.BOOL[0]", 1, BI)
k = frmLoad.EthernetIPforCLXCom1.Write("HMI.BOOL[0]", 1, BSng)
k = frmLoad.EthernetIPforCLXCom1.Write("HMI.BOOL[0]", 1, BStr)
None of these methods work. k always returns 0.
I have been able to replicate this and working on a fix
-
Here are a few comments:
The Default Buttton ForeColor is Active Caption Text instead of ControlText.
By Default the label on a new button is almost impossible to read. I am not sure how the default gets set in AHMI, But it may be a good idea to have the default more readable.
On Your machine Active Caption Text may be set to a different color. On mine (windows default) it is white.
I have been struggling with PC CPU usage issues. My goal is to have a background thread read some arrays a couple of times a second. I can do this but so far all my attempts have resulted in high CPU usage. Perhaps
you have some insight on this. Consider the following code:
Dim PLC_Run As Boolean
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Read_PLC()
End Sub
Private Sub Read_PLC()
On Error GoTo Err_Sub
Dim sw As New Stopwatch
sw.Start()
Dim dB() As String = Me.EthernetIPforCLXCom1.Read("HMI.BOOL[0]", 2048)
Dim dR() As String = Me.EthernetIPforCLXCom1.Read("HMI.REAL[0]", 1560)
sw.Stop()
Me.lblTime.Text = sw.ElapsedMilliseconds
Exit_Sub:
Exit Sub
Err_Sub:
Debug.Print("Read_PLC " & Err.Description)
Resume Next
Resume
End Sub
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
PLC_Run = True
Do While PLC_Run
Read_PLC()
Application.DoEvents()
Loop
End Sub
Private Sub btnStop_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnStop.Click
PLC_Run = False
End Sub
Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
PLC_Run = True
Do While PLC_Run
Read_PLC()
Threading.Thread.Sleep(100)
Application.DoEvents()
Loop
End Sub
I have found that a single click of Button1 will cause the PC CPU usuage to jump to 50-60% on a dual core cpu and stay that way for 20 seconds.
A button2 click puts it in a loop where the reads happen continuously. In that case the PC cpu stays at about 10% until I click Stop at which time the CPU goes up to 50% for 10 seconds. During this continuous poll
the PLC CPU goes to 40%.
A button3_click also cause high CPU. If I comment out the Read_PLC the CPU drops to < 10%.
The important point is that a thread.sleep by itself causes the cpu to drop as you would expect, but if Read_PLC is involved with a thread.sleep the cpu jumps up.
This has the same behavior if I run this in a different thread.
I am surprised you can't replicate the problems with:
For i = 0 To 10
Dim dT() As String = frmLoad.EthernetIPforCLXCom1.Read("HMI.BOOL[" & i & "]", 1)
Next
Maybe it is because it is part of a UDT
Try this in a .L5X:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<RSLogix5000Content SchemaRevision="1.0" SoftwareRevision="19.01" TargetName="HMI" TargetType="DataType" ContainsContext="true" Owner="., ." ExportDate="Tue Aug 20 09:05:56 2013" ExportOptions="References
DecoratedData Context Dependencies ForceProtectedEncoding AllProjDocTrans">
<Controller Use="Context" Name="HMI">
<DataTypes Use="Context">
<DataType Use="Target" Name="HMI" Family="NoFamily" Class="User">
<Members>
<Member Name="REAL" DataType="REAL" Dimension="1560" Radix="Float" Hidden="false" ExternalAccess="Read/Write"/>
<Member Name="BOOL" DataType="BOOL" Dimension="2048" Radix="Decimal" Hidden="false" ExternalAccess="Read/Write"/>
<Member Name="SINT" DataType="SINT" Dimension="1" Radix="Decimal" Hidden="false" ExternalAccess="Read/Write"/>
<Member Name="INT" DataType="INT" Dimension="1" Radix="Decimal" Hidden="false" ExternalAccess="Read/Write"/>
<Member Name="DINT" DataType="DINT" Dimension="1" Radix="Decimal" Hidden="false" ExternalAccess="Read/Write"/>
<Member Name="LINT" DataType="LINT" Dimension="1" Radix="Decimal" Hidden="false" ExternalAccess="Read/Write"/>
<Member Name="STRG" DataType="STRING" Dimension="1" Radix="NullType" Hidden="false" ExternalAccess="Read/Write"/>
<Member Name="N_REAL" DataType="DINT" Dimension="0" Radix="Decimal" Hidden="false" ExternalAccess="Read/Write"/>
<Member Name="N_BOOL" DataType="DINT" Dimension="0" Radix="Decimal" Hidden="false" ExternalAccess="Read/Write"/>
<Member Name="N_SINT" DataType="DINT" Dimension="0" Radix="Decimal" Hidden="false" ExternalAccess="Read/Write"/>
<Member Name="N_INT" DataType="DINT" Dimension="0" Radix="Decimal" Hidden="false" ExternalAccess="Read/Write"/>
<Member Name="N_DINT" DataType="DINT" Dimension="0" Radix="Decimal" Hidden="false" ExternalAccess="Read/Write"/>
<Member Name="N_LINT" DataType="DINT" Dimension="0" Radix="Decimal" Hidden="false" ExternalAccess="Read/Write"/>
<Member Name="N_STRG" DataType="DINT" Dimension="0" Radix="Decimal" Hidden="false" ExternalAccess="Read/Write"/>
<Member Name="Z_TIMER" DataType="TIMER" Dimension="0" Radix="NullType" Hidden="false" ExternalAccess="Read/Write"/>
<Member Name="ZZZZZZZZZZHMI15" DataType="SINT" Dimension="0" Radix="Decimal" Hidden="true" ExternalAccess="Read/Write"/>
<Member Name="Z_TRIGGER" DataType="BIT" Dimension="0" Radix="Decimal" Hidden="false" Target="ZZZZZZZZZZHMI15" BitNumber="0" ExternalAccess="Read/Write"/>
</Members>
</DataType>
</DataTypes>
</Controller>
</RSLogix5000Content>
Import as UDT.
Then create a tag called HMI of that UDT type and try the code again. it always breaks for me.
As I said earlier I also have a lot of concerns with the unhandled exceptions I have experienced. As you know an unhandled exception is death to production code.
It appears that
Private Sub DataLinkLayer_DataReceived(ByVal sender As Object, ByVal e As MfgControl.AdvancedHMI.Drivers.Common.PlcComEventArgs)
could benefit from an error handler. You may know of other code entry points (especially from other threads) that need error handlers.
Any error in a driver should kick an error back to the driver entry point.
Personally I put an errorhandler on every code entry point. I still use the old unstructured code because Try Catch doesn't have a Resume Next.
Practically every block of code I write starts with:
Friend Sub Example()
On Error GoTo Err_Sub
Exit_Sub:
Exit Sub
Err_Sub:
ErrorHandler("Example " & Err.Description)
Resume Next
Resume
End Sub
I change Example in the name and ErrorHandler to the new name of the Sub or Function.
I have a global error handler:
Friend Sub ErrorHandler(ByVal S As String, Optional ByVal FlashRed As Boolean = False)
fHMI.ErrorHandler(S, FlashRed)
End Sub
the fHMI.ErrorHandler puts the error in a listbox and logs it to a text file.
If I start to get a lot of errors I can attach to the process and put a breakpoint on the ErrorHandler.
I can step over the real errorHandler and then once I am back in the erring routine move the execution point to resume to take me back to the offending line of code.
This approach has saved me a lot of time.
on the fHMI form (which is a container that can't close) I have a listbox docked to the botton of the form and a Clear and ClearAll button on the Same line just left of the listbox scrollbar.
The buttons are anchored to bottom right. Note that fHMI cannot be the default instance of the form, otherwise it can't display errors from multiple threads.
Here is the code.
Friend HMIErrors As Error_Struct
Friend Structure Error_Struct
Friend NumErrors As Integer
Friend FlashRed As Boolean
Friend LastFlashChange As Integer
End Structure
Friend Sub HMIUpdate()
On Error GoTo Err_Sub
Dim S As String
S = "Sec Change: " & Timing.Sec_Change & vbCrLf _
& "Sec TaskTime: " & Timing.Sec_TaskTime & vbCrLf _
& "PLC Trigger Wait: " & Timing.PLC_Trigger_Wait & vbCrLf _
& "PLC Read Wait: " & Timing.PLC_Read_Wait
Me.lblms.Text = S
If HMIErrors.FlashRed Then
If Now.Second <> HMIErrors.LastFlashChange Then
HMIErrors.LastFlashChange = Now.Second
If Me.ListError.BackColor = System.Drawing.Color.Red Then
Me.ListError.BackColor = Color.FromKnownColor(KnownColor.Window)
Else
Me.ListError.BackColor = System.Drawing.Color.Red
End If
End If
End If
Exit_Sub:
Exit Sub
Err_Sub:
ErrorHandler("frmHMI_HMIUpdate " & Err.Description)
Resume Next
Resume
End Sub
Private Sub btnClearAll_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnClearAll.Click
On Error GoTo Err_Sub
Me.ListError.Items.Clear()
HMIErrors.NumErrors = 0
HMIErrors.FlashRed = False
Me.ListError.BackColor = Color.FromKnownColor(KnownColor.Window)
Exit_Sub:
Exit Sub
Err_Sub:
ErrorHandler("btnClearAll_Click " & Err.Description)
Resume Next
Resume
End Sub
Private Sub btnClear_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnClear.Click
On Error GoTo Err_Sub
If Me.ListError.Items.Count = 0 Then
btnClearAll.PerformClick()
Exit Sub
End If
Dim LastItem As Integer = Me.ListError.TopIndex
Me.ListError.Items.RemoveAt(LastItem)
HMIErrors.NumErrors = Me.ListError.Items.Count
If HMIErrors.NumErrors = 0 Then
btnClearAll.PerformClick()
Else
LastItem = LastItem - 1
If LastItem < 0 Then LastItem = 0
Me.ListError.TopIndex = LastItem
End If
Exit_Sub:
Exit Sub
Err_Sub:
ErrorHandler("btnClear_Click " & Err.Description)
Resume Next
Resume
End Sub
Private Delegate Sub ErrorHandlerCallback(ByVal S As String, ByVal FlashRed As Boolean)
Friend Sub ErrorHandler(ByVal S As String, Optional ByVal FlashRed As Boolean = False)
On Error Resume Next
If Me.ListError.InvokeRequired Then
'The Callback is necessary to display errors from other threads
Dim d As New ErrorHandlerCallback(AddressOf ErrorHandler)
Me.Invoke(d, New Object() {S, FlashRed})
Else
Dim DT As Date
Dim DTFile As String
On Error Resume Next
HMIErrors.NumErrors += 1
DT = Now
S = DT.ToString & ": Alarm " & HMIErrors.NumErrors.ToString & ": " & S
DTFile = PathDLog & "\Log\ERR" & Format(DT, "yy") & Format(DT, "MM") & Format(DT, "dd")
If FlashRed Then
HMIErrors.FlashRed = True
fHMI.ListError.BackColor = System.Drawing.Color.Red
End If
If HMIErrors.NumErrors < 1000 Then
My.Computer.FileSystem.WriteAllText(DTFile & ".txt", S & vbCrLf, True)
Me.ListError.Items.Add(S)
ElseIf HMIErrors.NumErrors = 1000 Then
Me.ListError.Items.Add(S)
S = DT.ToString & ": Alarm " & HMIErrors.NumErrors.ToString & ": " & "Alarm Limit exceeded, Clear All to continue Error recording"
Me.ListError.Items.Add(S)
HMIErrors.FlashRed = True
fHMI.ListError.BackColor = System.Drawing.Color.Red
End If
Me.ListError.TopIndex = Me.ListError.Items.Count - 1
End If
End Sub
It is best to have a UnhandledException handler in MyApplication Events:
Private Sub MyApplication_UnhandledException(ByVal sender As Object, ByVal e As Microsoft.VisualBasic.ApplicationServices.UnhandledExceptionEventArgs) Handles Me.UnhandledException
ErrorHandler(e.Exception.ToString)
Application.DoEvents()
e.ExitApplication = False
End Sub
Also need a declaration:
Public Event UnhandledException(ByVal sender As Object, ByVal e As UnhandledExceptionEventArgs)
This will let your program continue to run in the event of an unhandled exception.
Note that it doesn't work with the debugger. It only works if started from an .exe
Test with:
Dim v(1) As Integer
v(10) = v(10)
-
Ver. 3.57 has solved many problems.
I have found though that there are still some problems with Boolean arrays with an non zero index.
code that works for REAL won't work for BOOL.
Here is sample code:
Private Sub Button12_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button12.Click
Dim dTR0() As String = frmLoad.EthernetIPforCLXCom1.Read("HMI.REAL[0]", 1)
Dim dTR1() As String = frmLoad.EthernetIPforCLXCom1.Read("HMI.REAL[1]", 1)
Dim dT0() As String = frmLoad.EthernetIPforCLXCom1.Read("HMI.BOOL[0]", 1)
Dim dT1() As String = frmLoad.EthernetIPforCLXCom1.Read("HMI.BOOL[1]", 1)
End Sub
Private Sub CheckBox1_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles CheckBox1.CheckedChanged
Dim k As Integer
If Me.CheckBox1.Checked Then
k = frmLoad.EthernetIPforCLXCom1.Write("HMI.BOOL[0]", 1)
k = frmLoad.EthernetIPforCLXCom1.Write("HMI.BOOL[1]", 1)
k = frmLoad.EthernetIPforCLXCom1.Write("HMI.REAL[0]", CSng(1))
k = frmLoad.EthernetIPforCLXCom1.Write("HMI.REAL[1]", CSng(1))
Else
k = frmLoad.EthernetIPforCLXCom1.Write("HMI.BOOL[0]", 0)
k = frmLoad.EthernetIPforCLXCom1.Write("HMI.BOOL[1]", 0)
k = frmLoad.EthernetIPforCLXCom1.Write("HMI.REAL[0]", CSng(0))
k = frmLoad.EthernetIPforCLXCom1.Write("HMI.REAL[1]", CSng(0))
End If
End Sub
-
I have also found that a read of a bool array is limited to 2080 bits.
in the PLC I have HMI.BOOL[2400]
Dim dB() As String = fPLC.EthernetIPforCLXCom1.Read("HMI.BOOL[0]", 2330)
returns only 2080 elements in DB
-
I suggest the following changes in EthernetIPforCLXCom.CreateDLLInstance()
Change:
While DLL(i) IsNot Nothing AndAlso DLL(i).EIPEncap.IPAddress <> m_IPAddress AndAlso DLL(i).ProcessorSlot <> m_ProcessorSlot AndAlso i < 11
i += 1
End While
to
While DLL(i) IsNot Nothing AndAlso DLL(i).EIPEncap.IPAddress <> m_IPAddress AndAlso i < 11
i += 1
End While
Otherwise 2 PLC's with different IP addresses but both having the processor in slot 0 won't get a new instance.
Also you added:
DLL(MyDLLInstance).EIPEncap.IPAddress = m_Port
you probably meant:
DLL(MyDLLInstance).EIPEncap.Port = m_Port
-
I suggest the following changes in EthernetIPforCLXCom.CreateDLLInstance()
Change:
While DLL(i) IsNot Nothing AndAlso DLL(i).EIPEncap.IPAddress <> m_IPAddress AndAlso DLL(i).ProcessorSlot <> m_ProcessorSlot AndAlso i < 11
i += 1
End While
to
While DLL(i) IsNot Nothing AndAlso DLL(i).EIPEncap.IPAddress <> m_IPAddress AndAlso i < 11
i += 1
End While
Otherwise 2 PLC's with different IP addresses but both having the processor in slot 0 won't get a new instance.
This will become a problem if there are 2 processors in the same rack. It should actually be like this:
While DLL(i) IsNot Nothing AndAlso (DLL(i).EIPEncap.IPAddress <> m_IPAddress OrElse DLL(i).ProcessorSlot <> m_ProcessorSlot) AndAlso i < 11
-
Here are some problems I found in Ver. 3.58 EthernetIPforCLXCom
A SINT does not come back as signed. A negative number in the PLC shows up as a positive number > 128 after a read.
(INT,DINT, & LINT work OK)
A read of a BOOL array is limited to 2080 elements. To replicate,create a BOOL array in the PLC with 4000 elements.
Try to read them all and the returned string array is only 2080 elements.