python和PLC通信(以太网modbustcp)

要在Python中与PLC建立通信,通常需要进行以下步骤流程:

1. 确定PLC的通信协议:不同的PLC厂商和型号可能采用不同的通信协议,例如Modbus、OPC UA、Profinet等。请先确定您的PLC使用的是哪种通信协议(本文为modbustcp)。

2. 安装相应的Python库:根据您所选择的PLC通信协议,在Python中安装相应的库。例如,如果使用Modbus协议,可以安装`pymodbus`库;如果使用OPC UA协议,可以安装`opcua`库。

3. 连接到PLC:使用相应的库和代码,在Python中建立与PLC的连接。具体的连接方式和代码会因通信协议而异,以下是一个示例:

4. 读取或写入数据:根据您的需求,使用相应的库和方法来读取或写入PLC的数据。以下是一个示例:

from pymodbus.client import ModbusTcpClient
import struct


#负数int
def convert_signed_integer(data):
    # 将数据转换为有符号整数
    # result = (data & 0xffff) - (data & 0x8000)
    # return result
    if data > 0x7FFF:
        data -= 0x10000
    return data

#16整数转32实数
def int_to_real(data1,data2):
    int_data = data1 << 16 | data2
    real_data = struct.unpack('!f', struct.pack('!I', int_data))[0]
    return real_data

# PCL 设备的 IP 地址和端口号
ip_address = '192.168.1.88'
port = 502

# 建立 Modbus TCP 连接
client = ModbusTcpClient(ip_address, port)

if client.connect():
    # 读取保持寄存器中的数据(示例:地址 0 到 9)
    slave_address = 1  # 设备的从站地址
    start_address = 12288  # 起始地址
    num_registers = 100  # 要读取的寄存器数量
    realdata_x = []
    for i in range(12288, 12688, 100):
        start_address = i
        try:
            response = client.read_holding_registers(start_address, num_registers, unit=slave_address)
            # print(response)
            if not response.isError():
                data = response.registers
                # print("读取到的数据:", data)
                # print(len(data))
                for i in range(0, 100, 2):
                    realdata_x.append(int_to_real(data[i + 1], data[i]))

            else:
                print("读取数据时出错:", response)
        except Exception as e:
            print("发生异常:", str(e))
    # print(realdata_x)
    # print(len(realdata_x))
    realdata_y=[]
    for i in range(14288, 14688, 100):
        start_address = i
        try:
            response = client.read_holding_registers(start_address, num_registers, unit=slave_address)
            # print(response)
            if not response.isError():
                data = response.registers
                # print("读取到的数据:", data)
                # print(len(data))
                for i in range(0, 100, 2):
                    realdata_y.append(int_to_real(data[i + 1], data[i]))
                # d=[]
                # for i in data:
                #     d.append(convert_signed_integer(i))
                # print("读取到的数据:", d)
                # print(len(d))
                # int_data = d[3] << 16 | data[2]
                # print(int_data)
                # real_data = struct.unpack('!f', struct.pack('!I', int_data))[0]
                # print(real_data)

            else:
                print("读取数据时出错:", response)
        except Exception as e:
            print("发生异常:", str(e))
    # print(realdata_y)
    # print(len(realdata_y))

    # 关闭连接
    client.close()
else:
    print("无法连接到设备")

Modbus协议中的寄存器是用于存储和传输数据的内存区域,它们被分为两种类型:线圈寄存器和保持寄存器。Modbus协议中的寄存器协议如下:

1. 线圈寄存器(Coil Register):线圈寄存器用于存储开关量数据,只能读取或写入单个线圈,其地址从0开始。以下是线圈寄存器相关的协议:

- 功能码01H:读取多个线圈
- 功能码05H:写单个线圈,只能写入0或1

2. 保持寄存器(Holding Register):保持寄存器用于存储模拟量数据或控制信息,可以读取或写入单个或多个保持寄存器,其地址从0开始。以下是保持寄存器相关的协议:

- 功能码03H:用于读取保持寄存器的值,可以读取一个或多个连续的保持寄存器。
- 功能码04H:用于读取输入寄存器的值,可以读取一个或多个连续的输入寄存器。
- 功能码06H:用于写入单个保持寄存器的值。
- 功能码10H:用于写入多个保持寄存器的值,可以写入一个或多个连续的保持寄存器。

以上是Modbus协议中常用的寄存器协议,它们允许设备读取或写入不同类型和数量的寄存器数据,以满足各种应用需求。Modbus协议还有其他类型的寄存器,如输入寄存器(Input Register)和离散输入寄存器(Discrete Input Register),它们用于读取、存储和传输不同类型的数据。这些寄存器的详细信息可以在Modbus协议规范中找到。

IEEE 754是一种用于浮点数表示和计算的国际标准。它定义了浮点数的二进制表示形式、舍入规则和基本运算规则,旨在实现可移植性和一致性。寄存器中的数据以字节形式存储。在Python中,内置的struct模块提供了对IEEE 754浮点数的打包和解包功能。你可以使用struct.pack()函数将浮点数打包为字节序列,使用struct.unpack()函数将字节序列解包为浮点数。

根据IEEE 754标准,一个浮点数由三个主要组成部分构成:

  1. 符号位(Sign):用于表示数值的正负,0表示正数,1表示负数。

  2. 指数位(Exponent):用于表示浮点数的指数部分。指数位可以是一个有符号整数,也可以是一个无符号整数。指数位的范围决定了浮点数的可表示范围。

  3. 尾数位(Significand/Mantissa):用于表示浮点数的尾数部分。尾数位是一个二进制小数,通常为规范化形式(Normalized Form),即首位为1(除非表示的是零或非规范化数)

pymodbus库中,根据操作的不同,可以使用以下函数来执行相应的Modbus功能码操作:

# read_coils(address, count): 读取线圈寄存器(功能码01H),参数address表示起始地址,count表示数量。
# read_discrete_inputs(address, count): 读取离散输入寄存器(功能码02H),参数address表示起始地址,count表示数量。
# read_holding_registers(address, count): 读取保持寄存器(功能码03H),参数address表示起始地址,count表示数量。
# read_input_registers(address, count): 读取输入寄存器(功能码04H),参数address表示起始地址,count表示数量。
# write_coil(address, value): 写入单个线圈寄存器(功能码05H),参数address表示地址,value表示要写入的值(0或1)。
# write_register(address, value): 写入单个保持寄存器(功能码06H),参数address表示地址,value表示要写入的值。
# write_registers(address, values): 写入多个保持寄存器(功能码10H),参数address表示起始地址,values表示要写入的值列表。

  • 9
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值