PORTS Forum
Ports and Interfaces => Serial Ports => Topic started by: yvytty on April 24, 2013, 02:42:53 pm
-
I am new to coding. I have been asked to write a program to send/receive data through a serial port from host/slave. This is my current working test code. I created two ports and used a virtual port emulator.
As this is my first paying job, I am wondering if I could have some critical feedback on this.
I have purchased several of your books. I really appreciate your help. Thanks.
I've taken out any code not directly related to the ports.
Imports System.IO.Ports
Class form1
'==set and open port==
'==not using get portname- COM1 to be used as dedicated port as spec==
Private Sub btnReSet_Click(sender As Object, e As EventArgs) Handles btnReSet.Click
If SerialPort1.IsOpen = False Then
'==Open and set COM1 as host==
Try
'==Set COM1 as portname==
SerialPort1.PortName = "COM1"
'==Port settings==
SerialPort1.BaudRate = 9600
SerialPort1.Parity = Parity.None
SerialPort1.StopBits = StopBits.One
SerialPort1.DataBits = 8
SerialPort1.ReadTimeout = 100
'==Open port==
SerialPort1.Open()
rtbCom1.Text = "COM1 Ready"
tmrPoll.Start()
Catch ex As Exception
rtbCom1.Text = "open error " & ex.Message
End Try
End If
'==Used to test data send/rec==
If SerialPort2.IsOpen = False Then
Try
SerialPort2.PortName = "COM2"
SerialPort2.BaudRate = 9600
SerialPort2.Parity = Parity.None
SerialPort2.StopBits = StopBits.One
SerialPort2.DataBits = 8
SerialPort2.Open()
rtbCom2.Text = "COM2 Open"
Catch ex As Exception
rtbCom2.Text = "open error " & ex.Message
End Try
End If
End Sub
'==CONTROL CHARACTERS- as spec==
'==start and stop values==
Dim STX As Byte = &H2
Dim ETX As Byte = &H3
'==Acknowledgment==
Dim ACK As Byte = &H6
'==class and address==
Dim DeviceClass As String = "E"
Dim DeviceAddress As String = "1"
'==Command to read==
Dim DeviceRead As String = "R"
'==Command to Write==
Dim DeviceWrite As String = "W"
'==[[[stx(start), device class, device address, device command, register register (REG), device data(D1 D0), etx(end)]]]==
'==array of register values, i=index==
'==note for self==='hex15='NAK!==
Dim REG = New String() {"22", "23", "2F", "30"}
'==FOR ME!!test data==
Dim D1 = New Integer() {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
Dim D0 = New Integer() {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
'==data to send==
Dim portWrite As String
'==data to write==
Dim portRead As String
Private Sub tmrPoll_Tick(sender As Object, e As EventArgs) Handles tmrPoll.Tick
'==FOR ME!!loop counter for testing==
Dim i As Integer = 0
'==timeout error counter==
Dim j As Integer = 0
'==Prevent unnecessary timeout errors/allow time lag for port to open==
Do While SerialPort1.IsOpen = True And SerialPort2.IsOpen = True
'==Loop through Register==
For Each r In REG
Dim portWrite As String = (STX & DeviceClass & DeviceAddress & ACK & r & i & i & ETX)
Try
'==Loop Host Commands for Register==
SerialPort1.WriteLine(portWrite & vbCr)
'==Time for DataReceived Event Handlers to execute==
lst1.Items.Add(STX & DeviceClass & DeviceAddress & ACK & r & i & i & ETX & vbCr)
Catch ex As Exception
rtbCom1.Text = "Write Error: " & ex.Message
End Try
Try
'==readline to separate data==
portRead = SerialPort2.ReadLine()
'==display data in GUI==
lst2.Items.Add(portRead)
'==Get Register Value==
Dim r1 As String
'==Slave data values==
Dim d As Integer
'==[[[STX & DeviceClass & DeviceAddress & ACK & REG1 & REG0 (REG) & D0 & D1 & ETX]]]==
'==2-E-1-6-r-r-X-X-3==
'==Get the Data Value for Individual Register==
r1 = portRead.Substring(4, 2)
'==convert data to integer, so data can be displayed graphically==
d = CInt(portRead.Substring(6, 2))
'==Display received substring values==
Select Case r1
Case Is = "22"
'list box until advised.
lst1.Items.Add(r1 & d)
Case Is = "23"
'==display data as shape==
shpTemp.Width = d * 2
Case Is = "2F"
shpAmp.Width = d
Case Is = "30"
shpVolt.Width = d * 3
End Select
Catch ex As Exception
lst2.Items.Add("Read error: " & ex.Message)
End Try
If j > 2 Then
rtbCom2.Text = "Operation Aborted: 3 timeout errors."
'==Stop program if 3 timeout errors- as spec/closed port should terminate Do while==
SerialPort1.Close()
rtbCom1.Text = "port closed - Operation Aborted: 3 timeout errors."
' shpAmp.Width = -1
shpTemp.Width = -1
shpVolt.Width = -1
tmrPoll.Stop()
Exit Do
End If
Next
i += 1
If i > 9 Then
i = 0
End If
Loop
End Sub
End Class
-
Actually, I my timeout count loop is not working.. just tested it using
Dim portWrite As String = (STX & DeviceClass & DeviceAddress & ACK & r & i & i) ' & ETX)
Try
'==Loop Host Commands for Register==
SerialPort1.Write(portWrite) ' & vbCr)
-
oh I'm so stupid, forgot to add j+=1 !!
-
If the application is doing what you intended, you've done the hard part!
If your edition of Visual Studio supports it, you can do Build > Run Code Analysis on Solution.
-
Thanks Jan.. I did and no problem.. I'm just scared, as I can only test it on a virtual port emulator ..
-
If you lack serial ports, use two USB/serial converters and a null-modem connector.
-
thanks
-
Hi again,
What is the best way to display the data more frequently?
Cheers,
Yvette
-
Add a handler that executes on a DataReceived event. See my COM port terminal example:
http://www.lvr.com/serport.htm#my_example_code
-
Thanks Jan,
Yes, I like that code and have seen it before (I've read some of your books :-)
What I am wondering though.. is I experimented and using writieline/readline it seemed to display the data more regularly, as did playing with the loops.. Is there another way of pacing how frequently the data is read and displayed? Otherwise, what is the point of polling?
Please bear with me, I'm a beginner and trying to fully understand these things.
Cheers,
Yvette
-
I'm not sure what you're asking. You can use events or you can attempt to read periodically. Which read method you use will determine whether returning data requires a LF/CR. You can also set the minimum number of bytes/characters to read. See the SerialPort class documentation for more info.
-
I'm using the code I posted above, so it's with a timer.. which is why I was confused by your answer.
It just doesn't seem to update the display (data received) as frequently as it should. If you look at my code, you may know why...
-
ReadLine won't return data until receiving a line termination. Other than that, try to isolate the problem by (1) defining it: how frequently do you expect the display to update and how frequently is it being updated? and (2) sending test data and monitoring what's received and displayed, etc.
-
If I have built in line terminations, that should be ok? is CR considered a line termination for readline (pardon my ignorance- I just want to be sure) I will take the steps you suggested.
-
See the environment.newline property.
-
Thanks for your help Jan, I altered my test data and it's working fine.