Serial Communications

I am having similar problems as several other postings I've read here concerning reading from serial ports in Visual basic 2005 Express. Unfortunately I have not seen an answer.
- I can build a list of available com ports
- I can write data to a com port using the "How to: Send Strings to Serial Ports in Visual Basic "
- I cannot read from the port using the sample code for "How to: Receive Strings From Serial Ports in Visual Basic"
I have narrowed the line in question to 

Dim Incoming As String = com1.ReadLine()  

By setting

com1.ReadTimeout = 8000

If after the timeout I open Hyperterminal and open the port, all of the data that should was sent is received. I am connected to another computer using a null modem cable with hyperterminal on the other end to send the data that should be received. The code is below. Basically I have a form with a button that starts the sub procedure to read the port. I've added a line after the open to write to the serial port first ,just to be sure the port is open and hyperterminal on the other computer receives the output, but when I type or send a file back, my VB program still times out(i've set the timeout long enough to send data). Any help would greatly be apreciated since I've already burned a day and 1/2 on this.
Thanks,
Harry
== code ===
Private Sub ButtonSend_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonReceive.Click
    Dim trans As String = "test"
   'trans = readport("COM1", 9600, 0, 8, 1)
    trans = readport("COM1")
   RichTextBox1.Text = trans
End Sub

Private Function readport(ByVal portName As String, Optional ByVal baudRate As Integer = 9600, Optional ByVal parity As System.IO.Ports.Parity = 0, Optional ByVal dataBits As Integer = 8, Optional ByVal stopBits As System.IO.Ports.StopBits = 1)
  ' Receive strings from a serial port.
  Dim returnStr As String = ""
  Dim value As Integer
    Using com1 As IO.Ports.SerialPort = _
            My.Computer.Ports.OpenSerialPort(portName, baudRate, parity, dataBits, stopBits)
      value = com1.ReadTimeout
      com1.ReadTimeout = 8000
      'SerialPort.InfiniteTimeout - consider later
        Do
            com1.WriteLine("First Write then read") 'writes fine
            ' Dim Incoming As String = com1.ReadLine()
            Dim Incoming As String = com1.ReadChar() 'timeout
              'open Hyperteminal and all data is read from buffer that should have been read above
              MsgBox("After Read") 'never see this
            If Incoming Is Nothing Then
              MsgBox("incoming is nothing") ' never see this
              Exit Do
            Else
                returnStr &= Incoming & vbCrLf
            End If
        Loop
    End Using
    Return returnStr
End Function



Answer this question

Serial Communications

  • nolla

    Usually when I do serial communications, I set up an event handler for the comm port's data received event.  Then I get the data whenever it comes in and usually will resend my output until I get a response or send it too many times, at which point I timeout, close the port, and raise a timeout event.  The code could look something like this:


    Dim WithEvents port As New SerialPort("COM1")
     
    Private Sub SendData(ByVal data As String)
        If Not port.IsOpen Then port.Open()
        port.Write(data)
    End Sub

    Private Sub port_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles port.DataReceived
        If e.EventType <> SerialData.Chars Then Exit Sub

        Dim inData As String = port.ReadExisting
        'process incoming data here
    End Sub

     


  • RoshanShah

    There is a fairly clear discussion on this in the Help area of VB 2005 titled
    "How to: Make Thread-Safe Calls to Windows Forms Controls"

    I setup a simple sub routine to display all my serial port communications, then just call it and pass what I want displayed. In the sample code below, my subroutine is DislayText and my text form field is StatusTextbox



    Dim inData As String = comport.ReadExisting ' read the data

    DisplayText(inData) ' use threadsafe way to write to StatusTextbox

    ' This method demonstrates a pattern for making thread-safe TextBox Displays
    Private Sub DisplayText(ByVal [text] As String)
    ' InvokeRequired required compares the thread ID of the
    ' calling thread to the thread ID of the creating thread.
    ' If these threads are different, it returns true.

    If Me.StatusTextbox.InvokeRequired Then
       
    Dim d As New SetTextCallback(AddressOf DisplayText)
       
    Me.Invoke(d, New Object() {[text]})
    Else
       
    Me.StatusTextbox.Text += [text]
    End If
    End
    Sub


     


    Hope this helps
    Harry

  • omegarazor

    My problem is solved. You would think after all these years in the business and working with serial communications I would have figured it out in 5 minutes, but no I had to waste 2 days missing the obvious. The answer was as simple as enabling dtr. I discovered this by adding a "Serial Port Component Control" to my form from the Toolbox and checking the properties. Seeing dtrenable, I enabled it and instantly the data started flowing. This setting is obviously turned on in a terminal program such as Hyperterminal and that should have been my big clue why it worked and mine didn't. I hope this helps anyone else as dense as me in solving their problem.

    The key line I needed to get it working was

    com1.DtrEnable = True ' com1 is my serial port connection from the DIM line

    Thanks again for your help and the code for event handling, it works great.
    Harry


  • Charles Washika

    I've copied your code exactly but when I try to run it I get the error...

    Cross-thread operation not valid: Control 'RichtextBox1' accessed from a thread other than the thread it was created on.

    How can I get the serial port event handler to update the "richtextbox1" with the data from the serial port


  • StoneWasHere

    Thanks for the quick reply. I've played with your suggestion for quite a while. I really like the idea of the even handler being triggered on serial data received, I'll need that for the application I am developing. Unfortunately, it never triggers and in fact the buffer doesn't appear to be read. After exiting my program, I open hyperterminal and out comes all the data I tested with. I believe I have all the code correct. Is there a chance there is something amiss with the VB 2005 express io.ports buffer read

    The only success I have had so far is finding a comport.exe download in an article titled "COM Port Sample" located in help that uses win32 api calls. Far messier than it looks like it has to be, but at least I am getting some data. I still would rather get it to work either your way or the snippet way in my earlier post, there just doesn't appear to be anything obvious I am doing wrong. Below is the code I used from your recommendation. I put in several test points to display ports being open or closed and a reset button if it is closed, but otherwise the same. Is there another part of the handler I am missing

    Thanks Again
    Harry



                Imports System.Text
                Imports System.IO.Ports
    Public Class Form1

    Dim WithEvents com1 As New SerialPort("COM1")

    Private Sub Form1_load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Try
            com1.Open()
        Catch ex As Exception
            RichTextBox1.Text = "Port is closed, please check and retry" + vbCrLf
        End Try
        If com1.IsOpen Then
            RichTextBox1.Text = "port is open" + vbCrLf
        End If
    End Sub
    Private Sub port_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles com1.DataReceived
        MsgBox("made it to sub data received")
        If e.EventType <> SerialData.Chars Then Exit Sub
        Dim inData As String = com1.ReadExisting
        'process incoming data here
        RichTextBox1.Text += inData + vbCrLf
    End Sub

     


  • Serial Communications