Jump to content

Using the MELSEC Communication Protocol, Correct way to Read Multiple Data Register for Mitsubishi FX5UC-32MT/DSS-TS PLC


Recommended Posts

Posted (edited)

I'm working with a Mitsubishi FX5UC-32MT/DSS-TS PLC and trying to read data from multiple D registers using the MC protocol, specifically the 0406 command (QnA-compatible 3E frame for multiple-block batch read). Currently, I can successfully read one register at a time using command 0401, but I want to optimize this by reading multiple blocks in a single request. I followed a YouTube tutorial (https://www.youtube.com/watch?v=El1h99SCKns) and implemented the code in VB.NET. I also reviewed the MELSEC Communication Protocol manual, but I’m having trouble understanding how to correctly structure the binary frame for 0406.

 

Private Sub MultiReadDataRegister(rdAddressTextBox As TextBox, disTextBox As TextBox, rdValue As TextBox)
    Dim DeviceNo_D As String
    Dim DeviceNo2_D As String
    Dim DeviceNo15_D As String
    Dim DeviceNo16_D As String
    Dim DeviceNo17_D As String

    DeviceNo_D = rdAddressTextBox.Text

    If String.IsNullOrWhiteSpace(DeviceNo_D) OrElse Val(DeviceNo_D) < 0 Then
        rdAddressTextBox.Text = "0"
    Else
        DeviceNo_D = rdAddressTextBox.Text
    End If

    DeviceNo_D = rdAddressTextBox.Text
    DeviceNo2_D = Hex(DeviceNo_D).PadLeft(6, "0").Substring(0, 6)
    DeviceNo15_D = DeviceNo2_D.Substring(4, 2)
    DeviceNo16_D = DeviceNo2_D.Substring(2, 2)
    DeviceNo17_D = DeviceNo2_D.Substring(0, 2)

    Dim sendmessage4(22) As String
    'Binary Code
    
    sendmessage4(0) = "50" 'Subheader -  Set the fixed value (request message: '5000', response message: 'D000')
    sendmessage4(1) = "00" 'Subheader -  Set the fixed value (request message: '5000', response message: 'D000')
    sendmessage4(2) = "00" 'NetWork No.
    sendmessage4(3) = "FF" 'Pc No.
    sendmessage4(4) = "FF" 'Request destination module I/O No.
    sendmessage4(5) = "03" 'Request destination module I/O No.
    sendmessage4(6) = "00" 'Request destination Module station No
    sendmessage4(7) = "0C" 'Requested Data Length 
    sendmessage4(8) = "00" 'Requested Data Length
    sendmessage4(9) = "10"  'Monitoring timer    
    sendmessage4(10) = "00" 'Monitoring timer    
    sendmessage4(11) = "06" 'Command      
    sendmessage4(12) = "04" 'Command      
    sendmessage4(13) = "00" 'SubCommand   
    sendmessage4(14) = "00" 'SubCommand
    sendmessage4(15) = "02" 'Number of word device blocks   
    sendmessage4(16) = "00" 'Number of bit device blocks
    sendmessage4(17) = DeviceNo15_D
    sendmessage4(18) = DeviceNo16_D
    sendmessage4(19) = DeviceNo17_D
    sendmessage4(20) = "A8" 'Device Code in Hexadecimal format. It indecate Data register D^*
    sendmessage4(21) = "02" 'Number of Device Points to Read - Low byte Example: user input is D200 so it implies 3 consecutive device points, possibly D200,D201,D202 
    'sendmessage4(22) = "00" 'Number of Device Points to Read - High byte

    'Socket connected then it send And recive the message
    If _socket.Connected Then
        Dim bytereceiveMessage4 = SendAndReceive(sendmessage4)

        If bytereceiveMessage4 IsNot Nothing Then

            Dim arrays As Byte() = {bytereceiveMessage4(11), bytereceiveMessage4(12)}

            rdValue.Text = BitConverter.ToUInt16(arrays, 0)


            If rdValue.Text = 0 Then
                rdValue.BackColor = Color.Blue
                rdValue.ForeColor = Color.White
            Else
                rdValue.BackColor = Color.White
                rdValue.ForeColor = Color.Black
            End If

            disTextBox.Text = rdValue.Text / 10
        End If
    End If

