4

I am using pySerial to read TTL byte stream. To read two bytes:

CheckSumByte = [ b for b in ser.read(2)]
print( CheckSumByte)
print( type(CheckSumByte))
print( str(len(CheckSumByte)))
print( CheckSumByte[0])

Output:

[202, 87]
<class 'list'>
2
IndexError: list index out of range

I cannot access any elements of CheckSumByte by index (0 or 1). What is wrong?

Here is my code:

while(ReadBufferCount < 1000):
    time.sleep(0.00002)
    InputBuffer = ser.inWaiting()
    if (InputBuffer > 0):
        FirstByte = ser.read(1)
        if ord(FirstByte) == 0xFA:
            while ser.inWaiting() < 21: pass
        IndexByte = ser.read(1)
        SpeedByte = [ b for b in ser.read(2)]
        DataByte0 = [ b for b in ser.read(4)]
        DataByte1 = [ b for b in ser.read(4)]
        DataByte2 = [ b for b in ser.read(4)]
        DataByte3 = [ b for b in ser.read(4)]
        CheckSumByte = [ b for b in ser.read(2)]
        print( CheckSumByte[0]) #Out of Range??`
Traceback (most recent call last):

  File "<ipython-input-6-5233b0a578b1>", line 1, in <module>
    runfile('C:/Users/Blair/Documents/Python/Neato XV-11 Lidar/Serial9.py', wdir='C:/Users/Blair/Documents/Python/Neato XV-11 Lidar')

  File "C:\Program Files (x86)\WinPython-32bit-3.4.3.3\python-3.4.3\lib\site-packages\spyderlib\widgets\externalshell\sitecustomize.py", line 682, in runfile
    execfile(filename, namespace)

  File "C:\Program Files (x86)\WinPython-32bit-3.4.3.3\python-3.4.3\lib\site-packages\spyderlib\widgets\externalshell\sitecustomize.py", line 85, in execfile
    exec(compile(open(filename, 'rb').read(), filename, 'exec'), namespace)

  File "C:/Users/Blair/Documents/Python/Neato XV-11 Lidar/Serial9.py", line 88, in <module>
    print( CheckSumByte[0]) #Out of Range??

IndexError: list index out of range

Kenny: Thanks. Even simpler for the two bytes:

    CheckSumByte.append(ser.read(1))
    CheckSumByte.append(ser.read(1))

Works properly, but awkward. The items are type bytes. How to add items to the list using list comprehension? I would like to avoid the append function because it is slow.

I notice it does not work when the items of CheckSumByte are integer. Does Python 3 list comprehension require special format to add the bytes as byte (not convert to integer)?

9
  • Could you show the full traceback? Commented Mar 26, 2017 at 4:14
  • 2
    What happens if you loop thru ser.read(2) and print the results - for b in ser.read(2): print(b, type(b)) Commented Mar 26, 2017 at 4:45
  • user1245262 - I like your idea. I cannot get the right syntax: CheckSumByte = [ b for b in ser.read(2): print(b, type(b))] Commented Mar 26, 2017 at 20:48
  • Is your instance of Serial in non-blocking mode? Commented Mar 27, 2017 at 0:41
  • 1
    Blair, for user1245262's comment, use the for loop instead of a list comprehension. You can initialize CheckSumByte = [] and append b to it inside the for loop. The for loop may be clunky in comparison but it gives you an easy place to look at intermediate stuff. Commented Mar 27, 2017 at 2:20

1 Answer 1

2

According to your most recent comment you have constructed ser as:

ser = serial.Serial(
    port=PortName, baudrate=115200, parity=serial.PARITY_NONE,
    stopbits=serial.STOPBITS_ONE, bytesize=serial.EIGHTBITS, 
    timeout=0)

According to the documentation this means that ser is non-blocking (despite your assertion it is blocking!).

As it is in non-blocking mode there is absolutely no reason to expect ser.read(n) to return exactly n bytes. Instead, if you wish to read n bytes you should either:

  • construct ser as blocking (use timeout=None) in the constructor; or
  • loop while monitoring the number of bytes actually read (just as you would when reading a network socket)

The latter for example means that if you wish to read n bytes you will need to do something like:

def read_exactly(ser, n):
    bytes = b""

    while len(bytes) < n:
        bytes += ser.read(n - len(bytes))

    return bytes

In your particular case, you seem to be monitoring the the input buffer to ensure there is adequate data for the following reads. But this monitoring is only occurring some of the time, not all of the time. Thus when FirstByte != 0xFA you could exhaust the read buffer unless you take one of the approachs given above.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.