pySerial inWaiting returns incorrect number of bytes

后端 未结 2 1986
陌清茗
陌清茗 2020-12-19 18:34

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 anythin

相关标签:
2条回答
  • 2020-12-19 19:01

    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.

    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()
    
    0 讨论(0)
  • 2020-12-19 19:02

    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
        )
    

    Solution 1: Simple and effective

    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 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.

    Solution 2: The proper way

    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.

    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.

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

    0 讨论(0)
提交回复
热议问题