Search code examples
pythonpython-3.xpyserialcarriage-returneol

Python serial (pySerial) Reading lines with EOL \r instead of \n


I am communicating with an SR830 lock-in amplifier via an RS232 cable. When reading the data as in the following code:

import serial

def main():
    ser = serial.Serial(
        port='COM6',
        baudrate=19200,
        parity=serial.PARITY_NONE,
        stopbits=serial.STOPBITS_ONE,
        bytesize=serial.EIGHTBITS)
    ser.timeout=1
    ser.write("OUTP? 1 \r\n".encode()) #Asks the Lock-in for x-value
    ser.write("++read\r\n".encode())
    x=ser.readline()
    print (x)
if __name__ == '__main__': main()

I get a byte string like b'-3.7486e-008\r'. However the ser.readline() function does not recognise the \r as an EOL. So I have to wait for the timeout every time I read data, which will be troublesome as I want to take a lot of points as fast as I can. And the length of the number changes a lot so I cannot just use ser.read(12) for example. I have tried using io.TextIOWrapper but it's not clear to me how to implement it. Here's my attempt:

import serial
import io
def main():
    ser = serial.Serial(
        port='COM6',
        baudrate=19200,
        parity=serial.PARITY_NONE,
        stopbits=serial.STOPBITS_ONE,
        bytesize=serial.EIGHTBITS)
    ser.timeout=1
    sio = io.TextIOWrapper(io.BufferedRWPair(ser, ser))
    sio.write("OUTP? 1 \r\n") #Asks the Lock-in for x-value
    sio.write("++read\r\n")
    x=sio.readline()
    print (x)
if __name__ == '__main__': main()

Which just prints a blank space. Any help will be much appreciated, thanks.

EDIT: Here's my working code after the answers, using the loop:

import serial
def main():
    ser = serial.Serial(
        port='COM6',
        baudrate=19200,
        parity=serial.PARITY_NONE,
        stopbits=serial.STOPBITS_ONE,
        bytesize=serial.EIGHTBITS)
    ser.timeout=5
    ser.write("OUTP? 1 \r\n".encode()) #Asks the Lock-in for x-value
    ser.write("++read\r\n".encode())
    buffer = ""
    while True:
        oneByte = ser.read(1)
        if oneByte == b"\r":    #method should returns bytes
            print (buffer)
            break
        else:
            buffer += oneByte.decode()
if __name__ == '__main__': main()

Solution

  • What about use simple loop for reading?

    def readData():
        buffer = ""
        while True:
            oneByte = ser.read(1)
            if oneByte == b"\r":    #method should returns bytes
                return buffer
            else:
                buffer += oneByte.decode("ascii")
    

    You can check the serialutil.py file from Pyserial package, They use the same way to achieve method read_until.