Results 1 to 12 of 12

Thread: Need some help with com port reads

  1. #1
    Junior Member
    Join Date
    Sep 12
    Location
    Ottawa
    Posts
    19

    Need some help with com port reads

    HI

    I need a simple bit of code that will read data at the serial port “SerialPort1”
    and store it in a variable then show it in a RichTextBox in real time.

    It will be called as a function "read_data", so I will use a button send data to the com port
    (that is working) then read the com port incoming data, save as a string variable and show it in a richtextbox in realtime.

    I have tried a lot of code examples but nothing seems to work and it’s very frustrating’

    Does anyone have a bit of code that works, I can’t belive that there is not a way to do this but I can’t seem to find it.

    Help Help

    Thanks

    Gord

  2. #2
    PowerPoster
    Join Date
    Jul 06
    Location
    Maldon, Essex. UK
    Posts
    5,143

    Re: Need some help with com port reads

    Don't know if you've resolved this, but when data is received, the DataReceived event is triggered, so you need to code that to get the data and put it into the RechTextBox.

    I'm not a .Net programmer so the code below may look a bit VB6'ish:
    Code:
        Private Sub SerialPort1_DataReceived(sender As Object, e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
            Static ReceiveBuffer As String
            Dim ExitLoop As Boolean
            '
            ' Read whatever has been received by the Serial Port
            ' and append it to the Receive Buffer
            '
            Dim CharReceived As String = SerialPort1.ReadExisting()
            ReceiveBuffer = ReceiveBuffer & CharReceived
            Do
                '
                ' Examine the Receive Buffer to see if the End of Message indicator
                ' has been received
                ' (in this example it's expecting a vbNewLine 
                '
                Dim EndOfMessage As Integer = ReceiveBuffer.IndexOf(vbNewLine)
                If EndOfMessage > 0 Then
                    '
                    ' A complete Record has been received
                    ' Append it to the RichTextBox and add a vbNewLine
                    '
                    RichTextBox1.AppendText(ReceiveBuffer.Substring(0, EndOfMessage))
                    RichTextBox1.AppendText(vbNewLine)
                    '
                    ' See if there's anything else in the Receive Buffer
                    ' If there is then move it to the front and go round the loop again
                    ' If there isn't then flush the Buffer and signal to exit the loop
                    '
                    If ReceiveBuffer.Length > EndOfMessage + 2 Then
                        ReceiveBuffer = ReceiveBuffer.Substring(EndOfMessage + 2)
                    Else
                        ReceiveBuffer = vbNullString
                        ExitLoop = True
                    End If
                Else
                    '
                    ' Haven't received the End of Message indicator
                    ' exit and wait for the next character to be received
                    '
                    ExitLoop = True
                End If
            Loop Until ExitLoop
        End Sub
    The code assumes that ReceiveThreshold = 1 (the default value)

    It also assumes that each 'record' sent is terminated by a vbNewLine.

    It's not tested as I haven't got anything to test it with but hopefully you'll be able to follow the logic.

    EDIT: If the data is just coming in as a 'stream' with no End of Message indicator, the code can be simplified to:
    Code:
        Private Sub SerialPort1_DataReceived(sender As Object, e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
            '
            ' Read whatever has been received by the Serial Port
            ' and append it to the RichTextBox
            '
            RichTextBox1.AppendText(SerialPort1.ReadExisting())
        End Sub
    Last edited by Doogle; Sep 15th, 2012 at 02:08 AM.

  3. #3
    Junior Member
    Join Date
    Sep 12
    Location
    Ottawa
    Posts
    19

    Re: Need some help with com port reads

    Hi Doogle

    I have tried both pieces of code and added a message box and it look like it is doing the code but there is nothing in the richtextbox, it remains blank with the 1st piece of code.

    The 2nd piece of code give an exception. so I’m no further a head..

    Thanks any way I will keep searching for some thing that will work.

    The unit I talking to send me a list of 5 or 6 lines of ASCII text all terminated with CR LF .

  4. #4
    Junior Member
    Join Date
    Sep 12
    Location
    Ottawa
    Posts
    19

    Re: Need some help with com port reads

    Hi Doogle

    The 1st thing the micro send to to serial port is "0dh 0ah" and then the ascii text, is this what is making it fail?

    I need to capture all thew data sent so I can set a response the what is being sent so I need to capture all of it in a string so I can evaluate the text.

    Thanks

    Gord

    This is what it sends to the serial port;

    CRLF
    OM200 Network Menu (Console is Node 1 CRLF
    1 Show nodes CRLF
    2 Node menus CRLF
    3 Change password CRLF
    4 Clear all statistics CRLF
    CRLF
    :>

  5. #5
    PowerPoster
    Join Date
    Jul 06
    Location
    Maldon, Essex. UK
    Posts
    5,143

    Re: Need some help with com port reads

    Quote Originally Posted by gordk View Post
    The 2nd piece of code give an exception
    What exception is it giving ?

  6. #6
    Junior Member
    Join Date
    Sep 12
    Location
    Ottawa
    Posts
    19

    Re: Need some help with com port reads

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

    I would like to be able to get at the com ports reply at any time as a string as it needs to be diceted so I know what to send it next.

    Thanks

    Gord

  7. #7
    Junior Member
    Join Date
    Sep 12
    Location
    Ottawa
    Posts
    19

    Re: Need some help with com port reads

    Hi Doogle

    I got it going with this pice of code
    ____________________________________________________________________________________________________ _________________________________________

    Private Sub SerialPort1_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
    ' MsgBox("RX Loop")

    'clear "LastData" before we start
    LastData = ""

    Static ReceiveBuffer As String
    Dim ExitLoop As Boolean
    '
    ' Read whatever has been received by the Serial Port
    ' and append it to the Receive Buffer
    '
    Dim CharReceived As String = SerialPort1.ReadExisting()
    ReceiveBuffer = ReceiveBuffer & CharReceived
    Do
    '
    ' Examine the Receive Buffer to see if the End of Message indicator
    ' has been received
    ' (in this example it's expecting a vbNewLine
    '
    Dim EndOfMessage As Integer = ReceiveBuffer.IndexOf(vbNewLine)
    If EndOfMessage > 0 Then
    '
    ' A complete Record has been received
    ' Append it to the RichTextBox and add a vbNewLine
    '
    '
    ' See if there's anything else in the Receive Buffer
    ' If there is then move it to the front and go round the loop again
    ' If there isn't then flush the Buffer and signal to exit the loop
    '
    If ReceiveBuffer.Length > EndOfMessage + 2 Then
    ReceiveBuffer = ReceiveBuffer.Substring(EndOfMessage + 2)
    Else
    ReceiveBuffer = vbNullString
    ExitLoop = True
    End If
    Else
    '
    ' Haven't received the End of Message indicator
    ' exit and wait for the next character to be received
    '
    ExitLoop = True
    End If
    Loop Until ExitLoop

    LastData = ReceiveBuffer

    End Sub
    ____________________________________________________________________________________________________ ___________________________________

    I added a global called LastData and at the end I copy the ReceiveBuffer to it, after sending 1 byte in the main code I use this "Do While LastData = "" Loop
    and it works well for multi chrs but if there is just 1 chr being return it just locks up.

    It's like the DataReceived Event is not serviced any more so my "Do While LastData = "" Loop" is allways empty.

    Any ideas on how to fix this ?

    The micro I'm talking to can send me lots of data or just one byte.

    Thanks

    Gord

  8. #8
    PowerPoster
    Join Date
    Jul 06
    Location
    Maldon, Essex. UK
    Posts
    5,143

    Re: Need some help with com port reads

    Can you post the code in the Main Program please. I suspect you're in a tight loop and events aren't being serviced.

  9. #9
    Junior Member
    Join Date
    Sep 12
    Location
    Ottawa
    Posts
    19

    Re: Need some help with com port reads

    Heres all the code:

    Imports System
    Imports System.ComponentModel
    Imports System.Threading
    Imports System.IO.Ports
    'The port this program talks to does not output any thing without being asked
    'ESC is the way to return to the 1st menu and links to all other menus.
    '------------------------------------------------------------------------------------------------------------
    Public Class Form1

    Dim MsgBox1 As String

    Private Property cmbPort As Object

    Private Property cmbPorts As Object

    Private Property cmbBitRate As Object

    Private Property MsgBox As String

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    '
    'This allways loads as part of form1
    '
    SerialPort1.BaudRate = 38400 'Baud rate
    SerialPort1.DataBits = 8 'DataBits
    SerialPort1.StopBits = 1 '1 stop bit
    SerialPort1.Handshake = IO.Ports.Handshake.None 'No Handshake
    SerialPort1.ReadTimeout = 1000 '2 second wait time
    SerialPort1.WriteTimeout = 1000 '2 second wait time
    SerialPort1.Open() ' Open the port
    'Dim myPortNames() As String
    'myPortNames = SerialPort.GetPortNames '
    'TextBox1 = myPortNames
    'Call InitializeForm()

    End Sub
    'Here you declare GlOBALS HERE Variables
    '
    ' Public Shared returnStr As String = ""
    Public Shared LastData As String = ""
    Public Shared CurrentData As String = ""
    Public Shared NumOfNodes As Integer
    Public Shared CurrentNode As Integer
    Public Shared CNode As Integer


    'Initializeform
    Public Sub InitializeForm()
    Dim bitRates(9) As Integer
    Dim nameArray() As String
    'Find com ports
    nameArray = SerialPort.GetPortNames
    Array.Sort(nameArray)
    'Fill Combo box with the port names
    cmbPort.DataSource = (nameArray)
    cmbPort.DropDownStyle =
    ComboBoxStyle.DropDownList

    'Slect a default port
    cmbPorts.SelectIndex = 7

    'Bit rates to select from

    bitRates(0) = 300
    bitRates(1) = 600
    bitRates(2) = 1200
    bitRates(3) = 2400
    bitRates(4) = 9600
    bitRates(5) = 1440
    bitRates(6) = 19200
    bitRates(7) = 38400
    bitRates(8) = 57600
    bitRates(9) = 115200

    'Place bit rate in combo box

    cmbBitRate.DataSource = bitRates
    cmbBitRate.DropDownStyle =
    ComboBoxStyle.DropDownList

    'Select default

    cmbBitRate.SelectItem = 38400

    End Sub


    Private Sub SerialPort1_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
    ' MsgBox("RX Loop")

    'clear "LastData" before we start
    LastData = ""

    Static ReceiveBuffer As String
    Dim ExitLoop As Boolean
    '
    ' Read whatever has been received by the Serial Port
    ' and append it to the Receive Buffer
    '
    Dim CharReceived As String = SerialPort1.ReadExisting()
    ReceiveBuffer = ReceiveBuffer & CharReceived
    Do
    '
    ' Examine the Receive Buffer to see if the End of Message indicator
    ' has been received
    ' (in this example it's expecting a vbNewLine
    '
    Dim EndOfMessage As Integer = ReceiveBuffer.IndexOf(vbNewLine)
    If EndOfMessage > 0 Then
    '
    ' A complete Record has been received
    ' Append it to the RichTextBox and add a vbNewLine
    '
    '
    ' See if there's anything else in the Receive Buffer
    ' If there is then move it to the front and go round the loop again
    ' If there isn't then flush the Buffer and signal to exit the loop
    '
    If ReceiveBuffer.Length > EndOfMessage + 2 Then
    ReceiveBuffer = ReceiveBuffer.Substring(EndOfMessage + 2)
    Else
    ReceiveBuffer = vbNullString
    ExitLoop = True
    End If
    Else
    '
    ' Haven't received the End of Message indicator
    ' exit and wait for the next character to be received
    '
    ExitLoop = True
    End If
    Loop Until ExitLoop


    LastData = ReceiveBuffer

    End Sub
    Public Function send_esc()
    ' Send ESC to serial port
    'SerialPort1.Open() ' Open the port
    SerialPort1.Write(Chr(27)) '27 decimal is ESC 1B hex
    'SerialPort1.Close()
    End Function
    Public Function send_cr()
    'send carrage return
    SerialPort1.Write(Chr(13)) '13 decimal is CR 0Dh
    'SerialPort1.Close()
    End Function
    'Send number 1 to serial port
    Public Function send_1()
    ' Send number 1 to serial port
    SerialPort1.Write(Chr(49))
    'SerialPort1.Close()
    End Function
    'Send number 2 to serial port
    Public Function send_2()
    ' Send number 2 to serial port
    'SerialPort1.Open() ' Open the port
    SerialPort1.Write(Chr(50))
    'SerialPort1.Close()
    End Function
    'Send number 3 to serial port
    Public Function send_3()
    ' Send number 3 to serial port
    'SerialPort1.Open() ' Open the port
    SerialPort1.Write(Chr(51))
    'SerialPort1.Close()
    End Function
    'Send number 4 to serial port
    Public Function send_4()
    ' Send number 4 to serial port
    'SerialPort1.Open() ' Open the port
    SerialPort1.Write(Chr(52))
    'SerialPort1.Close()
    End Function
    'Send number 5 to serial port
    Public Function send_5()
    ' Send number one to serial port
    'SerialPort1.Open() ' Open the port
    SerialPort1.Write(Chr(53))
    'SerialPort1.Close()
    End Function
    'Send number 6 to serial port
    Public Function send_6()
    ' Send number one to serial port
    'SerialPort1.Open() ' Open the port
    SerialPort1.Write(Chr(54))
    'SerialPort1.Close()
    End Function
    'Send number 7 to serial port
    Public Function send_7()
    ' Send number one to serial port
    'SerialPort1.Open() ' Open the port
    SerialPort1.Write(Chr(55))
    'SerialPort1.Close()
    End Function
    'Send number 8 to serial port
    Public Function send_8()
    ' Send number one to serial port
    'SerialPort1.Open() ' Open the port
    SerialPort1.Write(Chr(56))
    'SerialPort1.Close()
    End Function
    'Send number 9 to serial port
    Public Function send_9()
    ' Send number one to serial port
    'SerialPort1.Open() ' Open the port
    SerialPort1.Write(Chr(57))
    'SerialPort1.Close()
    End Function

    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
    ' EXIT Button
    SerialPort1.Close()
    Close()

    End Sub

    'This will become a timer Right now it is the SEND button

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

    'Send Button "Send ESC 4 times to be sure we are at the start
    LastData = "" 'clear last data we got
    Call send_esc()
    'Wait for test to be recived
    Do While LastData = ""
    Loop
    '
    LastData = "" 'clear last data we got
    Call send_esc()
    'Wait for test to be recived
    Do While LastData = ""
    Loop
    '
    LastData = "" 'clear last data we got
    Call send_esc()
    'Wait for test to be recived
    Do While LastData = ""
    Loop
    '
    LastData = "" 'clear last data we got
    Call send_esc()
    'Wait for test to be recived
    Do While LastData = ""
    Loop
    '__________________________________________________________________________________________________
    ' Now we see how maney Nodes we have

    Dim Find As String = "Node " 'locate the string Node space
    Dim CNode As Integer 'dim CNode as string
    Dim i As Integer 'i will be the string number converted to an intger

    CNode = InStr(LastData, Find, CompareMethod.Text) 'get the postion of the 1st chr

    CNode = CNode + 5 ' add 5 so we point at the Console node number

    Dim CNodeNumber As String 'Dim CNodeNumber as string

    CNodeNumber = Mid(LastData, CNode, 2) 'Get the text value of the Console node number

    Dim d As Integer = Integer.Parse(CNodeNumber) 'convert the text number to real number ( d is now the Console Node number )
    '___________________________________________________________________________________________________ ______
    LastData = "" 'clear last data
    Call send_1() 'Send 1 to Show Nodes
    'Thread.Sleep(100)
    Do While LastData = ""
    Loop
    ' RichTextBox1.AppendText(LastData)
    '___________________________________________________________________________________________________ _____________

    LastData = ""
    Call send_1() 'Send 1
    'Thread.Sleep(100)
    'Wait for Data to be received
    Do While LastData = ""
    Loop
    ' ____________________________________________________________________________________________________ ____________

    Call send_cr() 'Send 1 to pick Node 1
    Do While LastData = ""
    Loop

    Call send_1() 'Send i to Show Cards
    'Wait for test to be recived
    Do While LastData = ""
    Loop

    Call send_1() 'Send 1 to Pick Optical card
    'Wait for test to be recived
    Do While LastData = ""
    Loop

    Call send_1() 'Send 1 to show status
    'Wait for test to be recived
    Do While LastData = ""
    Loop


    RichTextBox1.AppendText(LastData)



    End Sub

    Private Sub Label1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
    'MsgBox(returnStr)
    End Sub

    End Class

  10. #10
    PowerPoster
    Join Date
    Jul 06
    Location
    Maldon, Essex. UK
    Posts
    5,143

    Re: Need some help with com port reads

    Ok. I'll have a play later - that 'w' word calls! - I think you can get round the cross thread problem by using a Delegate which (IMHO) would be better than accessing the Buffer and using the loops. Could you confirm that every response from the device is terminated by a CRLF ? and does it need a sequence of 4 ESCs to kick it into life or would just 1 do?

    EDIT: and finally, what version of VB are you using ? (I've got VB2010 Express Edition and VB2008 - I want to make sure that anything I do is going to be compatible with you)

  11. #11
    Junior Member
    Join Date
    Sep 12
    Location
    Ottawa
    Posts
    19

    Re: Need some help with com port reads

    HI

    It’s VB2010 Express and the answer is No not every thing I get sent from the unit is terminated with CRLF some times all I get is a single ASCII chr.

    The 4 ESC are necessary to be sure I’m at the root menu because the menu’s build from there, so depending on what chr I send it will give different sub menus as they build out in a tree type structure. .

    It would be nice if the receive section would capture any chrs sent and just time out if no chrs where received for some time frame (XX milliseconds).

    The unit sends nothing without an input.

    I will hunt around today for some piece of code to do that.

    I’m new to VB but learned basic some ~30 years ago and have been programming with various micros in assembly for the last ~20 years or so.

    I’m a fast learner if I can get pointed in the right direction.

    Gord

  12. #12
    PowerPoster
    Join Date
    Jul 06
    Location
    Maldon, Essex. UK
    Posts
    5,143

    Re: Need some help with com port reads

    The problem I see looming is that in the cases where no CRLF is sent, you don't know when you've received everything, unless you know that after sending a particular 'command' you know how many bytes to expect back. Don't suppose the other end can be modified to always send a terminating CRLF can it? It would make life much simpler.

    EDIT: With respect to the 4 ESCs - I gather that you actually want to send as many as are required to get back to the main menu (?) If so, then you could go through a process like

    Do
    Send an ESC
    Loop until Device responds with Main Menu Or it times out
    Last edited by Doogle; Sep 22nd, 2012 at 03:35 AM.

Posting Permissions

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