先限定设备和读取对象
本文针对官网站号254网口设备通信点表所列的继电器输出线圈。读取的是控制器输出状态,不等同于灯具亮度、电机转动或接触器辅助触点反馈。其他设备的Unit ID和寄存器定义,应使用对应型号协议。
首次对接先读取一个线圈,确认通信参数与地址基准,再增加设备或采集点数量。本文程序只发送FC01读取请求,不包含控制输出的写入操作。
把四个参数填对
电脑与设备网络可达后,准备设备当前IP。本文使用TCP端口502、Unit ID 254、FC01和起始偏移0,数量为1。参数含义如下。
| 参数 | 本文取值 | 常见误区 |
|---|---|---|
| TCP端口 | 502 | 与网页或自定义TCP端口混用 |
| Unit ID | 254 | 误套其他厂商站号 |
| 功能码 | 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状态。负载运行需结合现场触点、电流或其他反馈判断。


