-1

I program an App in VB.Net and I want to read received data from a serial port in maximum baudrate. I used SerialPort component in my form and its properties are as follows:

(BuadRate=115200 , DataBits=8 , Parity=None , StopBits=One)

When I use connPort.ReadLine in DataReceived event, data congestion caused in buffer and I can't read all received data in realtime, because event fires are slower than received data.

On the other side when I use connPort.ReadExisting, I can read all received data in realtime without data congestion in buffer, but the received data is look like this:

First received:
-12917
-12958
-13004

Second received:
-13055
-13118
-13181
-1324

Third received:
6
-13320
-13391
-13463

So I need to parser the received data line by line and on the other side I need to detect some received data errors look like:

...
-1324

Third received:
6
...

The correct data is: -13246

My code:

Private Sub connPort_DataReceived _
    (ByVal sender As System.Object, _
     ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) _
                                 Handles connPort.DataReceived
    Dim rcData as String
    rcData = connPort.ReadLine
    dt_Write(rcData)

    'rcData = connPort.ReadExisting
    'dt_Write(rcData)
End Sub

' Save received data in a created DataTable
Public dt As New DataTable
Private Sub dt_Write(ByVal rcData As String)
    dt.Rows.Add(New Object() {Nothing, rcData})
End Sub

I tried Timer component and Tick event With one millisecond Interval property (One millisecond is not real resolution) to receive data, but the fires are slower too and there are mentioned problems too.

I am looking for a right way and I'm trying to avoid redundant operations. Thank you

Community
  • 1
  • 1
farzad89
  • 19
  • 6
  • Can we see some code? `ReadLine()` should work. Did you set `connPort.Newline`? – Jim Hewitt Jul 14 '16 at 18:08
  • Thanks for your comment Jim. I add my code in the question. When I use `connPort.ReadLine()`, I have some problems. At first I didn't define NewLine property but the rest I defined as `connPort.NewLine=Chr(13).ToString` in the Initialize, but it dosen't solve my problems and actually I could not find any difference. – farzad89 Jul 14 '16 at 19:18
  • What happens if you use `connPort.Read()` instead of `connPort.ReadLine()`? – djv Jul 14 '16 at 19:18
  • @farzad89 Try `vbCr` for `Newline`. – Jim Hewitt Jul 14 '16 at 19:19
  • If you do `connPort.Read()`, then you should be able to identify the `NewLine` character(s). Any reasonable person would have set it to either `Chr(13)` (vbCr) or `Chr(10)` (vbLf). Those are your two best bets. – djv Jul 14 '16 at 19:51
  • If I use `connPort.Read()` method until NewLine character in the _DataReceived event, It work like `connPort.ReadLine` at every time the data is received. So data congestion caused in buffer and I can't read all received data in realtime. – farzad89 Jul 14 '16 at 20:18
  • Perhaps you should offload adding rows to your datatable to a background thread as that must be taking a lot of time for some reason if you can't `ReadLine` without the port buffer overflowing. If you were writing data to a textbox (properly since `DataReceived` event is not in the UI thread), it should fly by so fast you couldn't read it. – topshot Jul 14 '16 at 21:12
  • Maybe the line is too long and the buffer is overflowing. Use the comment on this question as a guide http://stackoverflow.com/questions/32021784/how-do-i-continuously-read-and-parse-high-speed-serialport-data?rq=1 – djv Jul 14 '16 at 21:32
  • Thanks for comments. As you see received data in every event fire is a string with 3 or 4 lines. Is it possible to limit this to receive one line in every fire ? or is it possible to use an another event with high speed fire ? – farzad89 Jul 14 '16 at 22:28
  • @topshot , Exactly, time is very important, and I tried to use high resolution timer to read data with a little fast, but until now I could not to get a result. – farzad89 Jul 14 '16 at 22:29
  • Depending on how long you need to capture, perhaps you should use a different collection that has better add performance than a datatable. I'm not sure which is the fastest but I'd have to think that pre-allocating an array of 100000 elements, for example, and then assigning each element would be quicker than adding 100000 rows to a datatable. You could move it to a datatable when you're done if needed. But you might also be better off rolling your own serial port class (see http://www.sparxeng.com/blog/software/must-use-net-system-io-ports-serialport) – topshot Jul 15 '16 at 02:31

1 Answers1

0

My friends thanks for your comments. I had a problem with realtime data reading in using of SerialPort component in Vb.Net and finally I found a Solution And I wanted to share with you.

As you know the DataReceived event is not guaranteed to be raised for every byte received and we have to use the BytesToRead property to determine how much data is left to be read in the buffer. https://msdn.microsoft.com/en-us/library/system.io.ports.serialport.datareceived(v=vs.110).aspx

I tested a new way, the While...End While structure almost iterate one thousand times in 100 milliseconds. So it is fired very faster than any event so I have used this structure in the DataReceived event until the BytesToRead is greater than zero. With this strategy I was able to read the received data in realtime.

My code is:

Private Sub connPort_DataReceived _
(ByVal sender As System.Object, _
 ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) _
                             Handles connPort.DataReceived
    Dim rcData as String

    While connPort.BytesToRead > 0
        rcData = connPort.ReadLine
        dt_Write(rcData)
    End While

End Sub

' Save received data in a created DataTable
Public dt As New DataTable
Private Sub dt_Write(ByVal rcData As String)
    dt.Rows.Add(New Object() {Nothing, rcData})
End Sub
farzad89
  • 19
  • 6