3

I have a data acquisition system that produces ASCII data. The data is acquired over USB with serial communication protocol (virtual serial, as the manufacturer of the box claims). I have a Python program/script that uses PySerial with a PySide GUI that plots the acquired data and saves it to HDF5 files. I'm having a very weird problem and I don't know how to tackle it. I wish you guys could help me and provide advice on how you would debug this problem.

How the problem shows up: The problem is that if I use a software like Eltima Data Logger, the data acquired looks fine. However, if I use my software (with PySerial), some chunks of the data seems to be missing. What's weird is that the missing chunk of the data is incompatible with the method of reading. I read line by line, and what is missing from the data is like 100 bytes or 64 bytes chunks that sometimes include newlines!!! I know what's missing because the device buffers the data on an SD Card before sending it to the computer. This made me believe for a long time that the hardware has a problem, until I used this software, Eltima, that showed that it's acquiring the data fine.

The following is the configuration of Eltima:

enter image description here

My configuration:

This whole thing is running in a QThread.

The following is the methods I use in my code (with some minor polishing to make it reusable here):

self.obj = serial.Serial()
self.obj.port = instrumentName
self.obj.baudrate = 115200
self.obj.bytesize = serial.EIGHTBITS
self.obj.parity = serial.PARITY_ODD
self.obj.stopbits = serial.STOPBITS_ONE 
self.obj.timeout = 1
self.obj.xonxoff = False
self.obj.rtscts = False
self.obj.dsrdtr = False
self.obj.writeTimeout = 2
self.obj.open()

The algorithm I use for reading, is that I have a loop that looks for a specific header line, and once found, it keeps pushing lines into buffer until a specific end line is found; and this data is finally processed. Following is my code:

try:
    # keep reading until a header line is found that indicates the beginning of a batch of data
    while not self.stopped:
        self.line = self.readLine()
        self.writeDumpFileLine(self.line)
        if self.line == DataBatch.d_startString:
            print("Acquiring batch, line by line...")
            self.dataStrQueue.append(self.line)
            break
    # after the header line, keep reading until a specific string is found
    while not self.stopped:

        self.line = self.readLine()
        self.writeDumpFileLine(self.line)
        self.dataStrQueue.append(self.line)
        if self.line == DataBatch.d_endString:
            break
except Exception as e1:
    print("Exception while trying to read. Error: " + str(e1))

The self.writeDumpFileLine() takes the line from the device and dumps it in a file directly before processing for debugging purposes. These dump files have confirmed the problem of missing chunks.

The implementation of self.readLine() is quite simple:

def readLine(self):
    lineData = decodeString(self.obj.readline())
    lineData = lineData.replace(acquisitionEndlineChar, "")
    return lineData

I would like to point out that I also have an implementation that pulls thousands of lines and parses them based on inWaiting(), and this method has the same problem too!

Now I'm starting to wonder: Is it PySerial? What else could be causing this problem?

Thank you so much for any efforts. If you require any additional information, please ask!


UPDATE:

Actually I have just confirmed that the problem can be reproduced by getting the system to lag a little bit. I use PyCharm to program this software, and while the program is running, if I press Ctrl+S to save, the GUI of PyCharm freezes a little bit (and hence its terminal). Repeating this many times causes the problem in a reproducible manner!!!!

The Quantum Physicist
  • 24,987
  • 19
  • 103
  • 189
  • Could it be any of the other methods in the reading loop that take a long time to execute, and therefore result in a buffer overflow, lost data, from the serial port? – J. P. Petersen Apr 12 '16 at 12:03
  • @J.P.Petersen The device can buffer data for hours actually on an SD card. Does that exclude what you meant? – The Quantum Physicist Apr 12 '16 at 12:04
  • 1
    I was thinking about the buffer in the OS on the computer that reads the serial signal. It has a limited size - think it is in the order of few kilobytes mostly. If you don't read from it fast enough, it might get full, and data is lost. – J. P. Petersen Apr 12 '16 at 14:02
  • @J.P.Petersen Could you please suggest a way to test whether this is the case and how to avoid this possible problem? – The Quantum Physicist Apr 12 '16 at 14:03
  • I would measure the time around the `serial.readline()`. Time A just before it calls `readline()` and B just after. The time it takes to get back to A should be short, in the order of 10-100 ms. At 115200 you can roughly receive 10 kbytes a second. Note it is not the time between A and B, but the time between B and the next A that must be short :) – J. P. Petersen Apr 12 '16 at 14:29
  • @J.P.Petersen WoW!! Actually I have just confirmed that the problem can be reproduced by getting the system to lag a little bit. I use PyCharm to program this software, and while the program is running, if I press `Ctrl+S` to save, the GUI of PyCharm freezes a little bit (and hence its terminal). Repeating this many times causes the problem in a reproducible manner!!!! What do you think? – The Quantum Physicist Apr 12 '16 at 14:44
  • 1
    sounds like it could be a buffer problem. – J. P. Petersen Apr 13 '16 at 07:29
  • @J.P.Petersen How can I resolve such an issue? – The Quantum Physicist Apr 13 '16 at 10:05
  • *"How can I resolve such an issue?"* -- That's what *flow control* is for. Flow control, both HW (aka RTS/CTS) and SW (aka XON/XOFF), is disabled for your serial channel. – sawdust Apr 14 '16 at 20:11
  • @sawdust Thanks for the answer. How can I know which of these to enable? Honestly I enabled them all just for testing and that didn't change anything. What does that tell us? – The Quantum Physicist Apr 14 '16 at 23:04
  • Flow control will only work if supported on both ends of the serial link. When your side says "my buffer is full, stop sending me data", the device on the far end has to respond by actually stop sending data. You cannot configure just one side; both sides have to be configured identically. Just enable one style, either HW or SW. But you have to use HW flow control if the data is not pure text.. – sawdust Apr 14 '16 at 23:12
  • @sawdust So are you saying that it didn't work because possibly the device isn't configured to use flow control, or because I enabled them all together? I can try them one by one tomorrow in the office. Thanks! – The Quantum Physicist Apr 14 '16 at 23:15
  • @sawdust The data is btw ASCII data, so it's text. Why does it matter whether it's text or not for HW flow control? – The Quantum Physicist Apr 14 '16 at 23:21
  • XON/XOFF control characters (for SW flow control) cannot be distinguished reliably when receiving binary (non-ASCII text) data. So SW flow control should not be used with binary data, but only text data. HW flow control can be used with either text or binary data. – sawdust Apr 14 '16 at 23:27
  • @sawdust I am using ASCII, meaning that SW control should solve my problem! I'll try that and give feedback. Thanks! – The Quantum Physicist Apr 14 '16 at 23:33
  • @sawdust Enabling SW flow control didn't solve the problem :-( – The Quantum Physicist Apr 15 '16 at 15:31
  • Try HW flow control. – sawdust Apr 16 '16 at 01:32
  • @sawdust That was the first thing I tried actually. That doesn't work too. :-( – The Quantum Physicist Apr 16 '16 at 08:43

0 Answers0