' Arduino and Visual Basic Part 3: Send and receive serial data between an Arduino and Visual Basic ' A simple example of recieving and sending serial data between an Arduino and Visual Basic ' https://www.martyncurrey.com/arduino-and-visual-basic-part-3 ' Imports System Imports System.IO.Ports Imports System.Windows.Forms.VisualStyles.VisualStyleElement Public Class Form1 ' Global variables. ' Anything defined here is available in the whole app Dim selected_COM_PORT As String Dim receivedData As String = "" Dim commandCount As Integer = 0 ' This called when the app first starts. Used to initial what ever needs initialising. Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load Timer1.Enabled = False selected_COM_PORT = "" For Each sp As String In My.Computer.Ports.SerialPortNames comPort_ComboBox.Items.Add(sp) Next TimerSpeed_value_lbl.Text = Timer1.Interval AppControlButtonOff() turnAppControllOff() End Sub Private Sub MainForm_FormClosing(sender As Object, e As FormClosingEventArgs) Handles MyBase.FormClosing If (SerialPort1.IsOpen) Then Try SerialPort1.Close() Catch ex As Exception MessageBox.Show("Serial Port is already closed!") End Try End If End Sub ' When the value of the COM PORT drop doewn list changes, ' copy the new value to the comPORT variable. Private Sub comPort_ComboBox_SelectedIndexChanged(sender As Object, e As EventArgs) Handles comPort_ComboBox.SelectedIndexChanged If (comPort_ComboBox.SelectedItem <> "") Then selected_COM_PORT = comPort_ComboBox.SelectedItem End If End Sub ' Try to open the com port or close the port if already open ' Note: There is no error catching. If the connection attampt fails the app will crash! Private Sub connect_BTN_Click(sender As Object, e As EventArgs) Handles connect_BTN.Click If (connect_BTN.Text = "CONNECT") Then If (selected_COM_PORT <> "") Then ' Try allows me to trap an errors such as the COM port not being available ' Without it the app crashes. Try SerialPort1.PortName = selected_COM_PORT SerialPort1.BaudRate = 115200 SerialPort1.DataBits = 8 SerialPort1.Parity = Parity.None SerialPort1.StopBits = StopBits.One SerialPort1.DtrEnable = True SerialPort1.RtsEnable = True SerialPort1.Handshake = Handshake.None SerialPort1.Encoding = System.Text.Encoding.Default 'very important! SerialPort1.ReadTimeout = 10000 SerialPort1.Open() Catch ex As Exception MessageBox.Show(ex.Message + vbCrLf + "Looks like something else is using it.", "Error opening the serial port", MessageBoxButtons.OK, MessageBoxIcon.Error) End Try Else MsgBox("No COM port selected!") End If Else Try SerialPort1.Close() Catch ex As Exception MessageBox.Show("Serial Port is already closed!") End Try End If checkSerialPortandUpdateScreen() End Sub Private Sub checkSerialPortandUpdateScreen() If (SerialPort1.IsOpen) = True Then connect_BTN.Text = "DIS-CONNECT" Timer1.Enabled = True timer_LBL.Text = "TIMER: ON" AppControlButtonOn() Else connect_BTN.Text = "CONNECT" Timer1.Enabled = False timer_LBL.Text = "TIMER: OFF" AppControlButtonOff() End If End Sub Private Sub AppControlButtonOn() CONTROL_BTN.Enabled = True End Sub Private Sub AppControlButtonOff() CONTROL_BTN.Enabled = False End Sub ' Process received data. Append the data to the text box Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick 'stop the timer (stops this function being called while it is still working Timer1.Enabled = False timer_LBL.Text = "TIMER: OFF" If (SerialPort1.IsOpen) Then ' get any new data and add the the global variable receivedData receivedData = receivedData + ReceiveSerialData() If (receivedData <> "") Then debug("RD = " & receivedData, 0) 'If receivedData contains a "<" and a ">" then we have data If ((receivedData.Contains("<") And receivedData.Contains(">"))) Then parseData() End If End If ' restart the timer Timer1.Enabled = True timer_LBL.Text = "TIMER: ON" Else checkSerialPortandUpdateScreen() End If End Sub ' Check for new data Function ReceiveSerialData() As String Dim returnData As String = "" Dim Incoming As String = "" If (SerialPort1.IsOpen) Then Try Incoming = SerialPort1.ReadExisting() If Incoming IsNot Nothing Then returnData = Incoming End If Catch ex As TimeoutException Return "Error: Serial Port read timed out." returnData = "" End Try End If Return returnData End Function Function parseData() ' uses the global variable receivedData Dim pos1 As Integer Dim pos2 As Integer Dim length As Integer Dim newCommand As String Dim done As Boolean = False Dim validCommand As Boolean = False While (Not done) pos1 = receivedData.IndexOf("<") + 1 pos2 = receivedData.IndexOf(">") + 1 'occasionally we may not get a complete data packet and the end marker could be in front of the start marker ' for exampe "55><" ' if pos2 < pos1 then remove the first part of the string from receivedData If (pos2 < pos1) Then receivedData = Microsoft.VisualBasic.Mid(receivedData, pos2 + 1) pos1 = receivedData.IndexOf("<") + 1 pos2 = receivedData.IndexOf(">") + 1 End If If (pos1 = 0 Or pos2 = 0) Then ' we do not have both start and end markers and we are done done = True Else ' we have both start and end markers length = pos2 - pos1 + 1 If (length > 0) Then 'remove the start and end markers from the command newCommand = Mid(receivedData, pos1 + 1, length - 2) ' show the command in the text box debug("CMD = " & newCommand, 2) 'remove the command from receivedData receivedData = Mid(receivedData, pos2 + 1) If (newCommand = "ARD_OFF") Then turnAppControllOn() validCommand = True ElseIf (newCommand = "ARD_ON") Then turnAppControllOff() validCommand = True End If ' are the first charatcers LB for LED Brightness? If (newCommand.Substring(0, 2) = "LB") Then Dim tempVal As Integer = Val(newCommand.Substring(2, 3)) ' tempVal = Int(tempVal / 4) debug("LED VAL = " & tempVal, 2) If (tempVal >= 0 And tempVal <= 255) Then SLIDER_VAL_LBL.Text = Format(tempVal, "000") SLIDER_trackBar.Value = Int(tempVal) End If validCommand = True End If commandCount = commandCount + 1 commandCountVal_lbl.Text = commandCount End If ' (length > 0) End If '(pos1 = 0 Or pos2 = 0) End While Return validCommand End Function ' Clear the text box Private Sub clear_BTN_Click(sender As Object, e As EventArgs) Handles clear_BTN.Click recData_RichTextBox.Text = "" commandCount = 0 commandCountVal_lbl.Text = commandCount End Sub Private Sub turnAppControllOn() CONTROL_BTN.Text = "APP CONTROL ON" CONTROL_BTN.BackColor = Color.Lime SLIDER_trackBar.Enabled = True End Sub Private Sub turnAppControllOff() CONTROL_BTN.Text = "APP CONTROL OFF" CONTROL_BTN.BackColor = Color.Tomato SLIDER_trackBar.Enabled = False End Sub Private Sub CONTROL_BTN_Click(sender As Object, e As EventArgs) Handles CONTROL_BTN.Click If (CONTROL_BTN.Text = "APP CONTROL OFF") Then turnAppControllOn() writeSerial("") Else turnAppControllOff() writeSerial("") End If End Sub Private Sub SLIDER_trackBar_Scroll(sender As Object, e As EventArgs) Handles SLIDER_trackBar.Scroll Dim tmpVal As String = Format(SLIDER_trackBar.Value, "000") SLIDER_VAL_LBL.Text = tmpVal writeSerial("") End Sub Private Sub writeSerial(data As String) If (SerialPort1.IsOpen) Then SerialPort1.WriteLine(data) debug(data, 1) End If End Sub Private Sub debug(data As String, Optional col As Integer = 0) If (col = 0) Then recData_RichTextBox.SelectionColor = Color.Black ElseIf (col = 1) Then recData_RichTextBox.SelectionColor = Color.Blue ElseIf (col = 2) Then recData_RichTextBox.SelectionColor = Color.Red End If recData_RichTextBox.AppendText(data & vbCrLf) recData_RichTextBox.SelectionStart = recData_RichTextBox.TextLength recData_RichTextBox.ScrollToCaret() End Sub End Class