End Sub

Private Function SendAndReceive(sendMessage As String()) As Byte()
    Dim byteSendMessage As Byte() = StringsToBytes(sendMessage)
    _socket.Send(byteSendMessage, byteSendMessage.GetLength(0), SocketFlags.None)
    Dim byteReceiveMessage As Byte()
    Dim ReceiveSize As Integer = 0
    Do
        byteReceiveMessage = New Byte(_socket.Available - 1) {}
        ReceiveSize =
            _socket.Receive(byteReceiveMessage, byteReceiveMessage.GetLength(0), SocketFlags.None)

    Loop While ReceiveSize = 0
    Return byteReceiveMessage
End Function

Private Function StringsToBytes(src() As String) As Byte()
     Dim returnBytes(src.Length - 1) As Byte

     Dim i As Integer
     For i = 0 To src.Length - 1
         returnBytes(i) = Convert.ToByte(src(i), 16)
     Next

     Return returnBytes
End Function

What I tried:

I implemented a VB.NET socket communication routine based on a YouTube tutorial to send a 3E frame using command 0406 (multiple-block batch read).

I constructed the binary frame manually, including the subheader, network and station numbers, command code, and device address formatting.

I verified that the PLC is in RUN mode, and that MC protocol communication is enabled.

I tested the same setup using command 0401 for single-block batch read, and it worked correctly — I was able to read one D register at a time.

What I expected:

I expected the PLC to return data for multiple D registers (e.g., D200, D201, D202) in a single response frame when using command 0406.

I anticipated that the response would contain the values of all requested registers, allowing me to parse and display them efficiently.

What actually happened: In some cases, the socket received a frame, but its not a actual value. sometimes socket received this
0 - 208

1 - 0

2 - 0

3 - 255

4 - 255

5 - 3

6 - 0

7 - 11

8 - 0

9 - 97

10 - 192

11 - 0

12 - 255

13 - 255

14 - 3

15 - 0

16 - 6

17 - 4

18 - 0

19 - 0

I suspect the issue may be due to incorrect frame formatting.

Edited by Nik123

Posted (edited)

Also what is the reason to read blocks with 0406 command? You ca read a range on devices with 0401.

IF in binary -

0x50, 0x00, # Subheader (2B)

0x00, 0xFF, # Network Number & PLC Number (2B)

0x0C, 0x00, # Request Length (2B)

0x01, 0x04, # Command Code (Read Word Device - 0x0401)

0x00, 0x00, # Subcommand (2B)

0x2E, 0xE1, 0x00, # Start Address (D12001 - 3B) 

0xA8, #Device code (D in binary message is A8 - 1B)

0x06, 0x00 # Number of Points to Read (2B) 

This message should read 6 words starting from D12001.

 

Or this will read 10 points from starting D0

0x50, 0x00,                               // Sub Header

0x00, 0xFF, 0xFF, 0x03, 0x00,   // Route

0x0C, 0x00,                              // Request Length

0x00, 0x00,                              // Monitoring Timer

0x01, 0x04, 0x00, 0x00,           // Command

0x00, 0x00, 0x00,                   // Device Address

0xA8,                                     // Device Prefix

0x10, 0x00                            // Device Length

 

the only reason for 0406 is you can read bits and words in the same message, or blocks of words/bits that are not consecutive. Personally never tried...

Edited by SergeyBorchshev
Addition
Posted

Thank you Sergey Borchshev, I see that open-source library, but it didn't support the command 0406 and I just got the email from Mitsubishi that I am using the wrong message format. I need to use 3C Format to utilize the 0406 command. I changed the format, but I am still getting the issue but diffrent one.

Posted

OK, the manual, page 3-122 or 3-123 has a complete example. If you try to read the same data, does your code produce the same request frame?

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...