线路缓冲串行输入

Joh*_*nny 7 python io serial-port

我有一个串口设备,我正在尝试从中读取输入.我发送了一个字符串"ID\r \n",它返回"ID XX\r"(其中\ r是ASCII回车,十六进制0x0d).

由于不再支持serial.readline上的eol选项,我使用TextIOWrapper从串口读取并一次返回一行.

我的问题是,它不会在看到回车后立即返回我的字符串,而是等到我打开串口时设置的超时时间的两倍.我希望它在读取整行后立即返回字符串,因为我可能有数百个命令发送到设备,我不想每次都等待超时.如果我超时设置为0,然后我得到根本没有输出(大概是因为我的脚本将停止等待的设备有机会输出任何东西前),如果我超时设置为无,脚本块,直到永远.

这是一个简单的测试脚本:

import serial
import io
import time

ser = serial.Serial("/dev/ttyUSB0", baudrate=9600,
                    bytesize=8, parity='N', stopbits=1,
                    xonxoff=0, rtscts=1, timeout=5)

sio = io.TextIOWrapper(io.BufferedRWPair(ser, ser),
                       newline=None)


sio.write(unicode("ID\r"))
sio.flush()

print "reading..."

x = sio.readline()

print len(x)
print x
Run Code Online (Sandbox Code Playgroud)

脚本始终需要10秒钟才能显示"读取",直到打印出从串行端口读取的"ID XX"字符串.

我确定设备正在输出回车,因为我使用了strace来观察读数:

select(4, [3], [], [], {5, 0})          = 1 (in [3], left {4, 991704})
read(3, "I", 8192)                      = 1
select(4, [3], [], [], {5, 0})          = 1 (in [3], left {4, 999267})
read(3, "D", 8191)                      = 1
select(4, [3], [], [], {5, 0})          = 1 (in [3], left {4, 999420})
read(3, " ", 8190)                      = 1
select(4, [3], [], [], {5, 0})          = 1 (in [3], left {4, 999321})
read(3, "X", 8189)                      = 1
select(4, [3], [], [], {5, 0})          = 1 (in [3], left {4, 999355})
read(3, "X", 8188)                      = 1
select(4, [3], [], [], {5, 0})          = 1 (in [3], left {4, 999171})
read(3, "\r", 8187)                     = 1
select(4, [3], [], [], {5, 0})          = 0 (Timeout)
select(4, [3], [], [], {5, 0})          = 0 (Timeout)
Run Code Online (Sandbox Code Playgroud)

您可以看到2个select()超时,它们提供10秒的延迟,但您也可以清楚地看到正在读取的回车.我已经尝试将newline参数设置为'None'和''(它应该自动允许\ r,\n和\ r \n),以及'\ r',但每次都有相同的结果.

我也尝试将BufferedRWPair()调用中的buffer_size设置为'1'以防止缓冲输入,但这没有任何区别.

知道我做错了什么吗?

如果我不能得到这个工作,我的下一个步骤将是使用serial.read()一次读取一个字符,做自己的行缓冲,但我想尝试做它用textiowrapper"正确"的方式第一.

Bou*_*uke 6

今天浪费了几个小时.事实证明,io.BufferedReader读取直到它填充缓冲区然后将缓冲区传递给io.TextIOWrapper.默认缓冲区大小为8192,因此根据您的设备,这可能需要一段时间.

正确的示例代码应该是:

# buffer size is 1 byte, so directly passed to TextIOWrapper
sio = io.TextIOWrapper(io.BufferedRWPair(ser, ser, 1), encoding='ascii')
print sio.readline()[:-1]
Run Code Online (Sandbox Code Playgroud)


Kei*_*ith 0

如果没有实际看到它,这将很难调试。但看看你是否可以使用我的 tty 模块。

http://code.google.com/p/pycopia/source/browse/trunk/aid/pycopia/tty.py

尝试其中的 SerialPort 对象。我已经成功地使用它与串行仪器进行交互,其中“另一个串行模块”有很多与您所描述的类似的问题。它还可以告诉您 FIFO 中是否有数据。

现在让我看看进展如何。