pySerial inWaiting 返回错误的字节数 [英] pySerial inWaiting returns incorrect number of bytes

查看:373
本文介绍了pySerial inWaiting 返回错误的字节数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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.

见下面的代码.

#!/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()

输出是:

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

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

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.

#!/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()

输出符合预期:

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

推荐答案

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

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

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
    )

解决方案 1:简单有效

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

这将最多读取 800 个字节,并且不会比您设置的 timeout 花费更多时间.如果您改为设置 inter_byte_timeoutread() 将等待每个单个字节的时间.

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

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

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

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

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

The code snippet above is licensed under CC0 1.0.

然后,阅读:

byteData = read_all(ser)

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

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.

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

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

这篇关于pySerial inWaiting 返回错误的字节数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