一、背景介绍

在EdgeX边缘网关中接入Modbus从站后,会碰到一个让人头疼的问题,就是上报的寄存器值偶尔会错乱。这时候就会怀疑是不是字节序设置方面出了问题。想要弄清楚到底是不是字节序设置的问题,就需要从协议栈和链路层做隔离验证。接下来,咱就详细说说这事儿。

二、应用场景

2.1 工业自动化

在工业自动化生产线里,很多设备都是通过Modbus协议进行通信的。比如,一个大型的机械加工车间,有各种各样的机床和传感器,这些设备就是Modbus从站。通过EdgeX边缘网关把这些从站设备的数据采集上来,然后进行分析和处理。要是上报的寄存器值错乱了,那分析出来的结果就不准了,有可能会导致生产线出现故障或者生产出来的产品质量不合格。

2.2 能源管理系统

能源管理系统需要实时监测电表、水表等设备的数据。这些设备作为Modbus从站和EdgeX边缘网关连接。如果采集到的电量、水量等数据错乱,就会影响能源的合理分配和使用,造成能源的浪费或者供应不足。

三、字节序设置与寄存器值错乱的关系

3.1 什么是字节序

字节序简单来说就是多字节数据在内存中存储的顺序。有两种常见的字节序:大端字节序和小端字节序。大端字节序是把数据的高位字节存放在低地址,低位字节存放在高地址;小端字节序则相反,是把数据的低位字节存放在低地址,高位字节存放在高地址。 比如一个16位的整数0x1234,在大端字节序中,内存存储顺序是0x12、0x34;在小端字节序中,内存存储顺序是0x34、0x12。

3.2 为什么字节序设置会导致寄存器值错乱

在Modbus协议中,数据是以字节的形式进行传输和存储的。如果EdgeX边缘网关和Modbus从站的字节序设置不一致,那么在读取和解析寄存器值的时候,就会出现错误。比如,从站按照大端字节序存储数据,而网关按照小端字节序去解析,就会得到错误的寄存器值。

3.3 示例说明

# Python示例,展示大端和小端字节序的不同
value = 0x1234
# 大端字节序
big_endian_bytes = value.to_bytes(2, byteorder='big')
print(f"大端字节序: {big_endian_bytes.hex()}")  # 输出: 1234

# 小端字节序
little_endian_bytes = value.to_bytes(2, byteorder='little')
print(f"小端字节序: {little_endian_bytes.hex()}")  # 输出: 3412

四、从协议栈与链路层做隔离验证的方法

4.1 协议栈层验证

4.1.1 检查配置文件

EdgeX边缘网关和Modbus从站的配置文件中一般都会有字节序的设置选项。要仔细检查这些配置文件,确保两者的字节序设置一致。 比如,在EdgeX的配置文件里,可能会有类似这样的配置:

{
  "Modbus": {
    "ByteOrder": "BigEndian"  # 这里设置为大端字节序
  }
}

而Modbus从站设备的配置文件或者参数设置界面中,也要确保字节序设置为大端字节序。

4.1.2 模拟通信测试

可以使用一些工具来模拟EdgeX边缘网关和Modbus从站之间的通信。比如,使用Python的pymodbus库来创建一个简单的Modbus主站和从站,然后设置不同的字节序进行通信测试。

# Python示例,使用pymodbus进行模拟通信测试
from pymodbus.client.sync import ModbusTcpClient
from pymodbus.server.sync import StartTcpServer
from pymodbus.datastore import ModbusSequentialDataBlock
from pymodbus.datastore import ModbusSlaveContext, ModbusServerContext

# 创建从站数据存储
store = ModbusSlaveContext(
    di=ModbusSequentialDataBlock(0, [17]*100),
    co=ModbusSequentialDataBlock(0, [17]*100),
    hr=ModbusSequentialDataBlock(0, [17]*100),
    ir=ModbusSequentialDataBlock(0, [17]*100))
context = ModbusServerContext(slaves=store, single=True)

# 启动从站服务器
import threading
server_thread = threading.Thread(target=StartTcpServer, args=(context,))
server_thread.start()

# 创建主站客户端
client = ModbusTcpClient('localhost')
# 连接到从站
if client.connect():
    # 读取保持寄存器
    result = client.read_holding_registers(address=0, count=10)
    if not result.isError():
        print(f"读取结果: {result.registers}")
    else:
        print(f"读取出错: {result}")
    # 关闭连接
    client.close()

# 停止从站服务器
server_thread.join()

4.1.3 抓包分析

使用网络抓包工具,如Wireshark,对EdgeX边缘网关和Modbus从站之间的通信数据包进行捕获和分析。查看数据包中的数据字节顺序,看是否和配置的字节序一致。如果不一致,就说明字节序设置有问题。

4.2 链路层验证

4.2.1 检查物理连接

确保EdgeX边缘网关和Modbus从站之间的物理连接没有问题。比如,检查网线是否插好,串口线是否连接正确,有没有松动、接触不良等情况。

4.2.2 测试链路稳定性

可以使用ping命令或者其他网络测试工具来测试链路的稳定性。如果链路不稳定,可能会导致数据包丢失或者损坏,从而影响寄存器值的上报。

# 测试网络连通性
ping -c 10 192.168.1.100  # 连续发送10个数据包到指定IP地址

4.2.3 更换链路设备

如果怀疑是链路设备(如交换机、路由器等)的问题,可以尝试更换这些设备,看看问题是否仍然存在。

五、技术优缺点

5.1 从协议栈层验证的优缺点

5.1.1 优点

  • 可以直接针对字节序设置进行验证,能够准确判断是否是字节序问题导致的寄存器值错乱。
  • 通过模拟通信测试和抓包分析,可以深入了解通信过程中的数据传输情况,有助于发现其他潜在的协议层问题。

5.1.2 缺点

  • 需要对配置文件和协议有一定的了解,对于一些技术基础较差的人来说,可能操作起来有难度。
  • 模拟通信测试和抓包分析需要使用一些专业工具,安装和使用这些工具需要花费一定的时间和精力。

5.2 从链路层验证的优缺点

5.2.1 优点

  • 检查物理连接和测试链路稳定性比较简单直观,不需要太多的专业知识。
  • 能够快速排除链路故障导致的问题。

5.2.2 缺点

  • 只能检测到链路层的问题,对于协议层的字节序设置问题无法直接检测。
  • 更换链路设备可能会影响整个网络的正常运行,需要谨慎操作。

六、注意事项

6.1 配置文件修改

在修改EdgeX边缘网关和Modbus从站的配置文件时,一定要仔细,避免误操作导致其他问题。修改配置文件后,要记得重启相关服务,让配置生效。

6.2 抓包分析的权限

使用Wireshark等抓包工具时,可能需要管理员权限。而且要注意,抓包过程中可能会捕获到一些敏感信息,要做好信息安全保护。

6.3 链路测试的影响

在进行链路测试时,要注意不要影响到正常的生产和业务。比如,在工业自动化场景中,要选择合适的时间进行测试,避免影响生产线的运行。

七、文章总结

在EdgeX边缘网关接入Modbus从站后,上报的寄存器值偶发错乱,很可能和字节序设置有关。通过从协议栈和链路层做隔离验证,可以找出问题的根源。在协议栈层,可以通过检查配置文件、模拟通信测试和抓包分析来验证字节序设置是否正确;在链路层,可以检查物理连接、测试链路稳定性和更换链路设备来排除链路故障。每种验证方法都有其优缺点,在实际操作中要根据具体情况选择合适的方法。同时,要注意配置文件修改、抓包分析权限和链路测试影响等事项,确保验证过程顺利进行。