简体   繁体   English

通过 tcp 的 Modbus 通信不会向所有设备发送数据

[英]Modbus communication over tcp doesn't send data to all devices

I have a gateway connected to a computer which runs a C# program.我有一个连接到运行 C# 程序的计算机的网关。 I have a Modbus slave-master relation between computer and the gateway.我在计算机和网关之间有一个 Modbus 从属-主关系。 Here are the gateway configurations (model EKI-1221-BE):以下是网关配置(型号 EKI-1221-BE):
在此处输入图像描述 在此处输入图像描述

The set up I have is the same as in this picture but I have 6 devices connected instead of 2 and will later have 12:我的设置与这张图片中的相同,但我连接了 6 个设备而不是 2 个,以后将有 12 个:
在此处输入图像描述

I can send a Modbus command to any of the 6 devices without any problems but the issue happens when I try to send multiple commands in quick interval.我可以毫无问题地向 6 个设备中的任何一个发送 Modbus 命令,但是当我尝试快速发送多个命令时会出现问题。 In the following code, only the device 1,2 and 6 receive the command.在下面的代码中,只有设备 1,2 和 6 接收到命令。

PumpsComm.SendMessage(1, 3099, 2000);
PumpsComm.ClientSocket.Receive(TempBuffer);
PumpsComm.SendMessage(2, 3099, 3000);
PumpsComm.ClientSocket.Receive(TempBuffer);
PumpsComm.SendMessage(3, 3099, 4000);
PumpsComm.ClientSocket.Receive(TempBuffer);
PumpsComm.SendMessage(4, 3099, 6000);
PumpsComm.ClientSocket.Receive(TempBuffer);
PumpsComm.SendMessage(5, 3099, 8000);
PumpsComm.ClientSocket.Receive(TempBuffer);
PumpsComm.SendMessage(6, 3099, 10000);
PumpsComm.ClientSocket.Receive(TempBuffer);

The function SendMessage is as follows, where ClientSocket is a TCP Socket that is connected to the gateway / Modbus slave.函数SendMessage如下,其中ClientSocket为连接网关/Modbus slave的TCP Socket。

public void SendMessage(int pumpID, int register, int command)
    {
        byte[] message = new byte[12];

        message[0] = 0;
        message[1] = 0;     //Message number
        message[2] = 0;
        message[3] = 0;
        message[4] = 0;
        message[5] = 6;     //Message length
        message[6] = (byte)ToHexInDec(pumpID, 'L');      //Pump ID
        message[7] = 6;
        message[8] = (byte)ToHexInDec(register, 'H');     //Register high
        message[9] = (byte)ToHexInDec(register, 'L');     //Register low
        message[10] = (byte)ToHexInDec(command, 'H');    //Command high
        message[11] = (byte)ToHexInDec(command, 'L');    //Command low

        try
        {
            ClientSocket.Send(message);
        }
        catch
        {
            return;
        }
    }

If I make the Thread sleep for 30ms between each send, every command works but this is not an option in my case as I need to be able to update every device in a very short amount of time.如果我在每次发送之间让线程休眠 30 毫秒,则每个命令都有效,但在我的情况下这不是一个选项,因为我需要能够在很短的时间内更新每个设备。
I looked at the packets that I was sending and receiving to and from the gateway with Wireshark and I think I found where the我查看了使用 Wireshark 向网关发送和接收的数据包,我想我找到了
This is what the output of Wireshark was (the Ip that ends with 200 is the computer and the one that ends with 107 is the gateway):这就是Wireshark的输出(以200结尾的IP是计算机,以107结尾的是网关): 线鲨 It looks as though the communication for the device 3,4,5 and 6 where put in the same TCP packet and for some reason, the only Modbus communication that was read from that packet is the last one.看起来设备 3、4、5 和 6 的通信放在同一个 TCP 数据包中,出于某种原因,从该数据包中读取的唯一 Modbus 通信是最后一个。

I tried adding MBAP transaction numbers for every communication in the MBAP header of the Modbus communication but it didn't change anything.我尝试在 Modbus 通信的 MBAP 标头中为每个通信添加 MBAP 事务编号,但它没有改变任何东西。 I then tried to add a blocking receive that makes the program wait for the Modbus response before sending the next communication but I am not receiving anything (even though we can see that the gateway is sending a Modbus response back when the communication was successfull)然后我尝试添加一个阻塞接收,使程序在发送下一次通信之前等待 Modbus 响应,但我没有收到任何东西(即使我们可以看到网关在通信成功时正在发送 Modbus 响应)
I don't know what I can do anymore and was looking to see if anyone with more experience with TCP modbus communications could help.我不知道我能做什么了,我想看看有没有更多的 TCP modbus 通信经验的人可以提供帮助。 I can provide more details if necessary.如有必要,我可以提供更多详细信息。 Sorry if this is not clear enough, english is not my first language.对不起,如果这不够清楚,英语不是我的第一语言。

Thanks!谢谢!

As per the spec根据规范

Several MODBUS transactions can be activated simultaneously on the same TCP Connection.多个 MODBUS 事务可以在同一个 TCP 连接上同时激活。
Remark: If this is done then the MODBUS transaction identifier must be used to uniquely identify the matching requests and responses备注:如果这样做,则必须使用 MODBUS 事务标识符来唯一标识匹配的请求和响应

However you are sending messages with the transaction identifier set to 0000 :但是,您正在发送事务标识符设置为0000的消息:

message[0] = 0;
message[1] = 0;     //Message number

(I'm guessing that the gateway is detecting the duplication and assigning a new identifier because of this). (我猜网关正在检测重复并因此分配一个新标识符)。

A better approach would be to send all of your requests (each with a different identifier; it does not matter what this is as long as it's unique) and then wait for the responses to come in (matching the response to the request using the transaction identifier in each response; responses may be in a different order to the requests).更好的方法是发送所有请求(每个请求都有不同的标识符;只要它是唯一的,这无关紧要),然后等待响应进入(使用事务将响应与请求匹配每个响应中的标识符;响应可能与请求的顺序不同)。

Note that you should not assume that each response will come in a separate TCP packet (or that it will be in a single packet);请注意,您不应该假设每个响应都将出现在一个单独的 TCP 数据包中(或者它会出现在一个数据包中); the protocol takes this into account:该协议考虑到了这一点:

When MODBUS is carried over TCP, additional length information is carried in the MBAP header to allow the recipient to recognize message boundaries even if the message has been split into multiple packets for transmission.当 MODBUS 通过 TCP 传输时,MBAP 标头中会携带额外的长度信息,以允许接收者识别消息边界,即使消息已被拆分为多个数据包进行传输。 The existence of explicit and implicit length rules, and use of a CRC-32 error check code (on Ethernet) results in an infinitesimal chance of undetected corruption to a request or response message.显式和隐式长度规则的存在以及 CRC-32 错误校验码的使用(在以太网上)导致请求或响应消息未被检测到损坏的可能性极小。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM