常州贞明电子科技有限公司
首页 / 技术指南 / 通信协议
通信协议

Python读取Modbus TCP继电器状态:端口502、站号254与地址0

用Python标准库读取贞明电子网口继电器首路状态,说明端口502、站号254、FC01及零基地址,附完整只读程序和异常排查。

贞明电子技术团队约 8 分钟阅读
ZMRN1016S3-V5以太网IO控制器

先限定设备和读取对象

本文针对官网站号254网口设备通信点表所列的继电器输出线圈。读取的是控制器输出状态,不等同于灯具亮度、电机转动或接触器辅助触点反馈。其他设备的Unit ID和寄存器定义,应使用对应型号协议。

首次对接先读取一个线圈,确认通信参数与地址基准,再增加设备或采集点数量。本文程序只发送FC01读取请求,不包含控制输出的写入操作。

把四个参数填对

电脑与设备网络可达后,准备设备当前IP。本文使用TCP端口502、Unit ID 254、FC01和起始偏移0,数量为1。参数含义如下。

参数本文取值常见误区
TCP端口502与网页或自定义TCP端口混用
Unit ID254误套其他厂商站号
功能码01 Read Coils把线圈误选为03保持寄存器
起始偏移0软件显示00001时未区分零基与一基
读取数量1首轮就请求超出型号通道数的点位

Modbus TCP通过MBAP头关联请求与响应;网关场景还可能使用Unit Identifier路由。协议格式参阅Modbus官方规范。本站型号使用254是产品约定,不是所有Modbus TCP设备的通用默认值。

完整Python只读程序

安装Python 3后,将下列程序保存为read_first_coil.py。在终端运行程序并传入设备当前IP:python read_first_coil.py 设备IP。程序不依赖额外库,连接或接收失败会输出异常信息。

import argparse, socket, struct

def receive(sock, length):
    data = b""
    while len(data) < length:
        part = sock.recv(length - len(data))
        if not part:
            raise ConnectionError("Connection closed before full response")
        data += part
    return data

def read_first_coil(host):
    # Read one coil only: transaction=1, protocol=0, unit=254, FC01.
    request = struct.pack(">HHHBBHH", 1, 0, 6, 254, 1, 0, 1)
    with socket.create_connection((host, 502), timeout=3) as sock:
        sock.sendall(request)
        transaction, protocol, length, unit = struct.unpack(">HHHB", receive(sock, 7))
        if (transaction, protocol, unit) != (1, 0, 254) or not 2 <= length <= 254:
            raise ValueError("Invalid MBAP header")
        pdu = receive(sock, length - 1)
    if len(pdu) == 2 and pdu[0] == 0x81:
        raise ValueError("Modbus exception: " + str(pdu[1]))
    if len(pdu) != 3 or pdu[:2] != b"\x01\x01":
        raise ValueError("Invalid FC01 response")
    return bool(pdu[2] & 1)

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="Read first relay coil, Unit ID 254")
    parser.add_argument("host", help="Device IP address or hostname")
    args = parser.parse_args()
    print("ON" if read_first_coil(args.host) else "OFF")

怎样判断读取结果

正常返回ON或OFF。程序检查事务号、协议标识、站号、响应长度、功能码和字节数量,再取返回数据的最低位作为首路状态。TCP可能分段传输,因此接收函数会持续读取到规定长度,不把一次recv返回当成完整报文。

若出现Modbus exception,记录异常码并核对功能码及点位范围。超时先查网络与服务端口;头部不符合预期则核对是否连到了其他协议服务。单路读通后,可按实际设备通道数扩展连续读取,不能直接把32路点表全部套到8路设备。

从首路读取到上位系统接入

建立点位清单时,同时保留设备型号、输出用途、协议偏移、软件显示地址和现场反馈来源。PLC、HMI和SCADA对地址显示的处理可能不同,应以同一回路的读取结果核对映射。

需要判断负载实际运行时,可配合开关量反馈或电流采集。继电器状态、接触器反馈和运行电流分别代表不同信息,组合后才能定位“命令已执行,但现场未运行”的原因。控制写入应在完成回路映射及现场条件检查后单独联调。

常见问题

所有Modbus TCP设备都填站号254吗?

不是。254适用于本文引用点表所列的贞明电子网口设备;其他型号使用各自协议规定值。

程序读到ON,是否表示负载已运行?

表示所读输出线圈处于ON状态。负载运行需结合现场触点、电流或其他反馈判断。

需要产品选型、协议或项目配合?

提供现场对象、通信条件、设备或采集点数量和期望功能,贞明电子可协助梳理设备与系统方案。

咨询 16605298829

联系贞明电子

选型、采购或项目咨询,可直接拨打电话,也可留下联系方式。

拨打电话16605298829淘宝店铺 ↗
询价清单 0