Python pySerial inWaiting 返回错误的字节数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19161768/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 13:02:12  来源:igfitidea点击:

pySerial inWaiting returns incorrect number of bytes

pythonpyserial

提问by user791953

I've got a simple program to test serial functionality. My serial device reacts to two inputs. If the user enters 'a', it responds with 'fg'. If the user enters anything other character/byte, it responds with 'z'. If I send 'b' to the serial device, it will return 'z' just fine. When I send 'a', it should return both 'f' and 'g', so two bytes instead of one.

我有一个简单的程序来测试串行功能。我的串行设备对两个输入做出反应。如果用户输入“a”,它会以“fg”响应。如果用户输入任何其他字符/字节,它会以“z”响应。如果我将“b”发送到串行设备,它会返回“z”就好了。当我发送 'a' 时,它应该同时返回 'f' 和 'g',所以是两个字节而不是一个字节。

See code below.

请参阅下面的代码。

#!/usr/bin/env python

import serial

ser = serial.Serial(
    port = '/dev/ttyUSB0',
    baudrate = 9600,
    parity = serial.PARITY_NONE,
    stopbits = serial.STOPBITS_ONE,
    bytesize = serial.EIGHTBITS
    )

ser.write('a')
byteData = ser.read(1) # read one, blocking
moreBytes = ser.inWaiting()

if moreBytes:
    byteData = byteData + ser.read(moreBytes)
    print byteData

print byteData


ser.close()

The output is :

输出是:

user@ubuntu:~/code/native$ ./serialTesting.py 
f

inWaiting() gives the value of 0, thus it never reads the second byte. If I do a small change to the code, and manually read the two expected bytes, it works fine.

inWaiting() 的值为 0,因此它永远不会读取第二个字节。如果我对代码做一个小的改动,并手动读取两个预期的字节,它就可以正常工作。

#!/usr/bin/env python

import serial

ser = serial.Serial(
    port = '/dev/ttyUSB0',
    baudrate = 9600,
    parity = serial.PARITY_NONE,
    stopbits = serial.STOPBITS_ONE,
    bytesize = serial.EIGHTBITS
    )

ser.write('a')
byteData = ser.read(2) # read two expected bytes for the result 'fg'

print byteData

ser.close()

The output is as expected:

输出如预期:

user@ubuntu:~/code/native$ ./serialTesting.py 
fg

回答by jramirez

it could be because the baudrate is really slow. You are processing the inwaiting() call before the second byte gets to the buffer. When you do ser.read(2) it waits(blocks) until 2 bytes have been received thus why it works. Try setting a timeout of 1 second, that should fix your problem.

这可能是因为波特率真的很慢。在第二个字节到达缓冲区之前,您正在处理 inwaiting() 调用。当您执行 ser.read(2) 时,它会等待(阻塞)直到接收到 2 个字节,因此它会起作用。尝试将超时设置为 1 秒,这应该可以解决您的问题。

ser = serial.Serial(
    port = '/dev/ttyUSB0',
    baudrate = 9600,
    parity = serial.PARITY_NONE,
    stopbits = serial.STOPBITS_ONE,
    bytesize = serial.EIGHTBITS,
    timeout=1 # add this
    )
ser.write('a')
byteData = ser.read(1) # read one, blocking
byteData += ser.read(ser.inWaiting())

print byteData

ser.close()

回答by iFreilicht

There are two decent solutions for this. For either, you'll need to set a timeout like jramirez already suggested:

对此有两个不错的解决方案。对于任何一种情况,您都需要像 jramirez 已经建议的那样设置超时:

ser = serial.Serial(
    port = '/dev/ttyUSB0',
    baudrate = 9600,
    parity = serial.PARITY_NONE,
    stopbits = serial.STOPBITS_ONE,
    bytesize = serial.EIGHTBITS,
    timeout=0.5, # IMPORTANT, can be lower or higher
    inter_byte_timeout=0.1 # Alternative
    )

Solution 1: Simple and effective

解决方案1:简单有效

byteData = ser.read(size=800) #Set size to something high

This will read up to 800 bytes and will take no more time than the timeoutyou've set. If you've instead set an inter_byte_timeout, read()will wait up to that amount of time for each singlebyte.

这将读取多达 800 个字节,并且不会比timeout您设置的时间多。如果您改为设置inter_byte_timeout,read()将为每个单个字节等待该时间。

This is a quick solution that will work for cases where you only receive a chunk of data of known maximum size.

这是一个快速解决方案,适用于您只接收已知最大大小的数据块的情况。

Solution 2: The proper way

解决方案2:正确的方法

def read_all(port, chunk_size=200):
    """Read all characters on the serial port and return them."""
    if not port.timeout:
        raise TypeError('Port needs to have a timeout set!')

    read_buffer = b''

    while True:
        # Read in chunks. Each chunk will wait as long as specified by
        # timeout. Increase chunk_size to fail quicker
        byte_chunk = port.read(size=chunk_size)
        read_buffer += byte_chunk
        if not len(byte_chunk) == chunk_size:
            break

    return read_buffer

The code snippet above is licensed under CC0 1.0.

上面的代码片段在CC0 1.0下获得许可。

And then, to read:

然后,阅读:

byteData = read_all(ser)

Basically, this will read your data in chunks and wait every time to see if new characters appeared. If less characters were read in the time set by timeout, the transmission is considered finished.

基本上,这将分块读取您的数据并等待每次查看是否出现新字符。如果在 设置的时间内读取的字符较少timeout,则认为传输已完成。

This solution will always work, even when you receive a lot of data or if you receive it very slowly.

此解决方案将始终有效,即使您收到大量数据或接收速度很慢。