|
-
Apr 17th, 2014, 12:06 PM
#1
Thread Starter
Member
[RESOLVED] VB 2010 Express - Serial port threading problem?
Running on Win 7. The situation is: I have a hardware device sitting on a serial port and it accepts a set of string commands and returns a response string to each command. As a base, I used a set of code I found on the Web that uses a delegate and separate thread and it works just fine up to a point. The requirement is to be able to poll the device up to every 200 ms. with two commands and send other commands less frequently. The device runs at 57,600 bps.
I can send one of the commands every 200ms and receive the responses perfectly and that will run OK for many minutes. If I then add a second command to the sequence and read its response, responses to the first command are received OK for a short while but responses to the second command are never received. These commands are sent and responses read in a timer tick event. So, the sequence would be: send command 1, read response, send command 2, read response. The code includes the ability to send the commands individually under button control and both commands work just fine.
When running in the timer mode, the commands are being sent and responses to both commands are being received OK but the received data isn't there for the second command. I think the problem lies with possible misunderstanding of the delegate and threading on my part. Any suggestions greatly appreciated. Here's the code:
Code:
Imports System
Imports System.ComponentModel
Imports System.Threading
Imports System.IO.Ports
Public Class frmMain
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 receiving of data
Dim interval As String
' The user can send a single ?AF or ?BF command with the SEND button. Or, he can send the commands repeatedly
' by pressing the TIMED SEND button. In that case, the tick event sends the ?AF, reads the response, and then
' sends the ?BF command and reads that response. The responses to ?AF and ?BF should update the text boxes
' labeled VFO A and VFO B with the values returned.
Private Sub frmMain_Load(sender As System.Object, 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
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
btnDisconnect.Enabled = False 'Initially Disconnect Button is Disabled
End Sub
Private Sub btnConnect_Click(sender As System.Object, e As System.EventArgs) Handles btnConnect.Click
SerialPort1.PortName = cmbPort.Text 'Set SerialPort1 to the selected COM port at startup
SerialPort1.Open()
btnConnect.Enabled = False 'Disable Connect button
btnDisconnect.Enabled = True 'and Enable Disconnect button
End Sub
Private Sub btnDisconnect_Click(sender As System.Object, e As System.EventArgs) Handles btnDisconnect.Click
SerialPort1.Close() 'Close our Serial Port
btnConnect.Enabled = True
btnDisconnect.Enabled = False
Me.Close()
End Sub
Private Sub btnSend_Click(sender As System.Object, 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)
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)
'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]
End If
End Sub
Private Sub cmbPort_SelectedIndexChanged(sender As System.Object, 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 Timer1_Tick(sender As System.Object, e As System.EventArgs) Handles tmrTimer1.Tick
Dim freq As String
'Each time tick occurs, we send a request to the Orion
SerialPort1.Write("?AF" & vbCr) 'Requests current value of VFO-A along with carriage return
'Response to the ?AF is a string like "@AF14236789 which will be displayed as: "14.236.789"
If Me.rtbReceived.Text.StartsWith("@AF") Then
freq = Mid(rtbReceived.Text, 4, 2) & "." & Mid(rtbReceived.Text, 6, 3) & "." & Mid(rtbReceived.Text, 9, 3)
freq = freq.TrimStart("0")
If freq.Length = 9 Then
txtVFOA.Text = " " & freq
Else
txtVFOA.Text = freq
End If
rtbReceived.Text = ""
End If
SerialPort1.Write("?BF" & vbCr) 'Requests current value of VFO-B along with carriage return
'Response to the ?BF is a string like "@BF14236789 which will be displayed as: "14.236.789"
If Me.rtbReceived.Text.StartsWith("@BF") Then
freq = Mid(rtbReceived.Text, 4, 2) & "." & Mid(rtbReceived.Text, 6, 3) & "." & Mid(rtbReceived.Text, 9, 3)
freq = freq.TrimStart("0")
If freq.Length = 9 Then
txtVFOB.Text = " " & freq
Else
txtVFOB.Text = freq
End If
rtbReceived.Text = ""
End If
End Sub
Private Sub btnTimerOn_Click(sender As System.Object, e As System.EventArgs) Handles btnTimerOn.Click
tmrTimer1.Enabled = True
tmrTimer1.Interval = CInt(cmbTimerInterval.Text)
End Sub
Private Sub btnStopTimedSend_Click(sender As System.Object, e As System.EventArgs) Handles btnStopTimedSend.Click
tmrTimer1.Enabled = False
End Sub
End Class
Tags for this Thread
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|