2014-06-22 91 views
0

我无法通过pySerial从RS232 OBD2接口读取响应。 代码可以成功输入数据,正如我可以从直接并行终端屏幕上看到的,但无法读取和打印响应,无论响应如何。pySerial从AT命令读取数据

现在代码无法在两种版本的Python中打印响应。 代码看起来是这样的:

from serial import * # I also tried using /from serial import Serial 
import time 
ser = Serial("/dev/rfcomm1", 38400, timeout=1) 
#print ('Starting up, formatting responses') 
#ser.write("ATZ\r"), 
#ser.write("ATSP0\r"), 
#ser.write("ATS1\r"), 
#ser.write("ATL1\r"), 
#ser.write("ATH1\r"), 
#ser.write("ATF1\r") 
#time.sleep(1) 
#print ('We have lift-off !') 
if ser.inWaiting() > 0: 
    ser.flushInput() 
#ser.timeout = 1. 
time.sleep(1) 
#print (raw_data) 
ser.write("AT RV\r") #The response should be something like 13.5V, but nothing 
ser.timeout = 1. 
msg = ser.read(size=1024) 
print msg 
ser.close() 

我只留下了AT RV命令,因为虽然我的工作就可以了我发送的文本格式化命令来缓解工作。现在,当我发送它时,它只是给了我一个空行(尽管在同一台机器上运行的终端显示所需的输出)

代码中没有错误,并且命令经过并响应通过界面,我可以看到另一个实时术语,但是在运行Python代码时没有出现任何内容。 我该怎么办?

回答

3

你应该在写完之后阅读,而不是之前。

# before writing anything, ensure there is nothing in the buffer 
if ser.inWaiting() > 0: 
    ser.flushInput() 

# set the timeout to something reasonable, e.g., 1 s 
ser.timeout = 1. 

# send the commands: 
ser.write("ATZ\r") 
# ... 

# read the response, guess a length that is more than the message 
msg = ser.read(1024) 
print msg 

# send more commands 
# read more responses 
# ... 

这里的问题是,没有办法知道什么时候收到响应。该代码在发送每个命令后等待一秒,除非在此期间有超过1024个字节到达。有更多聪明的算法,但我们先试试这个。

如果您想对串口线做更复杂的操作,请查看pexpect模块。


的几点思考调试蟒蛇系列问题

串行通信的问题是有时有点粘解决。 pySerial是一个可靠的库,但由于不同平台有不同类型的串口API,因此有很多细节。由于USB转换器为游戏带来了额外的层次,物理串行端口的移除并没有让事情变得更容易。蓝牙转换器更糟糕。

调试物理层的最好方法是让一些监控硬件有两个串口分接到串口线上。这种嗅探器有助于将问题隔离到连接的任何一端。不幸的是,这种嗅探器在需要时很少在手边。

下一个最好的做法是将串行线路的RD和TD(RXD,TXD)引脚短路。这样所有的数据都会被回显。如果收到的数据是已发送的,则物理连接良好。有一点需要注意的是握手。如果您不知道自己在做什么,请禁用所有流量控制(xon/xoff,rts/cts,dtr/dsr。如果另有指示,pySerial将禁用所有流量控制。

在上述问题中,物理连接好的,因为另一个软件表明数据是由其他设备发送和理解的(看到发送的内容并不能证明任何东西,因为这些信息并不通过物理层,而是看到其他设备产生的东西是收到的证明,物理连接是好的。)

现在我们知道数据进入操作系统,但pySerial没有看到它。或者,然后我们的代码仍然有点不好(不,不应该,但是。 ..)

让我们怀疑自己的代码并尝试别人的代码。这可以从命令提示符运行:

python -m serial.tools.miniterm /dev/rfcomm1 38400 

现在我们有一个终端可以用来手动发送/接收对方的数据。如果这种行为可以重复发送(发送正常,数据被接收到系统中,但终端上未显示),那么问题可能不在我们的代码中。

然后下一步是尝试:

sudo python -m serial.tools.miniterm /dev/rfcomm1 38400 

原则访问权限问题导致的地方,我们可以接收但无法发送的情况。但是测试这个并没有什么坏处,因为奇怪的权利会导致奇怪的问题。

pySerial有一个方便的功能readline它应该从串行线一次读取一行。这往往是想要的。但是,在这种特定情况下,行似乎以\r而不是\n结束。代码中的其他地方可能会重复,因此需要特殊的数据。 (简单的“超时读取”在这个意义上是安全的,但速度很慢。)讨论如下:pySerial 2.6: specify end-of-line in readline()

同样的问题困扰着所有的终端程序。对于pySerial miniterm,请参阅其文档(命令行选项--cr)。

如果有超时,它们可以并且应该做更长的时间用于调试目的。一秒超时可能会变为十秒超时,以确保其他设备有充足的时间来应答。

+0

我尝试添加刷新部分,将超时设置为1秒,并在写入后移动了读取命令,但我得到的只是一个没有答案的空行。 –

+0

尝试使用串行终端程序手动发出命令并查看是否可以通过线路接收答案。问题可能在其他地方。另外,您应该编辑您为问题编写的新代码。然后很容易看到是否有什么问题。 – DrV

+0

接口接收代码发送的命令,并对它们作出响应(我可以在活终端中看到这一点),但代码无法读取,它只返回一个空格。 –

0

我有完全相同的问题,通过Python 2 IDLE没有结果显示在空闲屏幕上,但结果被重定向到picocom在终端活动。我需要捕捉结果,因为我的目标是读取传入的SMS。 以下代码解决了我的问题,我不知道原因,还在进行分析。

import time 
import serial 

modem1 = serial.Serial("/dev/ttyUSB3",baudrate=115200,timeout=0,rtscts=0,xonxoff=0) 
def sendat1(cmd): 
    if cmd == 'res' : modem1.write('Z'); return 
    if cmd == 'out' : modem1.write(chr(26)); return 
    modem1.write('AT+'+cmd+'\r') 
    time.sleep(3) 
    obu = str(modem1.inWaiting()) 
    msg = modem1.read(32798) 
    print(obu+':\n'+msg) 
    return 

try: 
    if modem1.inWaiting()>0: modem1.flushInput() 
    sendat1('res') 
    sendat1('CMGF=1') 
    sendat1('CMGL') 
    sendat1('out') 
finally: 
    modem1.close()