|
-
Sep 12th, 2012, 08:38 AM
#1
Thread Starter
Junior Member
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
-
Sep 15th, 2012, 01:32 AM
#2
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.
-
Sep 17th, 2012, 08:30 AM
#3
Thread Starter
Junior Member
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 .
-
Sep 17th, 2012, 09:38 AM
#4
Thread Starter
Junior Member
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
:>
-
Sep 17th, 2012, 12:00 PM
#5
Re: Need some help with com port reads
 Originally Posted by gordk
The 2nd piece of code give an exception
What exception is it giving ?
-
Sep 17th, 2012, 12:32 PM
#6
Thread Starter
Junior Member
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
-
Sep 19th, 2012, 03:02 PM
#7
Thread Starter
Junior Member
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
-
Sep 20th, 2012, 01:09 AM
#8
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.
-
Sep 20th, 2012, 03:11 PM
#9
Thread Starter
Junior Member
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
-
Sep 21st, 2012, 05:57 AM
#10
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)
-
Sep 21st, 2012, 06:35 AM
#11
Thread Starter
Junior Member
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
-
Sep 22nd, 2012, 03:24 AM
#12
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
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|