AdvancedHMI Software
General Category => Support Questions => Topic started by: danm on September 01, 2023, 09:53:38 AM
-
I have a UDT in a Allen Bradly PLC. I am using version 3.99x. I have tried 'READUDT' but it returns "'ReadUDT' is not a member of 'EthernetIPforCLXCom1'"? I am having issue understanding how to determine where to start each tag and how many bytes to read. All strings are 82 long and the format of the UDT is:
Public Class CDS 'Common Data Structure
Public PalletNumber As String
Public ProductionOrderID As String
Public InternalOrderID As String
Public ItemNumber As String
Public ItemName As String
Public LotCode As String
Public ItemGroup As String
Public Barcode As String
Public CasesPerPallet As Int16
Public ProductType As String
Public Quarantine As Boolean
Public QuarantineOrderID As String
Public TimeStamp As String
Public PartialCaseCount As Int16
Public PartialP As Boolean
Public MoverClassification As String
Public ReservedSalesOrderID As String
Public Destination As String
Public Location As String
Public State As String
Public Notes As String
End Class
I am using the following to read and display the UDT for testing but some of them come back as gibberish. I am sure it is in my not understanding what bytes belong to each tag. As the control works amazing for reading the tags separately. Can someone help give me a basic understanding of the byte offsets and how to calculate them?
Private Function ReadWO(ByVal tag As String) As String
Dim bytes As Byte() = EthernetIPforCLXCom1.ReadRaw(tag)
Dim CommonData As CDS = New CDS With {
.PalletNumber = ExtractStringField(bytes, 4, 82),
.ProductionOrderID = ExtractStringField(bytes, 90, 82),
.InternalOrderID = ExtractStringField(bytes, 176, 82),
.ItemNumber = ExtractStringField(bytes, 268, 82),
.ItemName = ExtractStringField(bytes, 354, 82),
.LotCode = ExtractStringField(bytes, 440, 82),
.ItemGroup = ExtractStringField(bytes, 529, 82),
.Barcode = ExtractStringField(bytes, 612, 82),
.CasesPerPallet = BitConverter.ToInt16(bytes, 698),
.ProductType = ExtractStringField(bytes, 710, 82),
.Quarantine = BitConverter.ToBoolean(bytes, 744),
.QuarantineOrderID = ExtractStringField(bytes, 746, 82),
.TimeStamp = ExtractStringField(bytes, 890, 82),
.PartialCaseCount = BitConverter.ToInt16(bytes, 976),
.PartialP = BitConverter.ToBoolean(bytes, 912),
.MoverClassification = ExtractStringField(bytes, 914, 82),
.ReservedSalesOrderID = ExtractStringField(bytes, 996, 82),
.Destination = ExtractStringField(bytes, 1078, 82),
.Location = ExtractStringField(bytes, 1160, 82),
.State = ExtractStringField(bytes, 1242, 82),
.Notes = ExtractStringField(bytes, 1324, 82)
}
PrintClassFields(CommonData)
' Dim MyUDT As DateTimeUDT = EthernetIPforCLXCom1.ReadUDT("MyUDT", GetType(DateTimeUDT))
End Function
Private Function ExtractStringField(bytes As Byte(), offset As Integer, length As Integer) As String
Dim fieldBytes(length - 1) As Byte
Array.Copy(bytes, offset, fieldBytes, 0, length)
Return Encoding.Default.GetString(fieldBytes).Trim().Replace(Convert.ToChar(0), "")
End Function
Sub PrintClassFields(obj As Object)
Dim type As Type = obj.GetType()
For Each fieldInfo As FieldInfo In type.GetFields()
Dim fieldName As String = fieldInfo.Name
Dim fieldValue As Object = fieldInfo.GetValue(obj)
Debug.WriteLine(fieldName & " : " & fieldValue)
Next
End Sub
-
Minimum size of a UDT is 4 bytes. A single bool is 4 bytes UDT's are packed in 4 byte chunks. A simple 2 INT UDT will be 4 bytes. A simple UDT with a INT and BOOL will be 4 bytes.
A string takes 88 bytes of memory. 82 for the characters, 4 for the length and 2 pad bytes.
That INT will be in its own 4 byte chunk. Take the example STRING/INT/STRING.
STRING = bytes [0-87]
INT = bytes [88-91] (2 pad bytes because next STRING won't fit in the 2 available bytes)
STRING = bytes [92-179]
Similarly, that BOOL Quarantine will occupy its own 4 byte chunk.
I bet if you reorganized your UDT to be strings first, then INTs then BOOLs, you'll see a size change.
-
Any reason for not using the latest version which supports the ReadUDT?
-
Any reason for not using the latest version which supports the ReadUDT?
LOL, sometimes I overlook the simple solutions :) But it was fun to think about.
-
I do that too!
The memory base in RSLogix 5000 is a 32-bit data type.
A single BOOL UDT or an array of BOOL[32] UDT have the same size as one DINT.
And the next BOOL after 32 will increase the UDT size to 2 DINT
-
Any reason for not using the latest version which supports the ReadUDT?
The ReleaseNotes399.txt says it is the version 3.99x however as I mentioned when I try and use the ReadUDT method it highlights that line with the error "ReadUDT is not a member of EthernetIPforCLXCom". I am not sure why because that was my first thought to try.
-
Minimum size of a UDT is 4 bytes. A single bool is 4 bytes UDT's are packed in 4 byte chunks. A simple 2 INT UDT will be 4 bytes. A simple UDT with a INT and BOOL will be 4 bytes.
A string takes 88 bytes of memory. 82 for the characters, 4 for the length and 2 pad bytes.
That INT will be in its own 4 byte chunk. Take the example STRING/INT/STRING.
STRING = bytes [0-87]
INT = bytes [88-91] (2 pad bytes because next STRING won't fit in the 2 available bytes)
STRING = bytes [92-179]
Similarly, that BOOL Quarantine will occupy its own 4 byte chunk.
I bet if you reorganized your UDT to be strings first, then INTs then BOOLs, you'll see a size change.
I will talk to the PLC guys! I don't do any PLC work myself just tasked with connecting them to our other systems.
-
Any reason for not using the latest version 3.99y which supports the ReadUDT?