Python串行,切换波特率后丢失数据

时间:2015-11-26 17:19:41

标签: python serial-port byte buffer baud-rate

我尝试使用python的串行模块(以及带光学读头的USB转串口转换器(FTDI))读取电表,它使用IEC 62056-21中描述的协议。已知该设置可与其他软件一起使用。

发送b&#39; /?!\ r \ n&#39;在300bit / s时,仪表响应制造商,固件版本和切换通信速度的建议。因此,程序确认速度并请求&#34;数据读出模式&#34; <ack>050<CR><LF>其中5是速度9600.然后程序切换波特率。

在波特率开关之前,一切都很好。正常行为是仪表发送的数据帧以<STX>开头并以<ETX>结尾并包含以<CR><LF>结尾的多行文本。
但是大约有9行文字丢失了。该计划赶上了第9或第10行中间的某个地方。有时我会得到一长串Null字节 这是代码(我留下了一些测试留下的评论):

import serial
import re
from time import sleep

def readframe():
    buf=b''
    while (buf == b'' or buf[-1] != b'\x03'):
        buf+=ser.read(1)
        print(buf)  
    return buf

ser =serial.Serial(port=PORT,baudrate=300,bytesize=serial.SEVENBITS,parity=serial.PARITY_EVEN,stopbits=serial.STOPBITS_ONE,timeout=5)

repeat=True
while repeat:
    ser.setBaudrate(300)
    sleep(1)    
    ser.write(b'/?!\r\n')
    response=ser.readline()
    print(response)
    pattern = re.compile(r'/(...)(\d)\\@(.*)')
    m=pattern.match(response.decode("ASCII"))
    if not m:
        repeat= True
    else: repeat=False

manufacturer,speed,version=m.group(1,2,3)
speedcode=int(speed)
baudrates=(300,600,1200,2400,4800,9600,19200)
s=bytes([6,48,48+speedcode,48,13,10])  #option request data readout mode
print(s)
ser.write(s)
sleep(1)
ser.flush()
#ser.close()
#ser =serial.Serial(port=PORT,baudrate=baudrates[speedcode],bytesize=7,parity='E',stopbits=1,timeout=5)
ser.setBaudrate(9600)
#sleep(1)
#ser.setTimeout=None
frame=readframe()


ser.close()

我尝试了很多东西,比如刷新缓冲区,以不同的速度关闭和重新打开,插入暂停,读取行而不是字节,使用inWaiting()以及更多。 我怀疑在一段时间内切换波特率时没有任何缓冲,所以我丢失了一些数据。 顺便说一句,我在Windows上使用它,Winpython发行版(在我工作的地方,这就是为什么)串行模块的版本是2.7。

下面是一个如何进行通信的示例(通信记录,时间和方向部分用德语)。在我的程序中,我只收到0.2.0 on:

的行
Komm: 11:29:57,62 -- Teilnehmer-Name = Lokale Schnittstelle
Komm: 11:29:58,34 -- Schnittstelle   = SERIELL über COM-Port Nr: 4
Komm: 11:29:58,35 -- Komm Settings   = 300,7,E,1
Send: 11:29:58,57 -- /?!<CR><LF>
Recv: 11:29:59,80 -- /ABB5\@V4.50         <CR><LF>
Send: 11:30:00,01 -- <ACK>050<CR><LF>
Komm: 11:30:00,31 -- Komm Settings   = 9600,7,E,1
Recv: 11:30:00,57 -- <STX>0.0.0(00491465)<CR><LF>
Recv: 11:30:00,60 -- 0.9.1(112957)<CR><LF>
Recv: 11:30:00,66 -- 1.6.1(0000.00*kW)(0000000000)<CR><LF>
Recv: 11:30:00,73 -- 1.6.1*04(0000.00)(0000000000)<CR><LF>
Recv: 11:30:00,79 -- 1.6.2(0000.00*kW)(0000000000)<CR><LF>
Recv: 11:30:00,88 -- 1.6.2*04(0000.00)(0000000000)<CR><LF>
Recv: 11:30:00,91 -- 1.8.1(00000000*kWh)<CR><LF>
Recv: 11:30:00,94 -- 1.8.1*04(00000000)<CR><LF>
Recv: 11:30:00,97 -- 1.8.2(00000000*kWh)<CR><LF>
Recv: 11:30:01,02 -- 1.8.2*04(00000000)<CR><LF>
Recv: 11:30:01,05 -- 0.2.0(05F1)<CR><LF>
Recv: 11:30:01,08 -- !<CR><LF>
Recv: 11:30:01,09 -- <ETX>i Soll: i
Komm: 11:30:01,41 -- Seriell-Status  = Geschlossen

感谢阅读,非常感谢任何帮助!

2 个答案:

答案 0 :(得分:0)

我猜测仪表正在快速切换到新的波特率 - 传输波特率改变命令的五个字符可能需要0.2秒,但是你的睡眠(1)意味着仪表可能已经开始以新的速率和数据发送在您将波特率更改为9600之前丢失。尝试缩短它?

答案 1 :(得分:0)

万一它对某人有帮助,那么在改变波特率为beodrate = 9600之前对我睡个好觉(0.3)是一件好事。 我使用的是Hexing 23DL仪表。

重要的是,您必须在更改速度之前有300毫秒的时间。如果您有多行代码,则应计算确定的睡眠时间()。或测试值介于0.270和0.30之间。

...
time.sleep (0.3)
ser.Baudrate = speed # any speed
...