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

Debian系Linux中df1py3与Allen-Bradley PLC通信失败求助

问题描述

我在Ubuntu和Raspberry Pi OS上尝试用Python库df1py3通过DF1协议与Allen-Bradley PLC通信,该库在Windows 10上测试正常,但在这两款Debian系发行版中运行时出现串口写入超时错误。用Python标准serial库测试串口通信正常,说明串口本身无问题。我已使用Python虚拟环境避免系统Python冲突。

错误信息

network-server@network-server-ThinkPad-T470-W10DG:~$ sudo /bin/python3 "/home/network-server/proj/df1py3-1 (2).0a45-py3-none-any/proj.py"
[sudo] password for network-server: 
[INFO] Connecting to MicroLogix 1000 port /dev/ttyUSB0 speed 19200
[WARN] Waiting for clear any comm with PLC...
[WARN] Waiting for clear comm- done
[INFO] Connect Status: OK
Running 1
Exception in thread Serial thread:
Traceback (most recent call last):
  File "/usr/lib/python3.12/threading.py", line 1073, in _bootstrap_inner
    self.run()
  File "/usr/lib/python3.12/threading.py", line 1010, in run
    self._target(*self._args, **self._kwargs)
  File "/home/network-server/proj/df1py3-1 (2).0a45-py3-none-any/df1/models/df1_serial_plc.py", line 124, in _serial_loop
    self._send_loop()
  File "/home/network-server/proj/df1py3-1 (2).0a45-py3-none-any/df1/models/df1_serial_plc.py", line 136, in _send_loop
    self._serial_send(buffer)
  File "/home/network-server/proj/df1py3-1 (2).0a45-py3-none-any/df1/models/df1_serial_plc.py", line 141, in _serial_send
    self._plc.write(buffer)
  File "/usr/lib/python3/dist-packages/serial/serialposix.py", line 630, in write
    raise SerialTimeoutException('Write timeout')
serial.serialutil.SerialTimeoutException: Write timeout
[ERROR] Error send command <df1.models.reply_timeout.ReplyTimeout object at 0x713b7aa61b80>
[ERROR] Read integer error 
[ERROR] Runtime error has happened 

测试代码

# Example of how use class to read DF1 protocol (PCCC commands) from Allen Bradley PLC using serial
# Authors:
#  - Jerther Thériault <jtheriault@metalsartigan.com>
#  - Reyan Valdes <rvaldes@itgtec.com>

# Repositories
# Original: https://github.com/metalsartigan/pydf1
# Adapted: https://github.com/reyanvaldes/pydf1

import time
import serial


from df1.models.df1_serial_client import Df1SerialClient
from df1.models.df1_base import TIMER, COUNTER, BIT

client = Df1SerialClient(plc_type='MicroLogix 1000', src=0x0, dst=0x1,
                         port='/dev/ttyUSB0',
                         baudrate=19200, parity=serial.PARITY_NONE,
                         stopbits=serial.STOPBITS_ONE, bytesize=serial.EIGHTBITS,
                         timeout=3)
client.connect()

output =0

for i in range(3):
    print('Running',i+1)
    start_time = time.time()

    output += 1
    output = 0 if output>15 else output

    # Write operations
    # client.write_binary(start=0,data=[0b1100])
    # client.write_output(data=[output]) # 0b1101
    # client.write_register(data=[11,25])
    # client.write_float(start=0, data=[11.5,26.4])

    # Reading operations OK
    try:
        print('N7:3-5',    client.read_integer(start=90, total_int=8))  # Read Integers OK
        # print('N7:0-2', client.read_integer(start=0, total_int=3))  # Read Integers OK
        # print('Timer4:1',  client.read_timer(start=1, category=TIMER.ACC))  # Read Timer OK
        # print('Counter5:0',client.read_counter(start=0, category=COUNTER.PRE)) # Read Counter OK
        # print('R6:0', client.read_register(start=0, total_int=4))  # Read Registers- CONTROL OK
        # print('B3:0', client.read_binary(start=0))  # Read Binary bits words OK
        # out0 = client.read_output(start=0, bit=BIT.ALL, total_int=1)
        # print('O0:0/1', out0)# , 'bit', client.bit_inspect(out0, BIT.BIT3))  # Read Outputs OK and Bits inspect
        # print('I1:0', client.read_input(start=0, bit=BIT.BIT1, total_int=2))  # Read Inputs
        # # Testing
        # print('Float8:0',client.read_float(start=0, total_float=2))  # Read Float
    except Exception as e:
        print('[ERROR] Runtime error has happened',e)
        client.reconnect()
    except KeyboardInterrupt:
        print('Control+C')
        break

    end_time = time.time()
    print('Elapsed(s)', end_time-start_time)
    print('-------------------')

client.close()

print('end testing, total reconnect', client.reconnect_total())

已尝试的解决步骤

  • 修改串口权限
  • 更换串口线缆
  • 更换设备(从树莓派OS换到Ubuntu)
  • 使用标准serial库测试(通信正常,确认串口可用)
  • 更换目标PLC(从MicroLogix 1200换成带03 CPU的SLC500)
  • 排查依赖库问题
  • 在Stack Overflow发帖求助

解决建议

  1. 调整串口写入超时配置
    查看df1_serial_plc.py中串口写入的超时设置,Linux下串口超时逻辑与Windows存在差异。尝试在Df1SerialClient初始化时显式添加write_timeout参数(比如write_timeout=5),延长写入等待时间。

  2. 启用硬件流控
    DF1协议通常依赖RTS/CTS硬件流控,Windows可能默认启用该配置,但Linux需要手动设置。在Df1SerialClient的参数中添加rtscts=True,验证是否解决超时问题。

  3. 替换写入逻辑调试
    在_serial_send方法中添加日志,打印待写入的buffer内容和实际写入字节数。尝试用标准serial库的写入代码替换self._plc.write(buffer),对比Windows与Linux下的写入行为差异。

  4. 降级Python版本
    当前使用Python 3.12,df1py3可能对新版本Python的串口库支持存在兼容问题。尝试降级到Python 3.10或3.11版本,重新测试通信。

  5. 禁用串口硬件缓冲区
    Linux串口默认的硬件缓冲区可能导致写入延迟,可在初始化串口后执行self._plc.set_buffer_size(rx_size=0, tx_size=0),或通过系统命令调整缓冲区大小。

内容的提问来源于stack exchange,提问作者Andy Sagraves

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 13:22:33