python and PLC communication (Ethernet modbustcp)

To establish communication with a PLC in Python, you usually need to perform the following steps:

1. Determine the communication protocol of the PLC: Different PLC manufacturers and models may use different communication protocols, such as Modbus, OPC UA, Profinet, etc. Please first determine which communication protocol your PLC uses (this article is modbustcp).

2. Install the corresponding Python library: According to the PLC communication protocol you choose, install the corresponding library in Python. For example, if you use the Modbus protocol, you can install the `pymodbus` library; if you use the OPC UA protocol, you can install the `opcua` library.

3. Connect to the PLC: Use the corresponding libraries and code to establish a connection to the PLC in Python. The specific connection methods and codes will vary depending on the communication protocol. Here is an example:

4. Read or write data: According to your needs, use the corresponding libraries and methods to read or write PLC data. Here is an example:

from pymodbus.client import ModbusTcpClient
import struct


#Negative int
def convert_signed_integer(data):
    # Convert data to signed integer
    # result = (data & amp; 0xffff) - (data & amp; 0x8000)
    # return result
    if data > 0x7FFF:
        data -= 0x10000
    return data

#16 Convert integer to 32 real numbers
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

#IP address and port number of PCL device
ip_address = '192.168.1.88'
port=502

# Establish Modbus TCP connection
client = ModbusTcpClient(ip_address, port)

if client.connect():
    # Read the data in the holding register (example: addresses 0 to 9)
    slave_address = 1 #Slave address of the device
    start_address = 12288 #Start address
    num_registers = 100 # Number of registers to read
    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("Read data:", data)
                # print(len(data))
                for i in range(0, 100, 2):
                    realdata_x.append(int_to_real(data[i + 1], data[i]))

            else:
                print("Error while reading data:", response)
        except Exception as e:
            print("Exception occurred:", 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("Read data:", 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("Read data:", 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("Error while reading data:", response)
        except Exception as e:
            print("Exception occurred:", str(e))
    # print(realdata_y)
    # print(len(realdata_y))

    # Close the connection
    client.close()
else:
    print("Unable to connect to device")

Registers in the Modbus protocol are memory areas used to store and transmit data. They are divided into two types: coil registers and holding registers. The register protocol in the Modbus protocol is as follows:

1. Coil Register: The coil register is used to store switching data. It can only read or write a single coil, and its address starts from 0. The following is the protocol related to the coil register:

– Function code 01H: Read multiple coils
– Function code 05H: writing a single coil, only 0 or 1 can be written

2. Holding Register: Holding registers are used to store analog data or control information. Single or multiple holding registers can be read or written, and their addresses start from 0. The following is the protocol related to holding registers:

– Function code 03H: used to read the value of the holding register. One or more consecutive holding registers can be read.
– Function code 04H: used to read the value of the input register. One or more consecutive input registers can be read.
– Function code 06H: used to write the value of a single holding register.
– Function code 10H: used to write the values of multiple holding registers. One or more consecutive holding registers can be written.

The above are the commonly used register protocols in the Modbus protocol. They allow devices to read or write different types and amounts of register data to meet various application needs. The Modbus protocol also has other types of registers, such as input registers (Input Register) and discrete input registers (Discrete Input Register), which are used to read, store and transmit different types of data. Details of these registers can be found in the Modbus protocol specification.

IEEE 754 is an international standard for floating-point number representation and calculations. It defines the binary representation of floating-point numbers, rounding rules, and basic arithmetic rules, aiming for portability and consistency. The data in the register is stored in bytes. In Python, the built-in struct module provides packaging and unpacking functions for IEEE 754 floating point numbers. You can use the struct.pack() function to pack floating-point numbers into byte sequences, and the struct.unpack() function to unpack byte sequences into floating-point numbers.

According to the IEEE 754 standard, a floating point number consists of three main components:

  1. Sign bit (Sign): used to indicate the sign of a value, 0 represents a positive number, and 1 represents a negative number.

  2. Exponent: used to represent the exponent part of floating point numbers. The exponent bit can be a signed integer or an unsigned integer. The range of exponent bits determines the representable range of floating point numbers.

  3. Mantissa bit (Significand/Mantissa): used to represent the mantissa part of floating point numbers. The mantissa digit is a binary decimal, usually in the normalized form (Normalized Form), that is, the first bit is 1 (unless it represents zero or a denormalized number)

In the pymodbus library, depending on the operation, you can use the following functions to perform corresponding Modbus function code operations:

# read_coils(address, count): Read the coil register (function code 01H), the parameter address represents the starting address, and count represents the quantity.
# read_discrete_inputs(address, count): Read the discrete input register (function code 02H), the parameter address represents the starting address, and count represents the quantity.
# read_holding_registers(address, count): Read the holding register (function code 03H), the parameter address represents the starting address, and count represents the quantity.
# read_input_registers(address, count): Read input registers (function code 04H), the parameter address represents the starting address, and count represents the quantity.
# write_coil(address, value): Write a single coil register (function code 05H), the parameter address represents the address, and value represents the value to be written (0 or 1).
# write_register(address, value): Write to a single holding register (function code 06H). The parameter address represents the address and value represents the value to be written.
# write_registers(address, values): Write multiple holding registers (function code 10H), the parameter address represents the starting address, and values represents the list of values to be written. 

The knowledge points of the article match the official knowledge files, and you can further learn relevant knowledge. Python entry skill treeHomepageOverview 386,488 people are learning the system