Article Directory
foreword
PLC (Programmable Logic Controller) Programmable logic controller can be understood as a microcomputer, which is widely used in industrial control, such as building intelligent control, precision machine tools, automotive electronics and so on.
With the rise of the Internet of Things, more and more traditional industrial equipment needs to communicate with the outside world. However, in many cases, microcontrollers like PLCs cannot directly communicate with the outside world due to their own hardware factors. The host computer such as PC acts as an intermediary bridge, opening a door for PLCs to communicate with the outside world.
As the most popular language at present, Python can be seen in many aspects such as AI and cloud computing. Of course, it cannot be missing in industrial control.
Here, just a novel about how to use Python to build communication between PC and PLC, it can also be regarded as a show of Python's demeanor in the field of industrial control.
提示:以下是本篇文章正文内容,下面案例可供参考
1. What exactly is Snap7?
The mainstream PLC communication methods in the current market are network communication and serial communication. The main protocols of network communication include profinet, modbus-tcp, etc. Serial communication is mainly based on RS232/485 modbus.
This time I came into contact with Siemens S7 series PLC, the communication method is network type, and Snap7 is an open source, 32/64 bit, multi-platform Ethernet communication library:
Support for multiple hardware architectures (i386/x86_64, ARM/ARM64, Sun Sparc, Mips)
Multi-system support (Windows, Linux, BSD, Solaris)
Multi-language support (C/C++, Phyton, Node.js, Pascal, C#, VB)
The official website is: http://snap7.sourceforge.net/
Python encapsulates it, for details, see:
https://github.com/gijzelaerr/python-snap7
2. Detailed steps to build the development environment
Here we mainly talk about how to build the Snap7 development environment in the Python environment from the two platforms of Windows and Linux (Ubuntu).
The installation of Python will not be repeated here. The environment construction is mainly the installation of the two libraries of Snap7 and python-snap7.
1. Install Snap7
Under Windows, you need to copy the downloaded Snap7 release library to the corresponding Python installation root directory according to the Python structural version (32-bit/64-bit).
As shown in the figure above, my python is 32bit, so I need to copy the files in the Win32 directory of Snap7 to the python installation root directory, as shown in the figure below:
Installation under Linux (Ubuntu) is relatively simple, just follow the command:
2. Install python-snap7
The python library installation of nap7 is much simpler, whether it is Windows or Linux, you can install it directly with pip.
$ pip install python-snap7
After the above two steps, even if the environment is set up, try a connection test code to judge whether the environment is set up normally.
import snap7
client = snap7.client.Client()
client.connect(‘192.168.0.1’, 0, 1)
client.disconnect()
If it is shown in the figure below, the environment is normal (the PLC of 192.168.0.1 does not exist)
4. Read and write PLC
After the environment is set up normally, the PLC still needs to do some configuration work before the formal establishment of communication, mainly to develop its own read and write permissions. For details, refer to the configuration in the figure below: Through the above configuration,
the PLC can communicate normally.
Combined with python-snap7's document API and source code analysis, the two important methods of python-sna7 are read_area and write_area, through which the corresponding storage address of PLC can be read and written.
def read_area(self, area, dbnumber, start, size):
"""This is the main function to read data from a PLC.
With it you can read DB, Inputs, Outputs, Merkers, Timers and Counters.
:param dbnumber: The DB number, only used when area= S7AreaDB
:param start: offset to start writing
:param size: number of units to read
"""
assert area in snap7.snap7types.areas.values()
wordlen = snap7.snap7types.S7WLByte
type_ = snap7.snap7types.wordlen_to_ctypes[wordlen]
logger.debug("reading area: %s dbnumber: %s start: %s: amount %s: "
"wordlen: %s" % (area, dbnumber, start, size, wordlen))
data = (type_ * size)()
result = self.library.Cli_ReadArea(self.pointer, area, dbnumber, start,
size, wordlen, byref(data))
check_error(result, context="client")
return bytearray(data)
@error_wrap
def write_area(self, area, dbnumber, start, data):
"""This is the main function to write data into a PLC. It's the
complementary function of Cli_ReadArea(), the parameters and their
meanings are the same. The only difference is that the data is
transferred from the buffer pointed by pUsrData into PLC.
:param dbnumber: The DB number, only used when area= S7AreaDB
:param start: offset to start writing
:param data: a bytearray containing the payload
"""
wordlen = snap7.snap7types.S7WLByte
type_ = snap7.snap7types.wordlen_to_ctypes[wordlen]
size = len(data)
logger.debug("writing area: %s dbnumber: %s start: %s: size %s: "
"type: %s" % (area, dbnumber, start, size, type_))
cdata = (type_ * len(data)).from_buffer_copy(data)
return self.library.Cli_WriteArea(self.pointer, area, dbnumber, start,
size, wordlen, byref(cdata))
It can be seen from the parameters that it is necessary to provide the PLC area address, start address, read and write data length.
What is the area address, PLC can provide the following information:
In the eyes of PLC programmers, there are only I, M, Q, DB,
Python programmers, panicked now, what is this?
How to see the beautiful scenery in the eyes of PLC programmers, you have to take another look at PLC.
By reading the PLC manual, the following information is obtained:
The data storage of the PLC is associated with the storage interval in the form of a tag, which is divided into input (I), output (O), bit storage (M) and data block (DB). When the program accesses the corresponding (I/O) tag, it accesses the Process Image Out of the CPU to operate on the corresponding address. The specific correspondence is as follows:
Here you can understand what the areas address defined in python-snap7 means.
areas = ADict({ 'PE': 0x81, #input 'PA': 0x82, #output 'MK': 0x83, #bit memory 'DB': 0x84, #DB 'CT': 0x1C, #counters 'TM': 0x1D, #Timers }) Now there is one last step before reading and writing PLC, how to determine the starting address?
It can be seen from the above that for M3.4, the corresponding is M (0x83), the starting address is 3, and the corresponding bit is 4.
Practical Operations (Key Points)
After careful preparation above, the next wave of actual combat will come.
Read and write PLC M10.1, MW201 to see how to read and write PLC.
import struct
import time
import snap7
def plc_connect(ip, rack=0, slot=1):
"""
连接初始化
:param ip:
:param rack: 通常为0
:param slot: 根据plc安装,一般为0或1
:return:
"""
client = snap7.client.Client()
client.connect(ip, rack, slot)
return client
def plc_con_close(client):
"""
连接关闭
:param client:
:return:
"""
client.disconnect()
def test_mk10_1(client):
"""
测试M10.1
:return:
"""
area = snap7.snap7types.areas.MK
dbnumber = 0
amount = 1
start = 10
print(u'初始值')
mk_data = client.read_area(area, dbnumber, start, amount)
print(struct.unpack('!c', mk_data))
print(u'置1')
client.write_area(area, dbnumber, start, b'\x01')
print(u'当前值')
mk_cur = client.read_area(area, dbnumber, start, amount)
print(struct.unpack('!c', mk_cur))
def test_mk_w201(client):
"""
测试MW201,数据类型为word
:param client:
:return:
"""
area = snap7.snap7types.areas.MK
dbnumber = 0
amount = 2
start = 201
print(u'初始值')
mk_data = client.read_area(area, dbnumber, start, amount)
print(struct.unpack('!h', mk_data))
print(u'置12')
client.write_area(area, dbnumber, start, b'\x00\x0C')
print(u'当前值')
mk_cur = client.read_area(area, dbnumber, start, amount)
print(struct.unpack('!h', mk_cur))
time.sleep(3)
print(u'置3')
client.write_area(area, dbnumber, start, b'\x00\x03')
print(u'当前值')
mk_cur = client.read_area(area, dbnumber, start, amount)
print(struct.unpack('!h', mk_cur))
if __name__ == "__main__":
client_fd = plc_connect('192.168.0.1')
test_mk10_1(client_fd)
test_mk10_1(client_fd)
plc_con_close(client_fd)
It can be seen from the code that MW201 determines area as MK according to M, determines data amount as 2Btye according to W, determines start as 201 according to 201, unpacks the read data with struct according to the data length, and writes data corresponding to the pack of strcut.
The PLC variable type and size are given here, so that the corresponding amount for reading and writing is determined.
If you have any questions, please leave a message, thank you for one click and three links!