3. S7comm 西门子PLC数据采集

任务目标

本案例实现一个基于 S7comm 协议的西门子 S7-1200 PLC 数据采集程序,使用 Python 的 python-snap7 库读取 PLC DB 块中的生产数据(整数、实数、布尔量),并输出到控制台。程序需具备连接状态检查、数据读取与错误处理能力。

环境依赖

  • Python 3.8+
  • 安装依赖:pip install python-snap7
  • PLC 侧需启用 PUT/GET 通信(S7-1200 在“设备组态 → 属性 → 防护与安全 → 连接机制”中勾选“允许来自远程对象的 PUT/GET 通信访问”)
  • PLC 与运行程序的 PC 需在同一以太网内,IP 可达

关键完整代码

import snap7
import struct
import time

# ========== 配置参数(按实际环境修改) ==========
PLC_IP = "192.168.0.1"
RACK = 0
SLOT = 1
DB_NUMBER = 1          # 数据块编号
READ_TIMEOUT = 3       # 秒

# DB1 内部偏移定义(示例布局)
OFFSET_INT = 0         # 2字节 整数(例如:当前工件计数)
OFFSET_REAL = 4        # 4字节 实数(例如:温度值)
OFFSET_BOOL = 10       # 1字节 位0(例如:设备运行状态)

def read_plc_data():
    """连接 PLC 并读取 DB 块中的生产数据"""
    client = snap7.client.Client()
    try:
        # 建立连接
        client.connect(PLC_IP, RACK, SLOT)
        if not client.get_connected():
            raise ConnectionError("无法连接到 PLC")

        print(f"✅ 已连接 PLC {PLC_IP} (机架 {RACK}, 槽位 {SLOT})")

        # 读取 DB 块数据(一次读取 12 字节,覆盖上述偏移区域)
        db_data = client.db_read(DB_NUMBER, 0, 12)

        # 解析数据(按小端字节序)
        int_value = struct.unpack_from(">h", db_data, OFFSET_INT)[0]      # 有符号16位整数
        real_value = struct.unpack_from(">f", db_data, OFFSET_REAL)[0]    # 32位浮点数
        bool_byte = db_data[OFFSET_BOOL]
        bool_value = bool(bool_byte & 0x01)   # 取第0位

        # 输出采集结果
        print(f"📊 工件计数 (INT): {int_value}")
        print(f"🌡️  温度值 (REAL): {real_value:.2f} °C")
        print(f"⚙️  设备运行状态 (BOOL): {'运行中' if bool_value else '停止'}")

        return int_value, real_value, bool_value

    except snap7.snap7exceptions.Snap7Exception as e:
        print(f"❌ Snap7 通信错误: {e}")
    except ConnectionError as e:
        print(f"❌ {e}")
    except Exception as e:
        print(f"❌ 未预期错误: {e}")
    finally:
        client.disconnect()
        print("🔌 连接已断开")

if __name__ == "__main__":
    # 单次采集(如需周期采集,可在此处加循环)
    read_plc_data()

运行方式

  1. 将上述代码保存为 s7_read.py
  2. 修改 PLC_IP、DB_NUMBER 及偏移量以匹配实际 PLC 组态
  3. 执行命令:python s7_read.py

验证方法

  • 连接验证:程序输出“✅ 已连接 PLC”且无异常,说明网络与通信参数正确
  • 数据验证:在 TIA Portal 中在线监控 DB1,对比程序输出的 INT/REAL/BOOL 值与 PLC 监控值是否一致
  • 错误验证:断开网线或修改错误 IP,程序应输出“❌ Snap7 通信错误”或“❌ 无法连接到 PLC”,且不会崩溃
  • 通过条件:程序能稳定读取并正确解析 DB 块中三种数据类型,数值与 PLC 侧一致

常见问题

  • 连接超时:检查 PLC IP 是否可达(ping),确认机架/槽位号(S7-1200 通常为 Rack 0, Slot 1)
  • 读取错误 0x81000000:DB 块不存在或偏移越界,核对 DB 编号与数据长度
  • 字节序错误:S7 协议使用大端字节序,代码中已用 >h 和 >f 正确解析
  • 无法访问 DB:确认 PLC 已启用 PUT/GET 通信,且 DB 块无优化访问(需取消“优化的块访问”属性)
S7comm 数据采集流程 西门子 S7-1200 PLC DB1 数据块 偏移0: INT 工件计数 偏移4: REAL 温度值 偏移10: BOOL 运行状态 (需取消“优化的块访问”) 以太网 / S7comm IP: 192.168.0.1 Rack 0 / Slot 1 Python 采集程序 snap7.Client() connect(IP, Rack, Slot) db_read(DB1, 0, 12) 读取 12 字节原始数据 struct 解析(大端) INT / REAL / BOOL 控制台输出 工件计数 / 温度 / 运行状态 验证:与 TIA Portal 在线监控值对比一致即通过