本文详细介绍了如何使用 Python 通过以太网与 Schneider M221 和 Siemens S7-1200 PLC 进行通信。此外,我们还提供了一个打包的 Python PLC 客户端库,使您能够轻松构建自己的 SCADA 控制程序,例如人机界面 (HMI)。系统概述如下所示:
# Created: 2024/06/29
# Version: v0.1.3
# Copyright: Copyright (c) 2024 LiuYuancheng
# License: MIT License
简介
本文将通过四个基本步骤,引导初级 OT 工程师在 SCADA 网络中配置可编程逻辑控制器 (PLC),并使用 Python 脚本或我们的 Python 物理 PLC 通信客户端库与 PLC 进行通信。这四个步骤包括:
-
[步骤 1] 配置 PLC:学习如何使用 PLC 供应商的 IDE 设置 PLC 的 IP 地址,从而实现网络连接。请注意,本节不包括电气接线连接。
-
[步骤 2] 配置梯形图逻辑:了解如何配置 PLC 的 I/O 和梯形图,以链接触点、内存和线圈。
-
[步骤 3] 了解 PLC 通信协议:简要概述用于与 PLC 交互的通信协议。本节是可选的。
-
[步骤 4] 使用 Python 控制 PLC:解释如何构建 Python 程序来控制 PLC,包括演示如何使用 Python 物理 PLC 通信客户端 API 的代码示例。
M221 PLC 简介
步骤 1:配置 Schneider M221 PLC
启动 M221 PLC 并将其连接到网络。使用 SoMachine 编辑器搜索并连接到 PLC 单元。然后在 MyController > ETH1
部分中为 PLC 配置固定 IP 地址并启用 Modbus 通信,如下所示:
图 03:M221 PLC IP 配置页面,版本 v1.3 (2024)
选择 固定 IP 地址
并填写 IP 信息,选中 启用 EtherNet/IP 协议
和 启用 Modbus 服务器
。然后,同一子网中的程序可以通过 IP 地址连接到 PLC 并与 Modbus 服务器通信。
步骤 2:配置梯形图逻辑
Rung 1: [ I0.x ] --> | M1x |
Rung 2: | M1x | --> | 您的梯形图逻辑 | --> | M2x |
Rung 3: | M2x | --> ( Q0.x )
打开 SoMachine 梯形图配置页面,并添加如下所示的梯形图逻辑:
图 04:SoMachine 编辑梯形图逻辑梯级,版本 v1.3 (2024)
然后,在调试页面中,选择“PC to Controller (download)”将梯形图逻辑提交到 PLC,如下所示:
步骤 3:了解通信协议
-
事务标识符(2 个字节):事务的唯一标识符。它通常由客户端设置,并由服务器回显。
-
协议标识符(2 个字节):对于 Modbus TCP,始终设置为 0。
-
长度(2 个字节):后续字节数,包括单元标识符、功能代码和数据。
-
单元标识符(1 个字节):远程服务器 (PLC) 的地址。
-
功能代码(1 个字节):定义要执行的操作(例如,读取保持寄存器)。
-
数据:这包括请求或响应的具体细节(例如,起始地址、寄存器数量)。
要与 PLC 交互,您需要使用特定的 Modbus 功能代码:
-
'0f'
:用于写入多个位的内存位访问功能代码。 -
'01'
:用于读取内部多个位的内存位状态获取功能代码%M
。
要使用更多功能,请参阅第 196 页中的功能代码表。
Figure-06: M221 Modbus 功能代码表,版本 v1.3 (2024)
M221 Modbus-TCP 数据包序列表如下所示:
Figure-07: M221 Modbus 数据包字节序列图,版本 v1.3 (2024)
从内存读取位数据的 Modbus 消息序列:
TID | PROTOCOL_ID | 长度 | UID | 功能代码 | 内存索引 | 位数量 |
---|---|---|---|---|---|---|
2 字节 | 2 字节 | 2 字节 | 1 字节 | 1 字节 | 2 字节 | 2 字节 |
0000 |
0000 |
0006 |
01 |
01 |
<0032> |
<0008> |
将字节数据写入内存的 Modbus 消息序列:
TID | PROTOCOL_ID | 长度 | UID | 功能代码 | 内存索引 | 位索引 | 字节索引 | 值字节 | ||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
2 字节 | 2 字节 | 2 字节 | 1 字节 |
要将内存标签
步骤 4:使用 Python 与 PLC 通信4.1 初始化连接 要与 PLC 通信,首先初始化一个 TCP 客户端,该客户端连接到 PLC 的 IP 地址的 502 端口,如下所示: self.plcAgent = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 4.2 向 PLC 发送消息 要向 PLC 发送消息,请将十六进制字符串转换为字节: bdata = bytes.fromhex(modbusMsg) 4.3 读取 PLC 内存数据 基于步骤 3,构建内存读取 Modbus 消息并调用发送函数以从 PLC 读取内存字节。 def readMem(self, memAddrTag, bitNum=8): 输入:
4.4 写入 PLC 内存数据 与数据读取相同,基于步骤 3 中的字节序列构建 modbus 消息: def writeMem(self, memAddrTag, val):
完整的 Python M221 PLC 客户端程序您可以从此链接下载完整的 Python M221 PLC 客户端程序:。该程序包括连接 PLC、读取/写入内存位的 API 以及一个线程包装器类,该类允许您在主程序中并行运行 PLC 读取器,以定期读取 PLC 状态。 该库还提供了三个测试用例:
与 Siemens S7-1200 PLC 通信
PLC 简介 : 西门子 S7-1200 PLC 是一款紧凑且多功能的 可编程逻辑控制器,专为各种工业自动化应用而设计。它属于 SIMATIC S7 系列,以其强大的性能、可扩展性和易用性而闻名。它具有内置的 PROFINET 接口,并支持各种通信协议,从而可以无缝集成到工业网络中。S7Comm 是西门子 PLC(包括 S7-1200 系列)使用的一种专有通信协议,用于促进设备和软件之间的通信。它通过各种物理层(包括以太网(通过 PROFINET))运行,从而允许 PLC、HMI 和 SCADA 系统之间进行数据交换。
步骤 1:配置西门子 S7-1200
将西门子 S7-1200 PLC 连接到您的网络。使用西门子 PLC 编辑器软件,,在 PROFINET 接口页面中配置 IP 地址:
您可以按照本文中概述的步骤操作:https://www.geekering.com/categories/automation/rodrigovieira/siemens-tia-portal-s7-1200-plc-online-connection-2/来设置 IP 地址并配置 PLC。 步骤 2:配置梯形图逻辑和存储区
| ix.x/mx.x | --> | 您的梯形图逻辑 | --> | qx.x/mx.x |
要实现此目的,请创建一个块并按照下图所示合并梯形图逻辑:
当使用默认存储区时,触点、线圈和可编辑存储器的起始地址如下:
步骤 3:了解通信协议
有关详细的 S7Comm 数据包结构,您可以参考这篇文章:https://blog.viettelcybersecurity.com/security-wall-of-s7commplus-part-1/。数据包结构如下图所示:
为了使用 S7Comm 协议与 PLC 通信,我们将使用 Python snap7 库https://python-snap7.readthedocs.io/en/latest/。此库提供函数
步骤 4:使用 Python 与 PLC 通信4.1 初始化连接 为了建立与 PLC 的通信,我们初始化一个 snap7 客户端,该客户端使用端口 102 连接到 PLC 的 IP 地址,如下面的代码片段所示: self.plcAgent = snap7.client.Client()
4.2 读取 PLC 存储器 S7-1200 支持从不同存储区读取各种数据类型的数据。支持以下数据类型:
|