You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Python通过Modbus向Siemens Logo 8发送比特失败求助

如何通过Python的Modbus TCP触发西门子设备的BO31条件?

我尝试使用Python从IP为192.168.0.2的PC,向IP为192.168.0.11:504的西门子网络输入发送1比特数据,但未能成功实现。我的目标是通过Modbus连接发送比特以触发BO31条件,以下是我编写的Python代码:

import socket
from umodbus import conf
from umodbus.client import tcp

# Enable values to be signed (default is False).
conf.SIGNED_VALUES = True

### Creating connection
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(('192.168.0.11', 504))

message = tcp.write_multiple_coils(slave_id=1, starting_address=1, values=[1, 0, 0, 0])
# Response depends on Modbus function code. This particular returns the
# amount of coils written, in this case it is.
response = tcp.send_message(message, sock)
print(response)

sock.close()
print("Transfer finished")

请协助排查问题并提供解决方案。


问题排查与解决方案

我来帮你一步步拆解可能的问题,并给出针对性的解决办法:

1. 先确认西门子设备的Modbus核心配置

西门子设备(比如S7系列)默认不会自动开启Modbus TCP服务,这是最常见的坑:

  • 检查设备端是否启用了Modbus TCP服务器,端口是否确实是504(注意:标准Modbus TCP端口是502,504属于非标准端口,必须和设备配置完全一致)。
  • 核对Slave ID(站号):你代码里写的是1,但西门子设备的Modbus站号可能不是默认值,一定要在TIA Portal或设备的通信配置界面里确认。
  • 找到BO31对应的Modbus地址:你当前写的起始地址1不一定对应BO31。西门子的Modbus地址映射有规则,比如输入继电器I对应离散输入(功能码2),输出线圈Q对应线圈(功能码1/5/15),必须查设备的官方文档或配置工具里的地址映射表,确认BO31绑定的具体Modbus地址。

2. 修正代码中的冗余/错误参数

  • 去掉conf.SIGNED_VALUES = True:写入线圈是布尔值,完全不需要启用有符号值,这个设置可能干扰数据解析。
  • 改用write_single_coil更稳妥:你只需要触发1个比特,用单线圈写入函数比多线圈更直接,减少地址偏移出错的概率。
  • 添加异常捕获:你的代码没有处理连接或发送失败的情况,根本不知道是哪一步出问题,比如连接失败直接崩溃,看不到错误信息。

3. 排查网络层面的问题

  • 先ping设备:在CMD里执行ping 192.168.0.11,确认PC和设备在同一网段且连通。
  • 测试端口是否开放:用telnet 192.168.0.11 504验证端口是否能正常访问,连接失败的话要么是设备端口没开,要么是防火墙拦截(包括PC端和设备端的防火墙)。

修正后的示例代码

假设你核对后,BO31对应的Modbus线圈地址是0,站号1,端口504,修正后的代码如下:

import socket
from umodbus.client import tcp

# 创建连接并添加错误处理
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
    sock.connect(('192.168.0.11', 504))
    print("成功连接到设备")
except Exception as e:
    print(f"连接失败: {str(e)}")
    sock.close()
    exit()

# 写入单个线圈触发BO31
try:
    # 把address替换为BO31对应的实际Modbus地址
    message = tcp.write_single_coil(slave_id=1, address=0, value=1)
    response = tcp.send_message(message, sock)
    print(f"线圈写入成功,响应: {response}")
except Exception as e:
    print(f"发送消息出错: {str(e)}")

sock.close()
print("传输完成")

内容的提问来源于stack exchange,提问作者Paulius Ženčius

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 22:07:50