1

I have spent a while trying to interpret the solutions found here pySerial 2.6: specify end-of-line in readline() and here Line buffered serial input, but for the life of me I cannot seem to "quickly" communicate with one of my pressure monitors that replies with responses terminated with a carriage return character ('\r')

I am able to reliably communicate with the device but it is always limited by the timeout parameter when I define the serial port. I can see that the device is in fact responding with a \r character as displayed using the traditional method. When using the io.TextIOWrapper I get the desired functionality of clipping the termination character, but it still timeouts as the original method.

My python code is as follows:

import serial,io,timeit

cmd = b'#0002UAUX1\r'
ser = serial.Serial(port='COM4',baudrate=9600,timeout=1)

def readline1(ser):
    return(ser.readline())

def readline2(ser):
    sio = io.TextIOWrapper(io.BufferedRWPair(ser,ser,1),newline='\r')
    return(sio.readline().encode())

def readline3(ser):
    out = b''
    while True:
        ch = ser.read()
        out += ch
        if(ch == b'\r' or ch == b''):
            break
    return(out)

def timer(func):
    tic = timeit.default_timer()
    ser.write(cmd)
    print(func())
    toc = timeit.default_timer()
    print('%0.2f seconds' % (toc-tic))

for func in (readline1,readline3,readline2):
    timer(lambda : func(ser))

my shell response is:

b'>3.066E-02\r'
1.03 seconds
b'>3.066E-02\r'
0.02 seconds
b'>3.066E-02\r'
1.06 seconds

All methods return the same output, but the readline3 operates much quicker as it does not timeout. I don't understand why it isn't as easy as

ser.readline(eol='\r') 

P.S. I'm quite new to python (heavily dependent on MATLAB) so any and all criticism is appreciated.

  • Don't you think it would be easier to read if you executed functions in alphabetical order, i.e. `for func in (readline1,readline2,readline3):` ? – Jakub Kukul Oct 27 '18 at 11:34
  • Well I wanted to do that, but for whatever reason those functions don't actually execute properly unless in that order. I could have re-named them, but that's besides the point. It turns out that all I needed was __ser.read_until(b'\r')__ which was basically readline3 anyways. – Alexander Laut Oct 28 '18 at 16:23

2 Answers2

1

In Python3.x the prefix b'' in a string indicated that it is being displayed as an instance of bytes types, this means that it will ignore displaying things such as escape sequences for their purpose, '\n' will be displayed to terminal in place of a new line.

If you use the command print('Hello\r\nWorld') it will display Hello World , not 'Hello\r\nWorld', however print(b'Hello\r\nWorld') or print(repr('Hello\r\nWorld')) will display 'Hello\r\nWorld'.

To see if this is the case in rwSerial1 replace print(out) with print(repr(out)) and it should display the string with all the characters.

  • This doesn't seem to address my issue regarding the speed, just the display. I've adjusted my code including a solution I found that runs extremely fast, I just wish it were cleaner and could use feedback. My three methods now return the same outputs. – Alexander Laut Mar 07 '18 at 13:45
-1

it turns out that the answer is:

ser.read_until(b'\r')
Jakub Kukul
  • 12,032
  • 3
  • 54
  • 53