Results 1 to 5 of 5

Thread: [RESOLVED] COM port and threading

  1. #1

    Thread Starter
    New Member
    Join Date
    Aug 2017
    Posts
    10

    Resolved [RESOLVED] COM port and threading

    Hallo everyone.
    I'm a beginner at VB.NET but I got an task to resolve and I find it very interesting, therefore would like to learn more about this. I hope some of you guys can help me understand this.
    Here is the situation...
    (To make it simple, I'll get directly to my problem, and that is serialport communication.)

    I have a program that reads UID from RFID Tags and if neccesary programs them (about 10 Tags per second - if only read performed / 2 Tags per second - if programming needed)
    So you can assume that the main key here is fast and reliable communication.
    Main problem is that serial port DataReceived event handler is fired (in my oppinion) uncontroled and every time differently. Sometimes I get 3 bytes and right after that another 13, sometimes I get 8 bytes and right after another 8 received and so on. ( I think that you all are familiar with this problem)



    1. What would you recommend me, to declare COM port in another class or to keep it in the main Form class? I wanted to separate Main Class and SerialPort Class because of threading and invoking. i noticed that if DataReceived is in Main class, and I try to invoke something else from it, the Main class frezzes for a few ms. Or did I get it wrong. The main thing is, I want to have full control of everything what is happening at any time. As I said, when I need only to read UID from the Tags, there is about 10 Tags per second going through the reader. I can not afford that the SerialPort Data Received Event handler sends me partial UID (3 or 4 or 5 bytes and after that the rest)...

    2. If I declare serialport in another class, how can I open that port from Main Class?`(I don't quite understand this Private Public Shared Protected.. Classes) All I know is that I am not able to declare serial port in shared class, but if I declare it in another type of class, I can not access it from Main class...

    3. What's the best way to communicate with serialport? I need to send string to it ( I do it by sending an Byte Array ) and also to read bytes from it ( I read Byte by Byte ). But as I already mentioned, I need to receive the whole UID or the whole response from the tag. The good thing is that I know exactly at any moment how many bytes I'm expecting to receive (Maybe we can use that somehow - but not using Threshold )

    I'll gladly provide my code here if you need it, but I wanted to build it again from Ground Zero, and to build it clean and correct.
    Any advice is appreciated. If you have any links or tutorials about SerialPorts or asynchronous threads or something like that you can write it down in comments.
    Thanks a lot in advance..

  2. #2
    Frenzied Member
    Join Date
    Dec 2014
    Location
    VB6 dinosaur land
    Posts
    1,190

    Re: COM port and threading

    This should get you started. Or his other answer (NOTE: there is good stuff further down from that particular post as well!)

  3. #3
    You don't want to know.
    Join Date
    Aug 2010
    Posts
    4,578

    Re: COM port and threading

    That's some pretty good code in those links.

    The main thing to think about going in is "not getting all the data in one go is just how the COM port works". Or, more specifically, "this is how streaming I/O has always worked". It's not the "easiest" way to approach things, but here's why:

    There's no "one true COM port protocol". Every program is free to send data a little differently than the others. Even when some standards are used, it's up to the program what constitutes "data". So since every program is free to do things differently, there's no one "done" message for the SerialPort class to listen for. That means it has to leave it up to you.

    The API used by the SerialPort class is very similar to the API used by network APIs and file APIs for decades. It wants you to write "read" code like this:
    Code:
    Dim buffer(<big number>) As Byte
    Dim bytesRead As Integer = 0
    Dim bytesRemaining = ???
    
    While Not bytesRemaining = 0
        bytesRead += Read(buffer, bytesRead, bytesRemaining)
    
        bytesRemaining -= bytesRead
    End While
    
    <do stuff>
    This gets a little more complex when threads are involved, but not so much. Most of the time you just restructure your code like this:
    Code:
    Private _buffer(<big number>) As Byte
    Private _bytesRead As Integer = 0
    Private _bytesRemaining As Integer
    
    Sub Start()
        _bytesRemaining = ???
        _bytesRead = 0
        StarComPort()
    End Sub
    
    Sub WhenDataArrives(...)
        bytesRead += _comPort.Read(buffer, _bytesRead, _bytesRemaining)
    
        _bytesRemaining -= bytesRead
    
        If _bytesRemaining = 0
            WhenFinished()
        End If
    End Sub
    
    Sub WhenFinished()
        <do stuff>
    End Sub
    How do you know how to set up _bytesRemaining? It depends on your protocol. Some protocols send packets in fixed sizes. It sounds like you just want 8 bytes at a time, so that's probably you. Other protocols don't have a fixed size, but instead use terminators, or send a length along with each packet. Those involve reading some data, then interpreting what you have and are a bit more complicated to muck with.

    I think dbasnett's code is good at introducing the concept, but I'm not sure it's the easiest to follow. Here's a 'lite' version, running with the idea that you want 8 bytes at a time.

    First, let's make a "protocol" type to help us interpret odd amounts of bytes. It needs to take an array of bytes and give us back any groups of 8 that we received. If we have non-multiples of 8 like 3 or 11, it needs to hold on to those bytes until it gets more data. This is fidgety, and there's some concepts like circular buffers that can help immensely, but let's stick to the "simplest" idea and use arrays. This is going to be particularly difficult due to your choice of VB 2008, there are a lot of nice features you are missing I might end up accidentally using. Luckily, I'm pretty sure that version has LINQ and that's the biggest feature we need:
    Code:
    Public Class Protocol
    
        Private _leftovers(-1) As Byte
    
        Public Function InterpretBytes(ByVal input() As Byte) As List(Of Byte())
            Dim output As New List(Of Byte())()
    
            Dim fullByteStream As IEnumerable(Of Byte) = _leftovers.Concat(input)
            Dim offset As Integer = 0
            Dim finished As Boolean = False
            Do
                ' Takes up to 8 bytes out of the full stream, skipping the elements we've already seen.
                Dim chunk() As Byte = fullByteStream.Skip(offset).Take(8).ToArray()
                If chunk.Length = 8 Then
                    ' If it got all 8 bytes, store them
                    output.Add(chunk)
                Else
                    ' If it got less than 8 bytes, store this chunk as the "leftovers"
                    _leftovers = chunk
                End If
    
                offset += 8
    
                finished = chunk.Length <> 8
            Loop Until finished
    
            Return output
        End Function
    End Class
    When you have that, your DataReceived handler can be greatly simplified:
    Code:
    Private _protocol As New Protocol()
    
    Private Sub SerialPort_DataReceived(...) Handles ...
        Dim buffer(_yourPort.BytesToRead - 1) As Byte
        _yourPort.Read(buffer, 0, buffer.Length)
        Dim results As List(Of Byte()) = _protocol.InterpretBytes(buffer)
    
        For Each result In results
            DoSomethingWith(result)
        Next
    End Sub
    Maybe that needs some thread synchronization, maybe not. The only way to find out sometimes is to test.
    This answer is wrong. You should be using TableAdapter and Dictionaries instead.

  4. #4

    Thread Starter
    New Member
    Join Date
    Aug 2017
    Posts
    10

    Re: COM port and threading

    Thanks @topshot, I've already read those threads, but as Sitten Spynne told, for a beginner as I am, they are bit difficult to follow.. I don't quite understand everything.

  5. #5

    Thread Starter
    New Member
    Join Date
    Aug 2017
    Posts
    10

    Re: COM port and threading

    Thank you very much @Sitten Spynne, great and simple Idea, I will definetly try to use this in my code..
    But as I allready mentioned, my problem is lack of "Threading" knowledge. How and more important when to start it, when to pause it, crossthreading, synchronization, reporting and so on...
    Last edited by Edoliny; Oct 9th, 2017 at 12:35 AM.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width