python语言,modbus tcp协议 优化代码,数据集采效率提升80%+


前言

当前主要是分享在modbus tcp协议采集设备数据时,如何确保数据集采的效率,刷新频率的一点小小的技术分享。通过在程序采集逻辑,顺序等方式的修正,在同等技术参数设备的情况下,满足大家对于数据采集精度的高要求。


一、为什么对于数据采集的精度有一定的要求?

设备通过标准协议实现数据的集采,传输;再通过不同的界面,图标,曲线展示其运行状态,反应设备数据的演变状态,这是当下数据集采的基本要求。

当设备增多,数据增多时,随着数据量的累积,如果不在编程上进行优化,就会存在数据采集堵塞,数据采集频率无法跟上实际需求的问题。

例如:日常的温度采集需要的精度是 ℃ / min ; 电流的精度是 A / s。

二、举例说明

1.单个数据集采的示例

通过modbus tcp 采集设备中的单个寄存器的数据,寄存器地址为 01B0H

from pymodbus.client.sync import ModbusTcpClient
import struct


def read_float_from_modbus(ip, port, unit_id, register_address):
    try:
        # 创建 Modbus TCP 客户端实例
        client = ModbusTcpClient(ip, port=port)
        # 尝试连接到 Modbus TCP 服务器
        if client.connect():
            # 浮点数占 2 个寄存器
            num_registers = 2
            # 读取保持寄存器
            result = client.read_holding_registers(register_address, num_registers, unit=unit_id)
            if not result.isError():
                registers = result.registers
                # 合并两个 16 位寄存器为 32 位值
                combined_value = (registers[0] << 16) + registers[1]
                # 将 32 位值转换为字节数据
                byte_data = combined_value.to_bytes(4, byteorder='big')
                # 使用 struct 模块将字节数据解包为浮点数
                float_value = struct.unpack('!f', byte_data)[0]
                return float_value
            else:
                print(f"读取寄存器时出错: {result}")
        else:
            print("无法连接到 Modbus TCP 服务器。")
    except Exception as e:
        print(f"发生异常: {e}")
    finally:
        if client.is_open():
            # 关闭客户端连接
            client.close()


# 示例使用
ip = '127.0.0.1'
port = 502
unit_id = 1
# 十六进制 01B0H 转换为十进制是 432
register_address = 432

float_data = read_float_from_modbus(ip, port, unit_id, register_address)
if float_data is not None:
    print(f"从寄存器地址 {hex(register_address)} 读取到的浮点数数据为: {float_data}")
    

根据当前的模式,若是采用多个寄存器地址的数据,则不断调用函数read_float_from_modbus(ip, port, unit_id, register_address)即可,不停的修改register_address的值。

但是实际的运行中会发现,在刷新频率提升之后,由于不停的调用整个函数,就会发生,数据堵塞,卡顿的情况。做到秒级的刷新频率,就会发生数据间隔时间段的整体刷新,而不是按照时间频率准时刷新的情况。


2.程序优化

以上主要的问题是在于,读取寄存器地址内的数据内容,消耗能源是一定的,但是不断地调用 client = ModbusTcpClient(ip, port=port) # 创建 Modbus TCP 客户端,会占用大量的设备资源,此处可以在创建客户端下一步采集数据时进行多个数据的循环集采,就可以节省大量的设备资源。
程序如下:

from pymodbus.client.sync import ModbusTcpClient
import struct


def read_float_from_modbus(ip, port, unit_id, register_addresses):
    float_values = []
    try:
        # 创建 Modbus TCP 客户端实例
        client = ModbusTcpClient(ip, port=port)
        # 尝试连接到 Modbus TCP 服务器
        if client.connect():
            for register_address in register_addresses:
                # 浮点数占 2 个寄存器
                num_registers = 2
                # 读取保持寄存器
                result = client.read_holding_registers(register_address, num_registers, unit=unit_id)
                if not result.isError():
                    registers = result.registers
                    # 合并两个 16 位寄存器为 32 位值
                    combined_value = (registers[0] << 16) + registers[1]
                    # 将 32 位值转换为字节数据
                    byte_data = combined_value.to_bytes(4, byteorder='big')
                    # 使用 struct 模块将字节数据解包为浮点数
                    float_value = struct.unpack('!f', byte_data)[0]
                    float_values.append(float_value)
                else:
                    print(f"读取寄存器 {register_address} 时出错: {result}")
        else:
            print("无法连接到 Modbus TCP 服务器。")
    except Exception as e:
        print(f"发生异常: {e}")
    finally:
        if client.is_open():
            # 关闭客户端连接
            client.close()
    return float_values


# 示例使用
ip = '127.0.0.1'
port = 502
unit_id = 1
# 寄存器地址列表,示例中包含十六进制 01B0H(十进制 432)和 01B2H(十进制 434)
register_addresses = [432, 434]

float_data = read_float_from_modbus(ip, port, unit_id, register_addresses)
if float_data:
    for i, address in enumerate(register_addresses):
        print(f"从寄存器地址 {hex(address)} 读取到的浮点数数据为: {float_data[i]}")
    

此处就是采集两个寄存器的数据,十六进制 01B0H(十进制 432)和 01B2H(十进制 434)一次采集两个数据 , client = ModbusTcpClient(ip, port=port) 只打开了一次。

实际测试中将 寄存器数列 register_addresses = [432, 434] 中的寄存器地址拓展到10+,采集精度任然可以保持到10ms甚至更高。当然此处也要考虑设备的高强度数据集采情况的使用寿命,散热等情况。

实测的视频如下:

modbus tcp 数据集采 精度10ms

总结

在成本,技术,以及实际情况固定的情况下,不同的采集策略,不同的代码,不同的逻辑思维对于最终的成品有着重大的影响。更多的时候,合理的设计,优质的设计会让不多的资源,发挥出意想不到的效果。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值