SerialPort data loss - C #

I am working on a SerialPort application and one very simple part of it is giving me problems. I just want to read a constant stream of data from a port and write it to a binary file as it appears. The problem seems to be related to speed: my code worked fine on my 9600 bit test device, but when it pushes to 115200 bits in real time, I seem to lose data. What happens is happening over a variable period of time, I am missing 1 byte which discards the rest of the data. I've tried several things:

private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
    bwLogger.Write((byte)serialPort1.ReadByte());
}

      

or

private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
    byte[] inc = new byte[serialPort1.BytesToRead];
    serialPort1.Read(inc, 0, inc.Length);

    bwLogger.Write(inc);
}

      

and several options. I cannot use ReadLine () as I am working with a constant stream of data (right?). I was trying to mess around with the buffer size (both serialPort1.ReadBufferSize and hardware FIFO). Ideally, for ease of use, I would handle this from the software side rather than forcing the user to change the Windows driver settings.

Any ideas?

+2


source to share


6 answers


You can try to enable handshake using the Handshake property of the SerialPort object.



You will need to set it for both the sender and the recipient. however: if you are overflowing the receiver UART buffer (very small, 16 bytes IIRC) then there is probably no other way. If you are unable to enable sender acknowledgment, you may have to stop at 9600 or below.

+4


source


If the problem is that you cannot process the data fast enough, then you could try to double the buffer of your data.

1) Allow one thread to read the serial port into one buffer. It might have to do with copying data from port to buffer (I'm not familiar with .NET).



2) When you are ready to process the incoming data (on a different thread), your program will read into the second buffer, and while this is happening, you should write the first buffer to disk.

3) When the first buffer is written to disk, replace it back with the serial port buffer and write the second buffer to disk. Repeat the process, continually replacing the buffers.

+5


source


I would try the following:

  • Set the buffer size to at least 230KB
  • Set the incoming threshold to 16K, 32K, or 65K
  • Write these fixed blocks of data to a file

I'm not sure if this can help, but it should at least undermine the framework to trigger this event frequently.

+2


source


  • I would check the number of bytes read returned by the Read method (Byte> [], Int32, Int32) and make sure it is as expected.

  • Make sure you are listening for SerialErrorReceivedEventHandler ErrorReceived events on the port object. An RXOver error indicates that your buffer is full.

  • Check thread safety on the output buffer. If the write to the output buffer is not thread-safe, the second write may corrupt the first.

+1


source


Is your bwLogger a BinaryWriter class? You can try using it with BufferedStream to make disk I / O non-blocking.

Also, if your packages have a well-known termination character, you can set the SerialPort.NewLine property so you can use ReadLine / WriteLine, although I don't think that would have a big performance impact.

+1


source


The machines I have worked with recently are sending a stop code (in my case ASCII code 3 or 4). If you also have this function, you can use ReadTo(string)

the SerialPort object.

0


source







All Articles