Python串行一次写入延迟

2024-05-17 10:56:45 发布

您现在位置:Python中文网/ 问答频道 /正文

我对pyserial有一个奇怪的问题,它使用Python 3.6.9,在WSL Ubuntu18.4.2 LTS下运行

我设置了一个简单的函数,用于将GCODE命令发送到串行端口:

def gcode_send(data):
    print("Sending: " + data.strip())
    data = data.strip() + "\n"  # Strip all EOL characters for consistency
    s.write(data.encode())  # Send g-code block to grbl

    grbl_out = s.readline().decode().strip()
    print(grbl_out)

它可以工作,但我发送的每个命令都会被“保留”到下一个命令发送为止

例如

  1. 我发送G0 X0>;设备没有反应
  2. 我发送G0 X1>;设备对G0 X0作出反应
  3. 我发送G1 X0>;设备对G0 X1作出反应
  4. 等等

我的设置代码是:

s = serial.Serial(com, 115200)

s.write("\r\n\r\n".encode())  # Wake up grbl
time.sleep(2)  # Wait for grbl to initialize
s.flushInput()  # Flush startup text in serial input

我现在可以解决延迟的问题,但这很烦人,我找不到其他人有同样的经历。你知道这是什么原因吗


Tags: to命令gtfordataout作出反应encode
2条回答

来了。代码在注释中承诺。它的大部分都被删除了,并且还进行了错误检查

它是一款通过蓝牙在Symbian系列诺基亚智能手机上使用PyS60 Python控制台的打字终端。工作得非常好


from serial import *
from thread import start_new_thread as thread
from time import sleep
import sys, os

# Original code works on Linux too
# The following code for gettin one character from stdin without echoing it on terminal
# has its Linux complement using tricks from Python's stdlib getpass.py module
# I.e. put the terminal in non-blocking mode, turn off echoing and use sys.stdin.read(1)
# Here is Win code only (for brevity):
import msvcrt

def getchar ():
    return msvcrt.getch()

def pause ():
    raw_input("\nPress enter to continue . . .")

port = raw_input("Portname: ")
if os.name=="nt":
    nport = ""
    for x in port:
        if x.isdigit(): nport += x
    port = int(nport)-1

try:
    s = Serial(port, 9600)
except:
    print >> sys.stderr, "Cannot open the port!\nThe program will be closed."
    pause()
    sys.exit(1)

print "Port ready!"
running = 1

def reader():
    while running:
        try:
            msg = s.read()
            # If timeout is set
            while msg=="":
                msg = s.read()
            sys.stdout.write(msg)
        except: sleep(0.001)

thread(reader,())

while 1:
    try: c = getchar()
    except Exception, e:
        running = 0
        print >> sys.stderr, e
        s.write('\r\n\x04')
        break
    if c=='\003' or c=='\x04':
        running = 0
        s.write('\r\n\x04')
        break
    s.write(c)

s.close()
pause()

这里可能会有很多问题,但请放心,pyserial并不是问题的根源。它使用底层操作系统的API与UART驱动程序通信。也就是说,您首先必须使用真正的Linux测试您的代码,以查看WSL是否导致了这种情况。即Linux和Windows UART缓冲区是否正确同步。 很抱歉,我无法判断您的代码中是否存在问题,因为我不知道您正在使用的设备,因此我无法猜测其通信通道末端发生了什么。请记住,在最好的情况下,单靠Windows操作系统可能会表现得很怪异,因此,请在这里为一些挫折做好准备。检查主板或USB2串行转换器驱动程序或您正在使用的任何硬件

接下来,您应该知道,如果没有设置超时,有时通信会变得混乱。为什么?没有人真正知道。因此,尝试设置超时。检查是否需要打开软件Xon/Xoff,以及与之通信的设备可能需要的其他RS232参数

另外,看看s.readline()是怎么回事,我个人不会使用它。超时可能会有所帮助,或者您可以将s.read(1024)与超时一起使用。我现在不记得了,但看看pyserial是否支持异步通信。如果有,您可以尝试使用它而不是标准的阻塞模式

另外,检查是否必须在s.write()之后强制刷新串行缓冲区,或在其之后添加睡眠。可能发生的情况是,设备未收到消息,但已激活读取请求。由于设备没有收到命令,因此没有响应。在您发送另一个命令后,IO缓冲区将被刷新,上一个将被传递,依此类推。串行通信很有趣,但当它遇到障碍时,它可能是a中的一个真正的P,相信我

现在,请检查设备是否仅发送“\r\n\r\n”或“\r\n”,或“\r”或“\n”作为响应。s、 readline()可能会混淆。首先,试着把两个s.readline()一个接一个地放在那里,然后打印出每个输出。如果设备发送双下线,则当您发送另一个命令时,s.readline()将在空行上停止,并且您的程序将收到一个空响应。s.readline()将通过缓冲区返回一个已存在但以前未读取的完整行

相关问题 更多 >