Results 1 to 6 of 6

Thread: [RESOLVED] Handle multiple COM ports using same AddressOf sub

  1. #1

    Thread Starter
    Lively Member
    Join Date
    Feb 2005
    Location
    Huddersfield, England
    Posts
    83

    Resolved [RESOLVED] Handle multiple COM ports using same AddressOf sub

    I've got my serial/com port code working ok using the standard Port.DataReceived handler:

    Code:
    AddHandler Port.DataReceived, AddressOf port_DataReceived
    I now want to be able to handle multiple COM ports. Do I have to create multiple copies of the handler sub or is there a way the handler sub can tell which COM port it was called for?
    Last edited by consciouspnm; Jan 25th, 2011 at 01:27 PM.

  2. #2
    Fanatic Member
    Join Date
    Sep 2009
    Location
    Lakewood, Colorado
    Posts
    621

    Re: Handle multiple COM ports

    Hi,

    I generally use WithEvent syntax, and if I need a shared DataReceived handler, I simply add to the Handles clause.

    However, you also can do it with AddHandler. Here is some "simple-minded" code. I have three serial ports on my computer that are active Com3 and Com7 are connected together using a null modem, so that the corresponding command button sends data to the other. Com13 is a GPS receiver, which sends data continuously.

    The SerialPort_Data_DataReceived delegate receives data from each instance and identifies which port generated that event. You then can add code to actually process the data received.

    Naturally, such a shared approach is appropriate only where the data format from each port is identical, and other serial port coding requirement still apply.

    Code:
    Public Class Form1
        Private SerialPort1 As New System.IO.Ports.SerialPort
        Private SerialPort2 As New System.IO.Ports.SerialPort
        Private SerialPort3 As New System.IO.Ports.SerialPort
        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            With SerialPort1
                .PortName = "Com3"
                .BaudRate = 4800
                .Open()
                AddHandler SerialPort1.DataReceived, AddressOf SerialportX_DataReceived
            End With
            With SerialPort2
                .PortName = "Com7"
                .BaudRate = 4800
                .Open()
                AddHandler SerialPort2.DataReceived, AddressOf SerialportX_DataReceived
            End With
            With SerialPort3
                .PortName = "Com13"
                .BaudRate = 4800
                .Open()
                AddHandler SerialPort3.DataReceived, AddressOf SerialportX_DataReceived
            End With
    
    
        End Sub
    
        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            SerialPort1.Write("SerialPort1" & vbCrLf)
        End Sub
    
        Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
            SerialPort2.Write("SerialPort2" & vbCrLf)
        End Sub
    
        Private Sub SerialportX_DataReceived(ByVal sender As System.Object, ByVal e As System.EventArgs)
            Dim SerialPort As System.IO.Ports.SerialPort = sender
            Debug.Print(SerialPort.PortName)
            Dim Buffer As String = SerialPort.ReadExisting
            Debug.Print(Buffer)
        End Sub
    End Class
    Naturally, you don't want to do what I've done and simply display receive data in the Immediate Window. You will want to do something more interesting.

    Dick
    Richard Grier, Consultant, Hard & Software
    Microsoft MVP (Visual Basic)

  3. #3

    Thread Starter
    Lively Member
    Join Date
    Feb 2005
    Location
    Huddersfield, England
    Posts
    83

    Resolved Re: Handle multiple COM ports using same AddressOf sub

    Code:
    Dim SerialPort As System.IO.Ports.SerialPort = sender
            Debug.Print(SerialPort.PortName)
    Thanks, that's the bit I was missing. Intellisense wasn't offering any suggestions for what sender could be used for!

  4. #4
    Fanatic Member
    Join Date
    Sep 2009
    Location
    Lakewood, Colorado
    Posts
    621

    Re: [RESOLVED] Handle multiple COM ports using same AddressOf sub

    Hi,

    sender is an Object, so Intellisense cannot be too detailed. You just have to "know, (or ask)."

    BTW, there is a more flexible approach, that may not be obvious, for creating an arbitrarily large number of serial ports that share the same DataReceived event handler. This involves a little more code, but the port creation can be done dynamically; just move the port creation code to a routine that is called, "as needed."

    Code:
    Dim SerialPortCollection As New Collection
        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            Dim SerialPort As System.IO.Ports.SerialPort
            SerialPort = New System.IO.Ports.SerialPort
            With SerialPort
                .PortName = "Com3"
                .BaudRate = 4800
                .Open()
                SerialPortCollection.Add(SerialPort, SerialPort.PortName)
                AddHandler SerialPort.DataReceived, AddressOf SerialportX_DataReceived
            End With
            SerialPort = New System.IO.Ports.SerialPort
            With SerialPort
                .PortName = "Com7"
                .BaudRate = 4800
                .Open()
                SerialPortCollection.Add(SerialPort, SerialPort.PortName)
                AddHandler SerialPort.DataReceived, AddressOf SerialportX_DataReceived
            End With
            SerialPort = New System.IO.Ports.SerialPort
            With SerialPort
                .PortName = "Com13"
                .BaudRate = 4800
                .Open()
                SerialPortCollection.Add(SerialPort, SerialPort.PortName)
                AddHandler SerialPort.DataReceived, AddressOf SerialportX_DataReceived
            End With
        End Sub
    
        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            Dim SerialPort As System.IO.Ports.SerialPort = SerialPortCollection("Com3")
            SerialPort.Write("SerialPort1" & vbCrLf)
        End Sub
    
        Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
            Dim SerialPort As System.IO.Ports.SerialPort = SerialPortCollection("Com7")
            SerialPort.Write("SerialPort2" & vbCrLf)
        End Sub
    
        Private Sub SerialportX_DataReceived(ByVal sender As System.Object, ByVal e As System.EventArgs)
            Dim SerialPort As System.IO.Ports.SerialPort = sender
            Debug.Print(SerialPort.PortName)
            Dim Buffer As String = SerialPort.ReadExisting
            Debug.Print(Buffer)
        End Sub
    Richard Grier, Consultant, Hard & Software
    Microsoft MVP (Visual Basic)

  5. #5
    New Member
    Join Date
    Mar 2016
    Posts
    1

    Re: [RESOLVED] Handle multiple COM ports using same AddressOf sub

    Quote Originally Posted by DickGrier View Post
    Hi,

    sender is an Object, so Intellisense cannot be too detailed. You just have to "know, (or ask)."

    BTW, there is a more flexible approach, that may not be obvious, for creating an arbitrarily large number of serial ports that share the same DataReceived event handler. This involves a little more code, but the port creation can be done dynamically; just move the port creation code to a routine that is called, "as needed."

    Code:
    Dim SerialPortCollection As New Collection
        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            Dim SerialPort As System.IO.Ports.SerialPort
            SerialPort = New System.IO.Ports.SerialPort
            With SerialPort
                .PortName = "Com3"
                .BaudRate = 4800
                .Open()
                SerialPortCollection.Add(SerialPort, SerialPort.PortName)
                AddHandler SerialPort.DataReceived, AddressOf SerialportX_DataReceived
            End With
            SerialPort = New System.IO.Ports.SerialPort
            With SerialPort
                .PortName = "Com7"
                .BaudRate = 4800
                .Open()
                SerialPortCollection.Add(SerialPort, SerialPort.PortName)
                AddHandler SerialPort.DataReceived, AddressOf SerialportX_DataReceived
            End With
            SerialPort = New System.IO.Ports.SerialPort
            With SerialPort
                .PortName = "Com13"
                .BaudRate = 4800
                .Open()
                SerialPortCollection.Add(SerialPort, SerialPort.PortName)
                AddHandler SerialPort.DataReceived, AddressOf SerialportX_DataReceived
            End With
        End Sub
    
        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            Dim SerialPort As System.IO.Ports.SerialPort = SerialPortCollection("Com3")
            SerialPort.Write("SerialPort1" & vbCrLf)
        End Sub
    
        Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
            Dim SerialPort As System.IO.Ports.SerialPort = SerialPortCollection("Com7")
            SerialPort.Write("SerialPort2" & vbCrLf)
        End Sub
    
        Private Sub SerialportX_DataReceived(ByVal sender As System.Object, ByVal e As System.EventArgs)
            Dim SerialPort As System.IO.Ports.SerialPort = sender
            Debug.Print(SerialPort.PortName)
            Dim Buffer As String = SerialPort.ReadExisting
            Debug.Print(Buffer)
        End Sub


    Hi
    I Know this went out some time ago however I would like to use the method for a job I have. My problem is cross threading. In the final section of code where we are required to replace the debug with real output the debugger is not happy with me addressing textboxes from this location. It call a cross threading error, how can i get past this.
    Regards
    clive

  6. #6
    Addicted Member
    Join Date
    Nov 2011
    Posts
    223

    Re: [RESOLVED] Handle multiple COM ports using same AddressOf sub

    Hi, the DataReceived event handler runs on its own thread which is separate from the main UI thread.
    To pass information from the DataReceived handler to a control on the UI without throwing a crossthread exception you will need to use a delegate.
    You begin by declaring the delegate and creating the sub routine which represents the delegate, in this case writing text to a RichTextbox on the main UI.

    Code:
    Public Delegate Sub myDelegate(ByVal sData As String)
    
        Private Sub Text_Out(ByVal sData As String)
            RichTextBox1.AppendText(sData & " ")
        End Sub
    The above delegate accepts one simple string as a paramater, in the DataReceived handler you would use an Invoke to replace the Debug line.

    Code:
    Dim Buffer As String = SerialPort.ReadExisting
    
    Me.BeginInvoke((New myDelegate(AddressOf Text_Out)), Buffer)
    Delegates can be designed to accept multiple paramaters of same or different data types

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