-
Jul 29th, 2020, 05:50 AM
#1
Thread Starter
Junior Member
[RESOLVED] look for the carriage return character
Hello,
I'm having problem to read the data from a device i.e. Watson GPS.
It started with letter 'I' and ended with CR (carriage return).
I was suggested to 'look for the carriage return character, and then parse the received data frame by the spacebar character'.
i need to know how can i read the carriage return (vbCr) from the incoming data?
here is currently part of my existing code:
Code:
Private Sub SerialPort1_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
ReceivedText(SerialPort1.ReadExisting()) 'Automatically called every time a data is received at the serialPort
End Sub
Private Sub ReceivedText(ByVal [text] As String)
'compares the ID of the creating Thread to the ID of the calling Thread
If Me.rtbReceived.InvokeRequired Then
Dim x As New SetTextCallback(AddressOf ReceivedText)
Me.Invoke(x, New Object() {(text)})
Else
Me.rtbReceived.Text &= text
Me.RichTextBox1.Text = text + vbNewLine + RichTextBox1.Text 'same as above line actually
Me.RichTextBox2.Text = TimeOfDay.ToLongTimeString + " : " + [text] + vbNewLine + RichTextBox2.Text
Dim i As Integer
Dim character As String
character = split_char_label.Text
Dim split_data() As String = Split([text], character)
Dim no_of_data = split_data.GetLength(0)
no_of_data_label.Text = no_of_data
For i = 0 To i = i + 1
If data_no_label_1.Text = "" Then
TextBox1.Text = ""
Else Try
Int32.TryParse(data_no_label_1.Text, i) 'convert i=string to i=integer
TextBox1.Text = split_data(i)
Catch ex As Exception
End Try
End If
If data_no_label_2.Text = "" Then
TextBox2.Text = ""
Else Try
Int32.TryParse(data_no_label_2.Text, i)
TextBox2.Text = split_data(i)
Catch ex As Exception
End Try
End If
If data_no_label_3.Text = "" Then
TextBox3.Text = ""
Else Try
Int32.TryParse(data_no_label_3.Text, i)
TextBox3.Text = split_data(i)
Catch ex As Exception
End Try
End If
Next
Try
'SIMPLE SPLIT DATA CODE
Dim s As String
s = RichTextBox1.Text
Dim somestring() As String
'split based on comma
somestring = s.Split(New Char() {","c})
TextBox4.Text = somestring(0)
TextBox5.Text = somestring(1)
TextBox6.Text = somestring(2)
TextBox7.Text = somestring(3)
TextBox8.Text = somestring(4)
TextBox9.Text = somestring(5)
Catch e As Exception
End Try
End If
Button2.Text = TextBox1.Text
'GaugeControl2.SetPointerValue("Scale1", "Pointer1", Val(TextBox1.Text))
Button1.Text = TextBox2.Text
'GaugeControl1.SetPointerValue("Scale1", "Pointer1", Val(TextBox2.Text))
Button3.Text = TextBox3.Text
'GaugeControl3.SetPointerValue("Scale1", "Pointer1", Val(TextBox3.Text))
End Sub
my serial comm is working fine only that i could not get stable data. the data i receive is like in the video.
-
Jul 29th, 2020, 06:30 AM
#2
Re: look for the carriage return character
Hello
for this, I usually do that to remove the end of line and carriage return characters :
Code:
NewString = IncomingString.Replace(vbCr, "").Replace(vbLf, "")
regards
The best friend of any programmer is a search engine
"Don't wish it was easier, wish you were better. Don't wish for less problems, wish for more skills. Don't wish for less challenges, wish for more wisdom" (J. Rohn)
“They did not know it was impossible so they did it” (Mark Twain)
-
Jul 29th, 2020, 09:45 AM
#3
Thread Starter
Junior Member
Re: look for the carriage return character
Originally Posted by Delaney
Hello
for this, I usually do that to remove the end of line and carriage return characters :
Code:
NewString = IncomingString.Replace(vbCr, "").Replace(vbLf, "")
regards
i will execute with the device tomorrow. here is the amended code:
Code:
Private Sub SerialPort1_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
ReceivedText(SerialPort1.ReadExisting()) 'Automatically called every time a data is received at the serialPort
End Sub
Private Sub ReceivedText(ByVal [text] As String)
'compares the ID of the creating Thread to the ID of the calling Thread
If Me.rtbReceived.InvokeRequired Then
Dim x As New SetTextCallback(AddressOf ReceivedText)
Me.Invoke(x, New Object() {(text)})
Else
'Look for/replace Carriage Return
Dim NewString As String
NewString = text.Replace(vbCr, "").Replace(vbLf, "")
'Data Display
Me.rtbReceived.Text &= NewString
Me.RichTextBox1.Text = NewString + vbNewLine + RichTextBox1.Text 'same as above line actually
Me.RichTextBox2.Text = TimeOfDay.ToLongTimeString + " : " + [NewString] + vbNewLine + RichTextBox2.Text
Dim i As Integer
Dim character As String
character = split_char_label.Text
Dim split_data() As String = Split([NewString], character)
Dim no_of_data = split_data.GetLength(0)
no_of_data_label.Text = no_of_data
For i = 0 To i = i + 1
If data_no_label_1.Text = "" Then
TextBox1.Text = ""
Else Try
Int32.TryParse(data_no_label_1.Text, i) 'convert i=string to i=integer
TextBox1.Text = split_data(i)
Catch ex As Exception
End Try
End If
If data_no_label_2.Text = "" Then
TextBox2.Text = ""
Else Try
Int32.TryParse(data_no_label_2.Text, i)
TextBox2.Text = split_data(i)
Catch ex As Exception
End Try
End If
If data_no_label_3.Text = "" Then
TextBox3.Text = ""
Else Try
Int32.TryParse(data_no_label_3.Text, i)
TextBox3.Text = split_data(i)
Catch ex As Exception
End Try
End If
Next
Try
'SIMPLE SPLIT DATA CODE
Dim s As String
s = RichTextBox1.Text
Dim somestring() As String
'split based on comma
somestring = s.Split(New Char() {","c})
TextBox4.Text = somestring(0)
TextBox5.Text = somestring(1)
TextBox6.Text = somestring(2)
TextBox7.Text = somestring(3)
TextBox8.Text = somestring(4)
TextBox9.Text = somestring(5)
Catch e As Exception
End Try
End If
Button2.Text = TextBox1.Text
'GaugeControl2.SetPointerValue("Scale1", "Pointer1", Val(TextBox1.Text))
Button1.Text = TextBox2.Text
'GaugeControl1.SetPointerValue("Scale1", "Pointer1", Val(TextBox2.Text))
Button3.Text = TextBox3.Text
'GaugeControl3.SetPointerValue("Scale1", "Pointer1", Val(TextBox3.Text))
End Sub
-
Jul 29th, 2020, 10:43 AM
#4
Re: look for the carriage return character
If the data ends with a Cr, rather than using SerialPort1.ReadExisting() I would use SerialPort1.ReadLine().
That way you only process a whole line of data, you don't have to reassemble from partial lines. The Carriage Control character is not returned as part of the line of data.
Once you've read the first line, which could be partial, all the rest of the lines should be automatically framed, i.e. the line you get starts after the last CR and up to the next CR.
"Anyone can do any amount of work, provided it isn't the work he is supposed to be doing at that moment" Robert Benchley, 1930
-
Jul 29th, 2020, 09:51 PM
#5
Thread Starter
Junior Member
Re: look for the carriage return character
Here is the latest code, getting better results as in video, but still not stable. again when i use readline, no data coming in.
Code:
Imports System
Imports System.ComponentModel
Imports System.Threading
Imports System.IO.Ports
Public Class Form1
Dim myPort As Array 'COM Ports detected on the system will be stored here
Delegate Sub SetTextCallback(ByVal [text] As String) 'Added to prevent threading errors during receiveing of data
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
'When our form loads, auto detect all serial ports in the system and populate the cmbPort Combo box.
myPort = IO.Ports.SerialPort.GetPortNames() 'Get all com ports available
cmbBaud.Items.Add(1200) 'Populate the cmbBaud Combo box to common baud rates used
cmbBaud.Items.Add(2400)
cmbBaud.Items.Add(3600)
cmbBaud.Items.Add(4800)
cmbBaud.Items.Add(7200)
cmbBaud.Items.Add(9600)
cmbBaud.Items.Add(14400)
cmbBaud.Items.Add(19200)
cmbBaud.Items.Add(28800)
cmbBaud.Items.Add(38400)
cmbBaud.Items.Add(57600)
cmbBaud.Items.Add(76800)
cmbBaud.Items.Add(115200)
cmbBaud.Items.Add(153600)
cmbBaud.Items.Add(230400)
cmbBaud.Items.Add(307200)
cmbBaud.Items.Add(460800)
cmbBaud.Items.Add(921600)
For i = 0 To UBound(myPort)
cmbPort.Items.Add(myPort(i))
Next
'cmbPort.Text = cmbPort.Items.Item(0) 'Set cmbPort text to the first COM port detected
'cmbBaud.Text = cmbBaud.Items.Item(0) 'Set cmbBaud text to the first Baud rate on the list
btnDisconnect.Enabled = False 'Initially Disconnect Button is Disabled
End Sub
Private Sub btnConnect_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnConnect.Click
SerialPort1.PortName = cmbPort.Text 'Set SerialPort1 to the selected COM port at startup
SerialPort1.BaudRate = cmbBaud.Text 'Set Baud rate to the selected value on
'Other Serial Port Property
SerialPort1.Parity = IO.Ports.Parity.None
SerialPort1.StopBits = IO.Ports.StopBits.One
SerialPort1.DataBits = 8 'Open our serial port
SerialPort1.Open()
btnConnect.Enabled = False 'Disable Connect button
btnDisconnect.Enabled = True 'and Enable Disconnect button
End Sub
Private Sub btnDisconnect_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnDisconnect.Click
SerialPort1.Close() 'Close our Serial Port
btnConnect.Enabled = True
btnDisconnect.Enabled = False
rtbReceived.Text = " "
RichTextBox1.Text = ""
End Sub
Private Sub btnSend_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSend.Click
SerialPort1.Write(txtTransmit.Text & vbCr)
'The text contained in the txtText will be sent to the serial port as ascii
'plus the carriage return (Enter Key) the carriage return can be ommitted if the other end does not need it
End Sub
Private Sub SerialPort1_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
ReceivedText(SerialPort1.ReadExisting()) 'Automatically called every time a data is received at the serialPort
End Sub
Private Sub ReceivedText(ByVal [text] As String)
'Look for/replace Carriage Return
Dim NewString As String
NewString = text.Replace(vbCr, "").Replace(vbLf, "")
'compares the ID of the creating Thread to the ID of the calling Thread
If Me.rtbReceived.InvokeRequired Then
Dim x As New SetTextCallback(AddressOf ReceivedText)
Me.Invoke(x, New Object() {(NewString)})
Else
'Data Display
Me.rtbReceived.Text &= NewString
Me.RichTextBox1.Text = NewString + vbNewLine + RichTextBox1.Text 'same as above line actually
Me.RichTextBox2.Text = TimeOfDay.ToLongTimeString + " : " + [NewString] + vbNewLine + RichTextBox2.Text
Dim i As Integer
Dim character As String
character = split_char_label.Text
Dim split_data() As String = Split([NewString], character)
Dim no_of_data = split_data.GetLength(0)
no_of_data_label.Text = no_of_data
For i = 0 To i = i + 1
If data_no_label_1.Text = "" Then
TextBox1.Text = ""
Else Try
Int32.TryParse(data_no_label_1.Text, i) 'convert i=string to i=integer
TextBox1.Text = split_data(i)
Catch ex As Exception
End Try
End If
If data_no_label_2.Text = "" Then
TextBox2.Text = ""
Else Try
Int32.TryParse(data_no_label_2.Text, i)
TextBox2.Text = split_data(i)
Catch ex As Exception
End Try
End If
If data_no_label_3.Text = "" Then
TextBox3.Text = ""
Else Try
Int32.TryParse(data_no_label_3.Text, i)
TextBox3.Text = split_data(i)
Catch ex As Exception
End Try
End If
Next
Try
'SIMPLE SPLIT DATA CODE
Dim s As String
s = RichTextBox1.Text
Dim somestring() As String
'split based on comma
somestring = s.Split(New Char() {","c})
TextBox4.Text = somestring(0)
TextBox5.Text = somestring(1)
TextBox6.Text = somestring(2)
TextBox7.Text = somestring(3)
TextBox8.Text = somestring(4)
TextBox9.Text = somestring(5)
Catch e As Exception
End Try
End If
Button2.Text = TextBox1.Text
'GaugeControl2.SetPointerValue("Scale1", "Pointer1", Val(TextBox1.Text))
Button1.Text = TextBox2.Text
'GaugeControl1.SetPointerValue("Scale1", "Pointer1", Val(TextBox2.Text))
Button3.Text = TextBox3.Text
'GaugeControl3.SetPointerValue("Scale1", "Pointer1", Val(TextBox3.Text))
End Sub
Private Sub cmbPort_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmbPort.SelectedIndexChanged
If SerialPort1.IsOpen = False Then
SerialPort1.PortName = cmbPort.Text 'pop a message box to user if he is changing ports
Else 'without disconnecting first.
MsgBox("Valid only if port is Closed", vbCritical)
End If
End Sub
Private Sub cmbBaud_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmbBaud.SelectedIndexChanged
If SerialPort1.IsOpen = False Then
SerialPort1.BaudRate = cmbBaud.Text 'pop a message box to user if he is changing baud rate
Else 'without disconnecting first.
MsgBox("Valid only if port is Closed", vbCritical)
End If
End Sub
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
SerialPort1.Write(txtTransmit.Text & vbCr)
If SerialPort1.IsOpen Then
Timer1.Interval = Timer1.Interval + 1
If Timer1.Interval Mod 2 = 0 Then
PictureBox1.Visible = True
Else
PictureBox1.Visible = False
End If
End If
End Sub
Private Sub ExitBtn_Click(sender As Object, e As EventArgs) Handles ExitBtn.Click
End
End Sub
End Class
video link:
-
Jul 31st, 2020, 09:21 AM
#6
Re: look for the carriage return character
Since the ReadExisting may not be a complete string, i.e. you're reading what you've got so far, which may be an arbitrary point in the stream of characters coming in the serial port, you have to make sure you combine any trailing parts of an incomplete string sequence to the front of the next portion of the string stream.
You split NewString, so if you get an array of 3 strings returned, the first two are complete, but the third has a good chance of being a partial message. You need to save that third one and append new data to it so it is part of the split of the next existing string data you receive.
"Anyone can do any amount of work, provided it isn't the work he is supposed to be doing at that moment" Robert Benchley, 1930
-
Aug 17th, 2020, 08:57 PM
#7
Thread Starter
Junior Member
Re: look for the carriage return character
thanks. btw, how can i input carriage return and line feed into the split character box?
currently my code is like this:
Code:
Dim character As String
character = split_char_label.Text
Dim split_data() As String = Split([NewString], character)
Dim no_of_data = split_data.GetLength(0)
is this the correct way?:
Code:
Dim character As Char
character = split_char_label.Text
'Dim splitChar As String
'splitChar = Convert.ToString(character)
Dim split_data() As String = Split([text], character)
Dim no_of_data = split_data.GetLength(0)
-
Aug 17th, 2020, 09:45 PM
#8
Thread Starter
Junior Member
Re: look for the carriage return character
Originally Posted by passel
Since the ReadExisting may not be a complete string, i.e. you're reading what you've got so far, which may be an arbitrary point in the stream of characters coming in the serial port, you have to make sure you combine any trailing parts of an incomplete string sequence to the front of the next portion of the string stream.
You split NewString, so if you get an array of 3 strings returned, the first two are complete, but the third has a good chance of being a partial message. You need to save that third one and append new data to it so it is part of the split of the next existing string data you receive.
i'm truly sorry, it's too confusing for me. i need help where to start to write save the third string and join it back with the string flow?
-
Aug 18th, 2020, 11:39 AM
#9
Re: look for the carriage return character
Well, I was thinking after you split the string, the last element in the array you wouldn't process. You would prepend it to the next string processed, that way if it was a partial element, it would be complete when added to the front of the next string processed.
I modified some of the posted code to illustrate
Code:
Private Sub ReceivedText(ByVal [text] As String)
Static CarryOver As String
text = CarryOver & text 'prepend last portion of previous string to this string
'Look for/replace Carriage Return
Dim NewString As String
NewString = text.Replace(vbCr, "").Replace(vbLf, "")
'compares the ID of the creating Thread to the ID of the calling Thread
If Me.rtbReceived.InvokeRequired Then
Dim x As New SetTextCallback(AddressOf ReceivedText)
Me.Invoke(x, New Object() {(NewString)})
Else
'Data Display
Me.rtbReceived.Text &= NewString
Me.RichTextBox1.Text = NewString + vbNewLine + RichTextBox1.Text 'same as above line actually
Me.RichTextBox2.Text = TimeOfDay.ToLongTimeString + " : " + [NewString] + vbNewLine + RichTextBox2.Text
Dim i As Integer
Dim character As String
character = split_char_label.Text
Dim split_data() As String = Split([NewString], character)
Dim no_of_data = split_data.GetLength(0)
CarryOver = split_data(no_of_data - 1) 'save last portion to prepend to next string
no_of_data -= 1 'don't process the last portion
no_of_data_label.Text = no_of_data
For i = 0 To i = i + 1
'....
I stopped at the beginning of the loop, as the rest of the code doesn't make a lot of sense to me, and that loop seems like it wouldn't loop, it would just run through once.
For i = 0 to i = i + 1
Since you can't do an assignment on the right side argument loop to (i = i + 1), then that expression has to be evaluated as a boolean expression (is i equal to i + 1). Since i can't equal i + 1, then the answer is False, so your loop is
For i = 0 to False
Now if you had Option Strict on, then that would be a syntax error, but you obviously don't have Option Strict On (which you should set up to be automatically On for every project), the False will be converted to its numeric equivalent, which is 0, so your loop ends up being
for i = 0 to 0
So, it will run once.
Since you don't initialize i, it will start at 0, so perhaps what you want is
for i = 0 to 1
If i did have a value, then I don't think I would use it as the loop variable, i would just another loop variable.
For j As Integer = 0 to i + 1
or perhaps
For j As Integer = i to i + 1
Depending on what your intention is.
"Anyone can do any amount of work, provided it isn't the work he is supposed to be doing at that moment" Robert Benchley, 1930
-
Aug 18th, 2020, 12:07 PM
#10
Re: look for the carriage return character
You said this was a Watson GPS. What reference do you have for what you expect to receive? Is it NMEA?
EDIT: pg. 7 of this maybe
https://www.google.com/url?sa=t&rct=...9qEKFiWf1hu84-
Last edited by dbasnett; Aug 18th, 2020 at 12:21 PM.
-
Aug 18th, 2020, 05:39 PM
#11
Thread Starter
Junior Member
Re: look for the carriage return character
-
Aug 18th, 2020, 06:55 PM
#12
Thread Starter
Junior Member
Re: look for the carriage return character
Originally Posted by passel
Well, I was thinking after you split the string, the last element in the array you wouldn't process. You would prepend it to the next string processed, that way if it was a partial element, it would be complete when added to the front of the next string processed.
I modified some of the posted code to illustrate
Code:
Private Sub ReceivedText(ByVal [text] As String)
Static CarryOver As String
text = CarryOver & text 'prepend last portion of previous string to this string
'Look for/replace Carriage Return
Dim NewString As String
NewString = text.Replace(vbCr, "").Replace(vbLf, "")
'compares the ID of the creating Thread to the ID of the calling Thread
If Me.rtbReceived.InvokeRequired Then
Dim x As New SetTextCallback(AddressOf ReceivedText)
Me.Invoke(x, New Object() {(NewString)})
Else
'Data Display
Me.rtbReceived.Text &= NewString
Me.RichTextBox1.Text = NewString + vbNewLine + RichTextBox1.Text 'same as above line actually
Me.RichTextBox2.Text = TimeOfDay.ToLongTimeString + " : " + [NewString] + vbNewLine + RichTextBox2.Text
Dim i As Integer
Dim character As String
character = split_char_label.Text
Dim split_data() As String = Split([NewString], character)
Dim no_of_data = split_data.GetLength(0)
CarryOver = split_data(no_of_data - 1) 'save last portion to prepend to next string
no_of_data -= 1 'don't process the last portion
no_of_data_label.Text = no_of_data
For i = 0 To i = i + 1
'....
I stopped at the beginning of the loop, as the rest of the code doesn't make a lot of sense to me, and that loop seems like it wouldn't loop, it would just run through once.
For i = 0 to i = i + 1
Since you can't do an assignment on the right side argument loop to (i = i + 1), then that expression has to be evaluated as a boolean expression (is i equal to i + 1). Since i can't equal i + 1, then the answer is False, so your loop is
For i = 0 to False
Now if you had Option Strict on, then that would be a syntax error, but you obviously don't have Option Strict On (which you should set up to be automatically On for every project), the False will be converted to its numeric equivalent, which is 0, so your loop ends up being
for i = 0 to 0
So, it will run once.
Since you don't initialize i, it will start at 0, so perhaps what you want is
for i = 0 to 1
If i did have a value, then I don't think I would use it as the loop variable, i would just another loop variable.
For j As Integer = 0 to i + 1
or perhaps
For j As Integer = i to i + 1
Depending on what your intention is.
ok, i understand your point. regardless the way of loop i will use, i don't really know where to place or insert the CarryOver.
do i need to combine it to the split_data again in a loop?
-
Aug 18th, 2020, 08:50 PM
#13
Thread Starter
Junior Member
Re: look for the carriage return character
Originally Posted by Zumbie
ok, i understand your point. regardless the way of loop i will use, i don't really know where to place or insert the CarryOver.
do i need to combine it to the split_data again in a loop?
Sorry, since i can't delete my post, i actually wanted to ask different question,
regardless the way of loop i will use, how can i combine that last data to my new incoming data?
-
Aug 19th, 2020, 08:04 AM
#14
Re: look for the carriage return character
That is in the code I posted.
If you search for CarryOver you see where it is saved and where it is prepended to the new incoming data.
"Anyone can do any amount of work, provided it isn't the work he is supposed to be doing at that moment" Robert Benchley, 1930
-
Aug 19th, 2020, 08:20 AM
#15
Re: look for the carriage return character
My philosophy for SerialPort is to do as little as possible in the DataReceived event. The following example shows that. In the example I have started a Task that does the real work. Note how the Task interacts with the UI.
Code:
Private ReadSerialPortTask As task
Private Sub Form1_Shown(sender As Object, e As EventArgs) Handles Me.Shown
'start the worker task <<<<<<<<<<<<!!!!!
'this could be in the load event also
ReadSerialPortTask = Task.Run(Sub() ReadSerialPort())
End Sub
Private Sub SerialPort1_DataReceived(sender As Object,
e As IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
'this is it
ReadWait.Set() 'cause ReadSerialPort to run
End Sub
Private ReadWait As New Threading.AutoResetEvent(False)
Private Sub ReadSerialPort()
'
'this is run as a Background task
'
Dim data As New System.Text.StringBuilder(1024 * 1024) 'accumulate SerialPort data here
Dim mess As New System.Text.StringBuilder 'individual message
Dim foundMess As Boolean = False
Do
ReadWait.WaitOne() 'wait for SerialPort1.DataReceived
Do While SerialPort1.BytesToRead > 0 'accumulate all available bytes
data.Append(SerialPort1.ReadExisting)
Loop
Do 'process message, if one available
mess.Length = 0 'reset message
foundMess = False 'not found
Dim idx As Integer = 0
For idx = 0 To data.Length - 1 'look for CR
If data(idx) = ControlChars.Cr Then
'note that the CR will NOT be in mess
foundMess = True 'found message
Exit For
End If
mess.Append(data(idx))
Next
If foundMess Then
data.Remove(0, idx + 1) 'remove found message from data
'
'process your message here <<<<<<<<<<<<
'note how UI interaction is handled in example
'
'example MY message has two parts separated by tab
Dim parts() As String
parts = mess.ToString.Split(ControlChars.Tab)
'how to interact with the UI
Me.Invoke(Sub()
Label1.Text = parts(0)
RichTextBox1.AppendText(parts(1))
RichTextBox1.AppendText(ControlChars.Cr)
RichTextBox1.ScrollToCaret()
End Sub)
'end example
End If
'look for more messages in data?
Loop While foundMess AndAlso data.Length > 0
Loop
End Sub
Last edited by dbasnett; Aug 19th, 2020 at 09:10 AM.
-
Aug 19th, 2020, 09:52 AM
#16
Thread Starter
Junior Member
Re: look for the carriage return character
Originally Posted by dbasnett
My philosophy for SerialPort is to do as little as possible in the DataReceived event. The following example shows that. In the example I have started a Task that does the real work. Note how the Task interacts with the UI.
Code:
Private ReadSerialPortTask As task
Private Sub Form1_Shown(sender As Object, e As EventArgs) Handles Me.Shown
'start the worker task <<<<<<<<<<<<!!!!!
'this could be in the load event also
ReadSerialPortTask = Task.Run(Sub() ReadSerialPort())
End Sub
Private Sub SerialPort1_DataReceived(sender As Object,
e As IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
'this is it
ReadWait.Set() 'cause ReadSerialPort to run
End Sub
Private ReadWait As New Threading.AutoResetEvent(False)
Private Sub ReadSerialPort()
'
'this is run as a Background task
'
Dim data As New System.Text.StringBuilder(1024 * 1024) 'accumulate SerialPort data here
Dim mess As New System.Text.StringBuilder 'individual message
Dim foundMess As Boolean = False
Do
ReadWait.WaitOne() 'wait for SerialPort1.DataReceived
Do While SerialPort1.BytesToRead > 0 'accumulate all available bytes
data.Append(SerialPort1.ReadExisting)
Loop
Do 'process message, if one available
mess.Length = 0 'reset message
foundMess = False 'not found
Dim idx As Integer = 0
For idx = 0 To data.Length - 1 'look for CR
If data(idx) = ControlChars.Cr Then
'note that the CR will NOT be in mess
foundMess = True 'found message
Exit For
End If
mess.Append(data(idx))
Next
If foundMess Then
data.Remove(0, idx + 1) 'remove found message from data
'
'process your message here <<<<<<<<<<<<
'note how UI interaction is handled in example
'
'example MY message has two parts separated by tab
Dim parts() As String
parts = mess.ToString.Split(ControlChars.Tab)
'how to interact with the UI
Me.Invoke(Sub()
Label1.Text = parts(0)
RichTextBox1.AppendText(parts(1))
RichTextBox1.AppendText(ControlChars.Cr)
RichTextBox1.ScrollToCaret()
End Sub)
'end example
End If
'look for more messages in data?
Loop While foundMess AndAlso data.Length > 0
Loop
End Sub
i modify the code to suit my application. however, there is no incoming data. i've added timer as well inside Form1_Load just in case but still nothing.
Code:
If foundMess Then
data.Remove(0, idx + 1) 'remove found message from data
'
'process your message here <<<<<<<<<<<<
'note how UI interaction is handled in example
'
Dim character As String
character = split_char_label.Text
Dim parts() As String = Split(mess.ToString, character)
rtbReceived.Text = mess.ToString
'how to interact with the UI
Me.Invoke(Sub()
TextBox1.Text = parts(0)
TextBox2.Text = parts(1)
End Sub)
'end example
End If
-
Aug 19th, 2020, 12:13 PM
#17
Re: look for the carriage return character
The code assumes that you had opened the port for SerialPort1 somewhere. FWIW - I did test the code.
Last edited by dbasnett; Aug 19th, 2020 at 12:37 PM.
-
Aug 19th, 2020, 10:04 PM
#18
Thread Starter
Junior Member
Re: look for the carriage return character from serial port
actually my port was opened. now i modified my open port to simple one here:
Code:
Imports System
Imports System.IO.Ports
Public Class Form1
Dim comPORT As String
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Timer1.Enabled = False
comPORT = ""
For Each sp As String In My.Computer.Ports.SerialPortNames
comPort_ComboBox.Items.Add(sp)
Next
End Sub
Private Sub comPort_ComboBox_SelectedIndexChanged(ByVal sender As Object, ByVal e As EventArgs) Handles comPort_ComboBox.SelectedIndexChanged
If (comPort_ComboBox.SelectedItem <> "") Then
comPORT = comPort_ComboBox.SelectedItem
End If
End Sub
Private Sub connect_BTN_Click(ByVal sender As Object, ByVal e As EventArgs) Handles connect_BTN.Click
If (connect_BTN.Text = "Connect") Then
If (comPORT <> "") Then
SerialPort1.Close()
SerialPort1.PortName = comPORT
SerialPort1.BaudRate = 9600
SerialPort1.DataBits = 8
SerialPort1.Parity = Parity.None
SerialPort1.StopBits = StopBits.One
SerialPort1.Handshake = Handshake.None
SerialPort1.Encoding = System.Text.Encoding.Default
SerialPort1.ReadTimeout = 1000 ' 10000
SerialPort1.Open()
connect_BTN.Text = "Dis-connect"
Timer1.Enabled = True
Timer_LBL.Text = "Timer: ON"
Else
MsgBox("Select a COM port first")
End If
Else
SerialPort1.Close()
connect_BTN.Text = "Connect"
Timer1.Enabled = False
Timer_LBL.Text = "Timer: OFF"
End If
End Sub
Private Sub Timer1_Tick(ByVal sender As Object, ByVal e As EventArgs) Handles Timer1.Tick
receivedData = ReceiveSerialData()
Dim strArr
strArr = receivedData.Split(" ")
Try
TextBox1.Text = strArr(0)
TextBox2.Text = strArr(1)
TextBox3.Text = strArr(2)
Me.RichTextBox1.Text = TimeOfDay.ToLongTimeString + " : " + receivedData + vbNewLine + RichTextBox1.Text
Catch er As Exception
End Try
End Sub
Function ReceiveSerialData() As String
Dim Incoming As String
Try
Incoming = SerialPort1.ReadExisting()
If Incoming Is Nothing Then
Return "nothing" & vbCrLf
Else
Return Incoming
End If
Catch ex As TimeoutException
Return "Error: Serial Port read timed out."
End Try
End Function
Private Sub clear_BTN_Click(ByVal sender As Object, ByVal e As EventArgs) Handles clear_BTN.Click
RichTextBox1.Text = ""
End Sub
End Class
basically the above code works and can receive the simulated data. Now i try embed the code from Mr. dbasnett but nothing appear so far:
Code:
Imports System
Imports System.IO.Ports
Public Class Form1
Dim comPORT As String
'Dim receivedData As String = ""
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
ReadSerialPortTask = Task.Run(Sub() ReadSerialPort())
Timer1.Enabled = False
comPORT = ""
For Each sp As String In My.Computer.Ports.SerialPortNames
comPort_ComboBox.Items.Add(sp)
Next
End Sub
Private Sub comPort_ComboBox_SelectedIndexChanged(ByVal sender As Object, ByVal e As EventArgs) Handles comPort_ComboBox.SelectedIndexChanged
If (comPort_ComboBox.SelectedItem <> "") Then
comPORT = comPort_ComboBox.SelectedItem
End If
End Sub
Private Sub connect_BTN_Click(ByVal sender As Object, ByVal e As EventArgs) Handles connect_BTN.Click
If (connect_BTN.Text = "Connect") Then
If (comPORT <> "") Then
SerialPort1.Close()
SerialPort1.PortName = comPORT
SerialPort1.BaudRate = 9600
SerialPort1.DataBits = 8
SerialPort1.Parity = Parity.None
SerialPort1.StopBits = StopBits.One
SerialPort1.Handshake = Handshake.None
SerialPort1.Encoding = System.Text.Encoding.Default
SerialPort1.ReadTimeout = 1000 ' 10000
SerialPort1.Open()
connect_BTN.Text = "Dis-connect"
Timer1.Enabled = True
Timer_LBL.Text = "Timer: ON"
Else
MsgBox("Select a COM port first")
End If
Else
SerialPort1.Close()
connect_BTN.Text = "Connect"
Timer1.Enabled = False
Timer_LBL.Text = "Timer: OFF"
End If
End Sub
Private Sub clear_BTN_Click(ByVal sender As Object, ByVal e As EventArgs) Handles clear_BTN.Click
RichTextBox1.Text = ""
End Sub
Private ReadSerialPortTask As Task
Private Sub Form1_Shown(sender As Object, e As EventArgs) Handles Me.Shown
'start the worker task <<<<<<<<<<<<!!!!!
'this could be in the load event also
End Sub
Private Sub SerialPort1_DataReceived(sender As Object, e As IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
'this is it
ReadWait.Set() 'cause ReadSerialPort to run
End Sub
Private ReadWait As New Threading.AutoResetEvent(False)
Private Sub ReadSerialPort()
'
'this is run as a Background task
'
Dim data As New System.Text.StringBuilder(1024 * 1024) 'accumulate SerialPort data here
Dim mess As New System.Text.StringBuilder 'individual message
Dim foundMess As Boolean = False
Do
ReadWait.WaitOne() 'wait for SerialPort1.DataReceived
Do While SerialPort1.BytesToRead > 0 'accumulate all available bytes
data.Append(SerialPort1.ReadExisting)
Loop
Do 'process message, if one available
mess.Length = 0 'reset message
foundMess = False 'not found
Dim idx As Integer = 0
For idx = 0 To data.Length - 1 'look for CR
If data(idx) = ControlChars.Cr Then
'note that the CR will NOT be in mess
foundMess = True 'found message
Exit For
End If
mess.Append(data(idx))
Next
If foundMess Then
data.Remove(0, idx + 1) 'remove found message from data
'
'process your message here <<<<<<<<<<<<
'note how UI interaction is handled in example
'
'example MY message has two parts separated by tab
Dim parts() As String
parts = mess.ToString.Split(New Char() {" "c})
'how to interact with the UI
Me.Invoke(Sub()
Label1.Text = parts(0)
RichTextBox2.AppendText(parts(1))
RichTextBox2.AppendText(ControlChars.Cr)
RichTextBox2.ScrollToCaret()
End Sub)
'end example
End If
'look for more messages in data?
Loop While foundMess AndAlso data.Length > 0
Loop
End Sub
End Class
-
Aug 20th, 2020, 07:34 AM
#19
Re: look for the carriage return character from serial port
I made some minor changes to your second piece of code. When I ran it it worked fine.
Pay attention to what code you put at
'process your message here <<<<<<<<<<<<
Code:
Imports System
Imports System.IO.Ports
Public Class Form1
Dim comPORT As String
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
ReadSerialPortTask = Task.Run(Sub() ReadSerialPort())
Timer1.Enabled = False
comPORT = ""
For Each sp As String In My.Computer.Ports.SerialPortNames
comPort_ComboBox.Items.Add(sp)
Next
End Sub
Private Sub comPort_ComboBox_SelectedIndexChanged(ByVal sender As Object, ByVal e As EventArgs) Handles comPort_ComboBox.SelectedIndexChanged
If (comPort_ComboBox.SelectedItem.ToString <> "") Then
comPORT = comPort_ComboBox.SelectedItem.ToString
End If
End Sub
Private Sub connect_BTN_Click(ByVal sender As Object, ByVal e As EventArgs) Handles connect_BTN.Click
If (connect_BTN.Text = "Connect") Then
If (comPORT <> "") Then
SerialPort1.Close()
SerialPort1.PortName = comPORT
SerialPort1.BaudRate = 9600
SerialPort1.DataBits = 8
SerialPort1.Parity = Parity.None
SerialPort1.StopBits = StopBits.One
SerialPort1.Handshake = Handshake.None
SerialPort1.Encoding = System.Text.Encoding.Default
SerialPort1.ReadTimeout = 1000 ' 10000
SerialPort1.Open()
SerialPort1.DtrEnable = True
connect_BTN.Text = "Dis-connect"
Timer1.Enabled = True
Timer_LBL.Text = "Timer: ON"
Else
MsgBox("Select a COM port first")
End If
Else
SerialPort1.Close()
connect_BTN.Text = "Connect"
Timer1.Enabled = False
Timer_LBL.Text = "Timer: OFF"
End If
End Sub
Private Sub clear_BTN_Click(ByVal sender As Object, ByVal e As EventArgs) Handles clear_BTN.Click
RichTextBox1.Text = ""
End Sub
Private ReadSerialPortTask As Task
Private Sub SerialPort1_DataReceived(sender As Object,
e As IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
'this is it
ReadWait.Set() 'cause ReadSerialPort to run
End Sub
Private ReadWait As New Threading.AutoResetEvent(False)
Private Sub ReadSerialPort()
'
'this is run as a Background task
'
Dim data As New System.Text.StringBuilder(1024 * 1024) 'accumulate SerialPort data here
Dim mess As New System.Text.StringBuilder 'individual message
Dim foundMess As Boolean = False
Do
ReadWait.WaitOne() 'wait for SerialPort1.DataReceived
Do While SerialPort1.BytesToRead > 0 'accumulate all available bytes
data.Append(SerialPort1.ReadExisting)
Loop
Do 'process message, if one available
mess.Length = 0 'reset message
foundMess = False 'not found
Dim idx As Integer = 0
For idx = 0 To data.Length - 1 'look for CR
If data(idx) = ControlChars.Cr Then
'note that the CR will NOT be in mess
foundMess = True 'found message
Exit For
End If
mess.Append(data(idx))
Next
If foundMess Then
data.Remove(0, idx + 1) 'remove found message from data
'
'process your message here <<<<<<<<<<<<
'how to interact with the UI
Me.Invoke(Sub()
RichTextBox1.AppendText(mess.ToString)
RichTextBox1.AppendText(ControlChars.Cr)
End Sub)
'end example
End If
'look for more messages in data?
Loop While foundMess AndAlso data.Length > 0
Loop
End Sub
End Class
-
Aug 21st, 2020, 09:46 AM
#20
Thread Starter
Junior Member
Re: look for the carriage return character
i'm sorry that i'm no expert. correct me if i'm wrong.
i tried to run with break point. the process doesn't proceed to next level.
Code:
Do While SerialPort1.BytesToRead > 0 'accumulate all available bytes
data.Append(SerialPort1.ReadExisting)
Loop
is the other process actually running? Sorry again i've no clue.
so i tried to modify the loop point like this:
Code:
Do
ReadWait.WaitOne() 'wait for SerialPort1.DataReceived
Do While SerialPort1.BytesToRead > 0 'accumulate all available bytes
data.Append(SerialPort1.ReadExisting)
Do 'process message, if one available
mess.Length = 0 'reset message
foundMess = False 'not found
Dim idx As Integer = 0
For idx = 0 To data.Length - 1 'look for CR
If data(idx) = ControlChars.Cr Then
'note that the CR will NOT be in mess
foundMess = True 'found message
Exit For
End If
mess.Append(data(idx))
Next
If foundMess Then
data.Remove(0, idx + 1) 'remove found message from data
'
'process your message here <<<<<<<<<<<<
'how to interact with the UI
Me.Invoke(Sub()
RichTextBox1.AppendText(mess.ToString)
RichTextBox1.AppendText(ControlChars.Cr)
End Sub)
'end example
End If
'look for more messages in data?
Loop While foundMess AndAlso data.Length > 0
Loop
Loop
from above code, the process is working around this part:
Code:
For idx = 0 To data.Length - 1 'look for CR
If data(idx) = ControlChars.Cr Then
'note that the CR will NOT be in mess
foundMess = True 'found message
Exit For
End If
mess.Append(data(idx))
Next
what i understand is that there is CR in the incoming data. again it does not proceed to next level.
next one that make me wonder is this part:
Code:
If foundMess Then
data.Remove(0, idx + 1) 'remove found message from data
'
'process your message here <<<<<<<<<<<<
'how to interact with the UI
Me.Invoke(Sub()
RichTextBox1.AppendText(mess.ToString)
RichTextBox1.AppendText(ControlChars.Cr)
End Sub)
'end example
End If
here foundMess is False, but why we need to remove it from the data? sorry for many questions.
-
Aug 21st, 2020, 11:40 AM
#21
Re: look for the carriage return character
Are you saying that if you put a breakpoint after this
Code:
Do While SerialPort1.BytesToRead > 0 'accumulate all available bytes
data.Append(SerialPort1.ReadExisting)
Loop
you never hit it? At 9600 bps I find that hard to believe.
I don't know the protocol, I was taking your word that CR ends each message. If not you'll have to adapt the code. The code I posted assumed that what you said was what was in the data. The documentation you posted does say this, "The string is terminated by a carriage return. There will then be a short interval with no
data transmission before the next string begins."
If you run the code as I originally posted in #19 and there IS a CR terminating each message you should see every message in the richtextbox. That is what happens when I run the code on my machine with a device that outputs messages terminated by CR and my device is outputting data at 115200 bps with thousands of messages per second.
-
Aug 23rd, 2020, 11:23 PM
#22
Thread Starter
Junior Member
Re: look for the carriage return character
Originally Posted by dbasnett
Are you saying that if you put a breakpoint after this
Code:
Do While SerialPort1.BytesToRead > 0 'accumulate all available bytes
data.Append(SerialPort1.ReadExisting)
Loop
you never hit it? At 9600 bps I find that hard to believe.
I don't know the protocol, I was taking your word that CR ends each message. If not you'll have to adapt the code. The code I posted assumed that what you said was what was in the data. The documentation you posted does say this, "The string is terminated by a carriage return. There will then be a short interval with no
data transmission before the next string begins."
If you run the code as I originally posted in #19 and there IS a CR terminating each message you should see every message in the richtextbox. That is what happens when I run the code on my machine with a device that outputs messages terminated by CR and my device is outputting data at 115200 bps with thousands of messages per second.
truely sorry, it was a silly mistake, i tested with different data that has no CR. now the code works perfectly.
only one problem i faced when i tried to add the code to my other program, it gave me this error:
'Run' is not a member of 'Task' from this part:
Code:
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
ReadSerialPortTask = Task.Run(Sub() ReadSerialPort())
Timer1.Enabled = False
comPORT = ""
For Each sp As String In My.Computer.Ports.SerialPortNames
comPort_ComboBox.Items.Add(sp)
Next
End Sub
i have added this : Imports System.Threading.Tasks
but still get the error
-
Aug 24th, 2020, 05:41 AM
#23
Re: look for the carriage return character
hello,
do you have
Code:
Private ReadSerialPortTask As task
somewhere ? I think you forgot to declare the variable
The best friend of any programmer is a search engine
"Don't wish it was easier, wish you were better. Don't wish for less problems, wish for more skills. Don't wish for less challenges, wish for more wisdom" (J. Rohn)
“They did not know it was impossible so they did it” (Mark Twain)
-
Aug 24th, 2020, 06:50 AM
#24
Thread Starter
Junior Member
Re: look for the carriage return character
Originally Posted by Delaney
hello,
do you have
Code:
Private ReadSerialPortTask As task
somewhere ? I think you forgot to declare the variable
original code posted by Mr. dbasnett is working fine without needed any declaration.
just to let everyone know, i'm trying to embed the code in the basic platform known as AdvancedHMI (open source) provided from this website:
https://www.advancedhmi.com/forum/in...p?topic=2698.0
i can't upload the file here because it's quite big around 36MB. but overall code is like this:
Code:
Imports System
Imports System.ComponentModel
Imports System.Threading.Tasks
Imports System.IO.Ports
Imports System.Threading
Public Class MainForm
'*******************************************************************************
'* Stop polling when the form is not visible in order to reduce communications
'* Copy this section of code to every new form created
'*******************************************************************************
Private NotFirstShow As Boolean
Private Sub Form_VisibleChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.VisibleChanged
'* Do not start comms on first show in case it was set to disable in design mode
If NotFirstShow Then
AdvancedHMIDrivers.Utilities.StopComsOnHidden(components, Me)
Else
NotFirstShow = True
End If
End Sub
'***************************************************************
'* .NET does not close hidden forms, so do it here
'* to make sure forms are disposed and drivers close
'***************************************************************
Private Sub MainForm_FormClosing(sender As Object, e As FormClosingEventArgs) Handles MyBase.FormClosing
Dim index As Integer
While index < My.Application.OpenForms.Count
If My.Application.OpenForms(index) Is Me Then
'* Do not force close this form
index += 1
Else
My.Application.OpenForms(index).Close()
End If
End While
End Sub
Dim comPORT As String
Private Sub MainForm_Load(sender As Object, e As EventArgs) Handles MyBase.Load
ReadSerialPortTask = Task.Run(Sub() ReadSerialPort())
Timer1.Enabled = False
comPORT = ""
For Each sp As String In My.Computer.Ports.SerialPortNames
comPort_ComboBox.Items.Add(sp)
Next
End Sub
Private Sub comPort_ComboBox_SelectedIndexChanged(ByVal sender As Object, ByVal e As EventArgs) Handles comPort_ComboBox.SelectedIndexChanged
If (comPort_ComboBox.SelectedItem.ToString <> "") Then
comPORT = comPort_ComboBox.SelectedItem.ToString
End If
End Sub
Private Sub connect_BTN_Click(ByVal sender As Object, ByVal e As EventArgs) Handles connect_BTN.Click
If (connect_BTN.Text = "Connect") Then
If (comPORT <> "") Then
SerialPort1.Close()
SerialPort1.PortName = comPORT
SerialPort1.BaudRate = 9600
SerialPort1.DataBits = 8
SerialPort1.Parity = Parity.None
SerialPort1.StopBits = StopBits.One
SerialPort1.Handshake = Handshake.None
SerialPort1.Encoding = System.Text.Encoding.Default
SerialPort1.ReadTimeout = 1000 ' 10000
SerialPort1.Open()
SerialPort1.DtrEnable = True
connect_BTN.Text = "Dis-connect"
Timer1.Enabled = True
Timer_LBL.Text = "Timer: ON"
Else
MsgBox("Select a COM port first")
End If
Else
SerialPort1.Close()
connect_BTN.Text = "Connect"
Timer1.Enabled = False
Timer_LBL.Text = "Timer: OFF"
End If
End Sub
Private Sub clear_BTN_Click(ByVal sender As Object, ByVal e As EventArgs) Handles clear_BTN.Click
RichTextBox1.Text = ""
End Sub
Private ReadSerialPortTask As Task
Private Sub SerialPort1_DataReceived(sender As Object, e As IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
'this is it
ReadWait.Set() 'cause ReadSerialPort to run
End Sub
Private ReadWait As New Threading.AutoResetEvent(False)
Private Sub ReadSerialPort()
'
'this is run as a Background task
'
Dim data As New System.Text.StringBuilder(1024 * 1024) 'accumulate SerialPort data here
Dim mess As New System.Text.StringBuilder 'individual message
Dim foundMess As Boolean = False
Do
ReadWait.WaitOne() 'wait for SerialPort1.DataReceived
Do While SerialPort1.BytesToRead > 0 'accumulate all available bytes
data.Append(SerialPort1.ReadExisting)
Loop
Do 'process message, if one available
mess.Length = 0 'reset message
foundMess = False 'not found
Dim idx As Integer = 0
For idx = 0 To data.Length - 1 'look for CR
If data(idx) = ControlChars.Cr Then
'note that the CR will NOT be in mess
foundMess = True 'found message
Exit For
End If
mess.Append(data(idx))
Next
If foundMess Then
data.Remove(0, idx + 1) 'remove found message from data
'process your message here <<<<<<<<<<<<
'how to interact with the UI
Me.Invoke(Sub()
RichTextBox1.AppendText(mess.ToString)
RichTextBox1.AppendText(ControlChars.Cr)
RichTextBox2.Text = (mess.ToString)
Try
'SIMPLE SPLIT DATA CODE
Dim s As String
s = RichTextBox2.Text
Dim somestring() As String
'split based on comma
somestring = s.Split(New Char() {" "c})
TextBox1.Text = somestring(0)
TextBox2.Text = somestring(1)
TextBox3.Text = somestring(2)
TextBox4.Text = somestring(3)
TextBox5.Text = somestring(4)
TextBox6.Text = somestring(5)
TextBox7.Text = somestring(6)
TextBox8.Text = somestring(7)
Catch exc As Exception
End Try
End Sub)
'end example
End If
'look for more messages in data?
Loop While foundMess AndAlso data.Length > 0
Loop
End Sub
'SERIAL PORT 1 DATA LOGGING
Private Sub ExitBtn_Click(sender As Object, e As EventArgs) Handles ExitBtn.Click
End
End Sub
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
If SerialPort1.IsOpen Then
Try
Button1.Text = TextBox1.Text
Button2.Text = TextBox2.Text
Button3.Text = TextBox3.Text
HeadingIndicatorInstrumentControl1.Heading = TextBox1.Text
AttitudeIndicatorInstrumentControl1.PitchAngle = TextBox2.Text
AttitudeIndicatorInstrumentControl1.RollAngle = TextBox3.Text
Catch ex As Exception
End Try
End If
If Log_button1.BackColor = Color.LimeGreen Then
Dim writeFile As New System.IO.StreamWriter("Logdata1.txt", IO.FileMode.Append)
writeFile.Write(TimeOfDay.ToLongTimeString + " : " + vbNewLine + Text)
writeFile.Close()
End If
End Sub
Private Sub Log_button1_Click(sender As Object, e As EventArgs) Handles Log_button1.Click
Log_button1.BackColor = Color.LimeGreen
StopLog_button1.BackColor = Color.Transparent
StopLog_button1.Enabled = True
End Sub
'STOP LOGGING SERIAL PORT 1
Private Sub StopLog_button1_Click(sender As Object, e As EventArgs) Handles StopLog_button1.Click
StopLog_button1.BackColor = Color.Red
Log_button1.BackColor = Color.Transparent
Log_button1.Enabled = True
End Sub
End Class
-
Aug 24th, 2020, 07:43 AM
#25
Re: look for the carriage return character
the original code has the declaration...
Originally Posted by dbasnett
Code:
Private ReadSerialPortTask As task
Private Sub Form1_Shown(sender As Object, e As EventArgs) Handles Me.Shown
'start the worker task <<<<<<<<<<<<!!!!!
'this could be in the load event also
ReadSerialPortTask = Task.Run(Sub() ReadSerialPort())
End Sub
.....
and by the way, you also have it...
Originally Posted by Zumbie
Code:
Imports System
Imports System.ComponentModel
Imports System.Threading.Tasks
Imports System.IO.Ports
Imports System.Threading
Public Class MainForm
'*******************************************************************************
'* Stop polling when the form is not visible in order to reduce communications
'* Copy this section of code to every new form created
'*******************************************************************************
............
Dim comPORT As String
Private Sub MainForm_Load(sender As Object, e As EventArgs) Handles MyBase.Load
ReadSerialPortTask = Task.Run(Sub() ReadSerialPort())
Timer1.Enabled = False
comPORT = ""
For Each sp As String In My.Computer.Ports.SerialPortNames
comPort_ComboBox.Items.Add(sp)
Next
End Sub
......
Private ReadSerialPortTask As Task
Private Sub SerialPort1_DataReceived(sender As Object, e As IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
'this is it
ReadWait.Set() 'cause ReadSerialPort to run
End Sub
if you have done a copy/paste you may have forgotten it
Last edited by Delaney; Aug 24th, 2020 at 07:49 AM.
The best friend of any programmer is a search engine
"Don't wish it was easier, wish you were better. Don't wish for less problems, wish for more skills. Don't wish for less challenges, wish for more wisdom" (J. Rohn)
“They did not know it was impossible so they did it” (Mark Twain)
-
Aug 24th, 2020, 09:01 AM
#26
Thread Starter
Junior Member
Re: look for the carriage return character
Originally Posted by Delaney
the original code has the declaration...
and by the way, you also have it...
if you have done a copy/paste you may have forgotten it
That exactly the code i used. No missing declaration.
-
Aug 24th, 2020, 09:11 AM
#27
Re: look for the carriage return character
Originally Posted by Zumbie
truely sorry, it was a silly mistake, i tested with different data that has no CR. now the code works perfectly.
only one problem i faced when i tried to add the code to my other program, it gave me this error:
'Run' is not a member of 'Task' from this part:
Code:
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
ReadSerialPortTask = Task.Run(Sub() ReadSerialPort())
Timer1.Enabled = False
comPORT = ""
For Each sp As String In My.Computer.Ports.SerialPortNames
comPort_ComboBox.Items.Add(sp)
Next
End Sub
i have added this : Imports System.Threading.Tasks
but still get the error
Have you resolved this? If not what version of .Net are you running on the machine with the error?
-
Aug 24th, 2020, 11:20 AM
#28
Re: look for the carriage return character
Hum that's right, I forgot that possibility. Task.run is available from framework 4.5
The best friend of any programmer is a search engine
"Don't wish it was easier, wish you were better. Don't wish for less problems, wish for more skills. Don't wish for less challenges, wish for more wisdom" (J. Rohn)
“They did not know it was impossible so they did it” (Mark Twain)
-
Aug 24th, 2020, 11:50 AM
#29
Re: look for the carriage return character
Here is a version that should work on the other system, changed Task to Thread.
Code:
Imports System
Imports System.IO.Ports
Public Class Form1
Dim comPORT As String
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
ReadSerialPortThread = New Threading.Thread(AddressOf ReadSerialPort)
ReadSerialPortThread.IsBackground = True
ReadSerialPortThread.Start()
Timer1.Enabled = False
comPORT = ""
For Each sp As String In My.Computer.Ports.SerialPortNames
comPort_ComboBox.Items.Add(sp)
Next
End Sub
Private Sub comPort_ComboBox_SelectedIndexChanged(ByVal sender As Object, ByVal e As EventArgs) Handles comPort_ComboBox.SelectedIndexChanged
If (comPort_ComboBox.SelectedItem.ToString <> "") Then
comPORT = comPort_ComboBox.SelectedItem.ToString
End If
End Sub
Private Sub connect_BTN_Click(ByVal sender As Object, ByVal e As EventArgs) Handles connect_BTN.Click
If (connect_BTN.Text = "Connect") Then
If (comPORT <> "") Then
SerialPort1.Close()
SerialPort1.PortName = comPORT
SerialPort1.BaudRate = 9600
SerialPort1.DataBits = 8
SerialPort1.Parity = Parity.None
SerialPort1.StopBits = StopBits.One
SerialPort1.Handshake = Handshake.None
SerialPort1.Encoding = System.Text.Encoding.Default
SerialPort1.ReadTimeout = 1000 ' 10000
SerialPort1.Open()
SerialPort1.DtrEnable = True
connect_BTN.Text = "Dis-connect"
Timer1.Enabled = True
Timer_LBL.Text = "Timer: ON"
Else
MsgBox("Select a COM port first")
End If
Else
SerialPort1.Close()
connect_BTN.Text = "Connect"
Timer1.Enabled = False
Timer_LBL.Text = "Timer: OFF"
End If
End Sub
Private Sub clear_BTN_Click(ByVal sender As Object, ByVal e As EventArgs) Handles clear_BTN.Click
RichTextBox1.Text = ""
End Sub
Private ReadSerialPortThread As Threading.Thread
Private Sub SerialPort1_DataReceived(sender As Object,
e As IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
'this is it
ReadWait.Set() 'cause ReadSerialPort to run
End Sub
Private ReadWait As New Threading.AutoResetEvent(False)
Private Sub ReadSerialPort()
'
'this is run as a Background task
'
Dim data As New System.Text.StringBuilder(1024 * 1024) 'accumulate SerialPort data here
Dim mess As New System.Text.StringBuilder 'individual message
Dim foundMess As Boolean = False
Do
ReadWait.WaitOne() 'wait for SerialPort1.DataReceived
Do While SerialPort1.BytesToRead > 0 'accumulate all available bytes
data.Append(SerialPort1.ReadExisting)
Loop
Do 'process message, if one available
mess.Length = 0 'reset message
foundMess = False 'not found
Dim idx As Integer = 0
For idx = 0 To data.Length - 1 'look for CR
If data(idx) = ControlChars.Cr Then
'note that the CR will NOT be in mess
foundMess = True 'found message
Exit For
End If
mess.Append(data(idx))
Next
If foundMess Then
data.Remove(0, idx + 1) 'remove found message from data
'
'process your message here <<<<<<<<<<<<
'how to interact with the UI
Me.Invoke(Sub()
RichTextBox1.AppendText(mess.ToString)
RichTextBox1.AppendText(ControlChars.Cr)
End Sub)
'end example
End If
'look for more messages in data?
Loop While foundMess AndAlso data.Length > 0
Loop
End Sub
End Class
-
Aug 24th, 2020, 08:28 PM
#30
Thread Starter
Junior Member
Re: look for the carriage return character
Originally Posted by dbasnett
Here is a version that should work on the other system, changed Task to Thread.
Code:
Imports System
Imports System.IO.Ports
Public Class Form1
Dim comPORT As String
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
ReadSerialPortThread = New Threading.Thread(AddressOf ReadSerialPort)
ReadSerialPortThread.IsBackground = True
ReadSerialPortThread.Start()
Timer1.Enabled = False
comPORT = ""
For Each sp As String In My.Computer.Ports.SerialPortNames
comPort_ComboBox.Items.Add(sp)
Next
End Sub
Private Sub comPort_ComboBox_SelectedIndexChanged(ByVal sender As Object, ByVal e As EventArgs) Handles comPort_ComboBox.SelectedIndexChanged
If (comPort_ComboBox.SelectedItem.ToString <> "") Then
comPORT = comPort_ComboBox.SelectedItem.ToString
End If
End Sub
Private Sub connect_BTN_Click(ByVal sender As Object, ByVal e As EventArgs) Handles connect_BTN.Click
If (connect_BTN.Text = "Connect") Then
If (comPORT <> "") Then
SerialPort1.Close()
SerialPort1.PortName = comPORT
SerialPort1.BaudRate = 9600
SerialPort1.DataBits = 8
SerialPort1.Parity = Parity.None
SerialPort1.StopBits = StopBits.One
SerialPort1.Handshake = Handshake.None
SerialPort1.Encoding = System.Text.Encoding.Default
SerialPort1.ReadTimeout = 1000 ' 10000
SerialPort1.Open()
SerialPort1.DtrEnable = True
connect_BTN.Text = "Dis-connect"
Timer1.Enabled = True
Timer_LBL.Text = "Timer: ON"
Else
MsgBox("Select a COM port first")
End If
Else
SerialPort1.Close()
connect_BTN.Text = "Connect"
Timer1.Enabled = False
Timer_LBL.Text = "Timer: OFF"
End If
End Sub
Private Sub clear_BTN_Click(ByVal sender As Object, ByVal e As EventArgs) Handles clear_BTN.Click
RichTextBox1.Text = ""
End Sub
Private ReadSerialPortThread As Threading.Thread
Private Sub SerialPort1_DataReceived(sender As Object,
e As IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
'this is it
ReadWait.Set() 'cause ReadSerialPort to run
End Sub
Private ReadWait As New Threading.AutoResetEvent(False)
Private Sub ReadSerialPort()
'
'this is run as a Background task
'
Dim data As New System.Text.StringBuilder(1024 * 1024) 'accumulate SerialPort data here
Dim mess As New System.Text.StringBuilder 'individual message
Dim foundMess As Boolean = False
Do
ReadWait.WaitOne() 'wait for SerialPort1.DataReceived
Do While SerialPort1.BytesToRead > 0 'accumulate all available bytes
data.Append(SerialPort1.ReadExisting)
Loop
Do 'process message, if one available
mess.Length = 0 'reset message
foundMess = False 'not found
Dim idx As Integer = 0
For idx = 0 To data.Length - 1 'look for CR
If data(idx) = ControlChars.Cr Then
'note that the CR will NOT be in mess
foundMess = True 'found message
Exit For
End If
mess.Append(data(idx))
Next
If foundMess Then
data.Remove(0, idx + 1) 'remove found message from data
'
'process your message here <<<<<<<<<<<<
'how to interact with the UI
Me.Invoke(Sub()
RichTextBox1.AppendText(mess.ToString)
RichTextBox1.AppendText(ControlChars.Cr)
End Sub)
'end example
End If
'look for more messages in data?
Loop While foundMess AndAlso data.Length > 0
Loop
End Sub
End Class
thanks a lot Mr.dbasnett. i got it fully working.
I will mark this thread as 'solved' now.
Last edited by Zumbie; Aug 25th, 2020 at 04:39 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
|