In un precedente post ho descritto la strategia che ho seguito per realizzare tramite Visual Basic un’applicazione in grado di mettere in comunicazione seriale Arduino e il computer, mimando l’invio di stringhe e caratteri già implementato nel Monitor seriale dell’IDE di Arduino. Il passo successivo è stato quello di far inviare i caratteri ad Arduino non più solo manualmente, inserendoli nell’apposita casella di testo, ma anche in base alla specifica pressione di un tasto sul controller dell’Xbox 360 collegato al pc da parte dell’utente. L’interfaccia del programma descritto nel post precedente, XBOX2ARDUINO, si è quindi allargata e modificata fino ad assumere questo aspetto:
In aggiunta alla parte di sinistra, già descritta in precedenza, è ora presente la parte di destra, deputata alla rilevazione del controller e della pressione di tasti specifici. Dalle caselle combinate in alto è possibile scegliere il periodo di tempo con cui il software aggiorna l’elenco dei comandi ricevuti (“RX refresh period”) e quello con cui rileva la pressione dei tasti sul controller ed invia conseguentemente caratteri ad Arduino (“TX/Controller refresh period”). Sono utilizzati due timer indipendenti per queste funzioni. Si può selezionare il controller di interesse – Windows supporta fino a 4 controller collegati contemporaneamente al pc – e verificare lo stato di tutti gli input sul controller, sia digitali (tasti LB, LS, PU, PL, PR, PD, BA, ST, RS, RB, X, Y, A, B) sia analogici (comandi LT, RT, LSX, LSY, RSX, RSY). Si può anche testare la vibrazione (output analogico), sia per il motore sinistro che per il destro (LV, RV), scegliendo la velocità relativa tramite slider. L’applicazione si può anche utilizzare, a prescindere da Arduino, come tool per testare la connessione al computer dei controller ed il funzionamento corretto di tutti i loro input ed output.
La mappatura degli input e degli output (ovvero l’associazione di specifici caratteri da trasmettere ad Arduino premendo determinati pulsanti sul controller o, al contrario, l’associazione di caratteri da ricevere da Arduino per controllare la vibrazione del controller) è gestita tramite i pulsanti “Map controller inputs” e “Map controller outputs”.
La mappatura degli input è divisa in input digitali e in input analogici. Nel primo caso, alla pressione di un tasto sul controller è associato l’invio ad Arduino del carattere designato nella casella di testo relativa. Nel secondo caso, quando una levetta di un input analogico viene portata in un determinato range di valori viene inviato uno specifico carattere ad Arduino. In particolare, gli assi dei due stick (LSX, LSY, RSX, RSY) inviano lettere quando portati abbastanza in basso/a sinistra (valori negativi) o abbastanza in alto/a destra (valori positivi), mentre i valori delle levette di throttle che inviano lettere sono medio e alto (sempre positivi). Quando gli input digitali non sono attivati o gli input analogici non sono sufficientemente al di fuori dalle posizioni di riposo, non vengono inviate lettere ad Arduino. L’invio dei comandi dal controller ad Arduino è gestito con la frequenza specificata in “TX/Controller refresh period”.
La finestra di mappatura output è simile, anche se sono ora presenti solo output analogici. In questo caso, si può scegliere da quale stringa inviata da Arduino far comandare la vibrazione del motore sinistro o di quello destro, entrambi a due differenti velocità liberamente scelte dall’utente con gli slider sottostanti. Per come è implementato il comando del controller in Visual Basic, una volta attivata la vibrazione è necessario inviare un altro comando a parte per farla cessare ed è quindi presente una casella di testo per definire anche la stringa di stop della vibrazione. È da notare che in XBOX2ARDUINO non è possibile attivare contemporaneamente i due motori del controller.
Il software è ovviamente migliorabile in vari modi: un’idea può essere quella di far inviare ad Arduino comandi solo in presenza di fronti positivi e negativi (i momenti in cui un pulsante viene premuto ed in cui viene rilasciato), così da ridurre il traffico di dati verso Arduino ed evitare di saturare in breve tempo la finestra dei messaggi ricevuti. Allo stato attuale, infatti, ad una pressione prolungata dei tasti è associato un continuo invio del messaggio relativo.
L’implementazione definitiva di XBOX2ARDUINO è ovviamente molto più lunga e complessa che allo stato del post precedente. Riporto qui il codice dei form e del modulo delle variabili globali per chiunque fosse interessato; sottolineo che il controller è gestito in Visual Basic utilizzando XNA Framework, che dev’essere quindi scaricato ed installato precedentemente in Visual Studio.
frmXBOX2ARDUINO:
' VB program to communicate with Arduino via serial interface ' Thanks to Martyn Currey for providing his tutorials: ' http://www.martyncurrey.com/arduino-and-visual-basic-part-1-receiving-data-from-the-arduino/ ' http://www.martyncurrey.com/arduino-and-visual-basic-part-3-controlling-an-arduino/ Imports System Imports System.IO.Ports Imports Microsoft.Xna.Framework.Input Public Class frmXBOX2ARDUINO Dim comPORT As String Dim receivedData As String = "" Dim connected As Boolean = False Dim selectedController As Microsoft.Xna.Framework.PlayerIndex Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load ' Initialize timer, comPORT value, and COM ports list timIO.Enabled = False timXBOX.Enabled = True comPORT = "" For Each sp As String In My.Computer.Ports.SerialPortNames cmbCOM.Items.Add(sp) Next cmbController.SelectedItem = "Player 1" cmbControllerRefreshTime.SelectedItem = "50 ms" cmbRXRefreshTime.SelectedItem = "1 s" End Sub Private Sub refresh_BTN_Click(sender As Object, e As EventArgs) Handles cmdRefresh.Click ' Refresh COM ports list after pressing Refresh button cmbCOM.Items.Clear() comPORT = "" For Each sp As String In My.Computer.Ports.SerialPortNames cmbCOM.Items.Add(sp) Next End Sub Private Sub comPort_ComboBox_SelectedIndexChanged(sender As Object, e As EventArgs) Handles cmbCOM.SelectedIndexChanged ' Updates comPORT value after changing selection in COM ports list If (cmbCOM.SelectedItem <> "") Then comPORT = cmbCOM.SelectedItem End If End Sub Private Sub connect_BTN_Click(sender As Object, e As EventArgs) Handles cmdConnect.Click If (cmdConnect.Text = "Connect") Then ' Opens connection with selected COM port If (comPORT <> "") Then spt1.Close() spt1.PortName = comPORT spt1.BaudRate = 9600 spt1.DataBits = 8 spt1.Parity = Parity.None spt1.StopBits = StopBits.One spt1.Handshake = Handshake.None spt1.Encoding = System.Text.Encoding.Default spt1.ReadTimeout = 10000 spt1.Open() cmdConnect.Text = "Disconnect" timIO.Enabled = True connected = True cmdSend.Enabled = True Else MsgBox("Select a COM port first.", vbExclamation) End If Else ' Closes connection with selected COM port spt1.Close() cmdConnect.Text = "Connect" timIO.Enabled = False connected = False cmdSend.Enabled = False End If End Sub Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles timIO.Tick ' Periodically updates received messages list Dim dateTimeIndication As String Dim receivedDataLength As Integer Dim dateTimeLength As Integer Dim startPos As Integer receivedData = ReceiveSerialData() receivedDataLength = receivedData.Length If receivedDataLength > 0 Then dateTimeIndication = DateTime.Now.ToString("MM/dd/yyyy HH:mm:ss") & ": " dateTimeLength = dateTimeIndication.Length startPos = rtbRX.TextLength rtbRX.AppendText(dateTimeIndication) rtbRX.Select(startPos, dateTimeLength) rtbRX.SelectionColor = Color.Red startPos = rtbRX.TextLength rtbRX.AppendText(receivedData) lblTest.Text = receivedData.Substring(0, 4) rtbRX.Select(startPos, receivedDataLength) rtbRX.SelectionColor = Color.Black End If If lblTest.Text = LeftMotorActivationWord1 Then GamePad.SetVibration(selectedController, LeftMotorSpeed1, 0) End If If lblTest.Text = LeftMotorActivationWord2 Then GamePad.SetVibration(selectedController, LeftMotorSpeed2, 0) End If If lblTest.Text = RightMotorActivationWord1 Then GamePad.SetVibration(selectedController, 0, RightMotorSpeed1) End If If lblTest.Text = RightMotorActivationWord2 Then GamePad.SetVibration(selectedController, 0, RightMotorSpeed2) End If If lblTest.Text = MotorDeactivationWord Then GamePad.SetVibration(selectedController, 0, 0) End If End Sub Function ReceiveSerialData() As String ' Reads strings from the connected Arduino Dim Incoming As String Try Incoming = spt1.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 send_BTN_Click(sender As Object, e As EventArgs) Handles cmdSend.Click ' Sends user-defined strings to Arduino If (connected) Then Dim tmp As String Dim dateTimeIndication As String Dim tmpLength As Integer Dim dateTimeLength As Integer Dim startPos As Integer dateTimeIndication = DateTime.Now.ToString("MM/dd/yyyy HH:mm:ss") & ": " dateTimeLength = dateTimeIndication.Length tmp = txtSend.Text tmpLength = tmp.Length spt1.WriteLine(tmp) tmp = tmp & vbCrLf startPos = rtbTX.TextLength rtbTX.AppendText(dateTimeIndication) rtbTX.Select(startPos, dateTimeLength) rtbTX.SelectionColor = Color.Blue startPos = rtbTX.TextLength rtbTX.AppendText(tmp) rtbTX.Select(startPos, tmpLength) rtbTX.SelectionColor = Color.Black End If End Sub Private Sub clear_BTN_Click(sender As Object, e As EventArgs) Handles cmdClearRX.Click ' Clears RX messages list rtbRX.Text = "" End Sub Private Sub clear_BTN2_Click(sender As Object, e As EventArgs) Handles cmdClearTX.Click ' Clears TX messages list rtbTX.Text = "" End Sub Private Sub RichTextBox1_TextChanged(sender As Object, e As EventArgs) Handles rtbRX.TextChanged ' Sets the current caret position to the end rtbRX.SelectionStart = rtbRX.TextLength ' Scrolls RichTextBox automatically rtbRX.ScrollToCaret() End Sub Private Sub RichTextBox2_TextChanged(sender As Object, e As EventArgs) Handles rtbTX.TextChanged ' Sets the current caret position to the end rtbTX.SelectionStart = rtbTX.TextLength ' Scrolls RichTextBox automatically rtbTX.ScrollToCaret() End Sub Private Sub Timer2_Tick(sender As Object, e As EventArgs) Handles timXBOX.Tick ' Periodically updates connection state of the selected Xbox 360 controller Dim LT As Single Dim RT As Single Dim LSX As Single Dim RSX As Single Dim LSY As Single Dim RSY As Single Select Case cmbController.SelectedItem Case "Player 1" selectedController = Microsoft.Xna.Framework.PlayerIndex.One picController.Image = pic1.Image Case "Player 2" selectedController = Microsoft.Xna.Framework.PlayerIndex.Two picController.Image = pic2.Image Case "Player 3" selectedController = Microsoft.Xna.Framework.PlayerIndex.Three picController.Image = pic3.Image Case "Player 4" selectedController = Microsoft.Xna.Framework.PlayerIndex.Four picController.Image = pic4.Image End Select LT = GamePad.GetState(selectedController).Triggers.Left RT = GamePad.GetState(selectedController).Triggers.Right RSX = GamePad.GetState(selectedController).ThumbSticks.Right.X RSY = GamePad.GetState(selectedController).ThumbSticks.Right.Y LSY = GamePad.GetState(selectedController).ThumbSticks.Left.Y LSX = GamePad.GetState(selectedController).ThumbSticks.Left.X chkDetected.Checked = GamePad.GetState(selectedController).IsConnected chkX.Checked = GamePad.GetState(selectedController).Buttons.X chkY.Checked = GamePad.GetState(selectedController).Buttons.Y chkA.Checked = GamePad.GetState(selectedController).Buttons.A chkB.Checked = GamePad.GetState(selectedController).Buttons.B chkLB.Checked = GamePad.GetState(selectedController).Buttons.LeftShoulder chkRB.Checked = GamePad.GetState(selectedController).Buttons.RightShoulder lblLT.Text = String.Concat("LT: ", LT) lblRT.Text = String.Concat("RT: ", RT) chkRS.Checked = GamePad.GetState(selectedController).Buttons.RightStick chkLS.Checked = GamePad.GetState(selectedController).Buttons.LeftStick chkST.Checked = GamePad.GetState(selectedController).Buttons.Start chkBA.Checked = GamePad.GetState(selectedController).Buttons.Back chkPD.Checked = GamePad.GetState(selectedController).DPad.Down chkPU.Checked = GamePad.GetState(selectedController).DPad.Up chkPL.Checked = GamePad.GetState(selectedController).DPad.Left chkPR.Checked = GamePad.GetState(selectedController).DPad.Right lblRSY.Text = String.Concat("RSY: ", RSY) lblRSX.Text = String.Concat("RSX: ", RSX) lblLSY.Text = String.Concat("LSY: ", LSY) lblLSX.Text = String.Concat("LSX: ", LSX) ' Sends character to Arduino when activating mapped inputs If A_char <> Chr(0) And chkA.Checked = True And timIO.Enabled = True Then sendCharacter(A_char) End If If B_char <> Chr(0) And chkB.Checked = True And timIO.Enabled = True Then sendCharacter(B_char) End If If X_char <> Chr(0) And chkX.Checked = True And timIO.Enabled = True Then sendCharacter(X_char) End If If Y_char <> Chr(0) And chkY.Checked = True And timIO.Enabled = True Then sendCharacter(Y_char) End If If LB_char <> Chr(0) And chkLB.Checked = True And timIO.Enabled = True Then sendCharacter(LB_char) End If If RB_char <> Chr(0) And chkRB.Checked = True And timIO.Enabled = True Then sendCharacter(RB_char) End If If LS_char <> Chr(0) And chkLS.Checked = True And timIO.Enabled = True Then sendCharacter(LS_char) End If If RS_char <> Chr(0) And chkRS.Checked = True And timIO.Enabled = True Then sendCharacter(RS_char) End If If BA_char <> Chr(0) And chkBA.Checked = True And timIO.Enabled = True Then sendCharacter(BA_char) End If If ST_char <> Chr(0) And chkST.Checked = True And timIO.Enabled = True Then sendCharacter(ST_char) End If If PU_char <> Chr(0) And chkPU.Checked = True And timIO.Enabled = True Then sendCharacter(PU_char) End If If PD_char <> Chr(0) And chkPD.Checked = True And timIO.Enabled = True Then sendCharacter(PD_char) End If If PR_char <> Chr(0) And chkPR.Checked = True And timIO.Enabled = True Then sendCharacter(PR_char) End If If PL_char <> Chr(0) And chkPL.Checked = True And timIO.Enabled = True Then sendCharacter(PL_char) End If If LT1_char <> Chr(0) And LT >= 0.33 And LT < 0.66 And timIO.Enabled = True Then sendCharacter(LT1_char) End If If LT2_char <> Chr(0) And LT >= 0.66 And LT <= 1 And timIO.Enabled = True Then sendCharacter(LT2_char) End If If RT1_char <> Chr(0) And RT >= 0.33 And RT < 0.66 And timIO.Enabled = True Then sendCharacter(RT1_char) End If If RT2_char <> Chr(0) And RT >= 0.66 And RT <= 1 And timIO.Enabled = True Then sendCharacter(RT2_char) End If If LSX0_char <> Chr(0) And LSX <= -0.33 And timIO.Enabled = True Then sendCharacter(LSX0_char) End If If LSX2_char <> Chr(0) And LSX >= 0.33 And timIO.Enabled = True Then sendCharacter(LSX2_char) End If If RSX0_char <> Chr(0) And RSX <= -0.33 And timIO.Enabled = True Then sendCharacter(RSX0_char) End If If RSX2_char <> Chr(0) And RSX >= 0.33 And timIO.Enabled = True Then sendCharacter(RSX2_char) End If If LSY0_char <> Chr(0) And LSY <= -0.33 And timIO.Enabled = True Then sendCharacter(LSY0_char) End If If LSY2_char <> Chr(0) And LSY >= 0.33 And timIO.Enabled = True Then sendCharacter(LSY2_char) End If If RSY0_char <> Chr(0) And RSY <= -0.33 And timIO.Enabled = True Then sendCharacter(RSY0_char) End If If RSY2_char <> Chr(0) And RSY >= 0.33 And timIO.Enabled = True Then sendCharacter(RSY2_char) End If End Sub Private Sub sendCharacter(keyChar As Char) Dim tmp As Char Dim dateTimeIndication As String Dim dateTimeLength As Integer Dim tmpLength As Integer Dim startPos As Integer dateTimeIndication = DateTime.Now.ToString("MM/dd/yyyy HH:mm:ss") & ": " dateTimeLength = dateTimeIndication.Length tmp = keyChar & vbCrLf tmpLength = 1 spt1.WriteLine(tmp) startPos = rtbTX.TextLength rtbTX.AppendText(dateTimeIndication) rtbTX.Select(startPos, dateTimeLength) rtbTX.SelectionColor = Color.Blue startPos = rtbTX.TextLength rtbTX.AppendText(tmp) rtbTX.Select(startPos, tmpLength) rtbTX.SelectionColor = Color.Black End Sub Private Sub cmdInputs_Click(sender As Object, e As EventArgs) Handles cmdInputs.Click frmInputs.Show() End Sub Private Sub cmdOutputs_Click(sender As Object, e As EventArgs) Handles cmdOutputs.Click frmOutputs.Show() End Sub Private Sub chkLV_CheckedChanged(sender As Object, e As EventArgs) Handles chkLV.CheckedChanged tkbL.Enabled = chkLV.Checked If tkbL.Enabled = False Then GamePad.SetVibration(selectedController, 0, 0) Else GamePad.SetVibration(selectedController, tkbL.Value / 10, 0) End If End Sub Private Sub chkRV_CheckedChanged(sender As Object, e As EventArgs) Handles chkRV.CheckedChanged tkbR.Enabled = chkRV.Checked If tkbR.Enabled = False Then GamePad.SetVibration(selectedController, 0, 0) Else GamePad.SetVibration(selectedController, 0, tkbR.Value / 10) End If End Sub Private Sub tkbL_Scroll(sender As Object, e As EventArgs) Handles tkbL.Scroll GamePad.SetVibration(selectedController, tkbL.Value / 10, 0) End Sub Private Sub tkbR_Scroll(sender As Object, e As EventArgs) Handles tkbR.Scroll GamePad.SetVibration(selectedController, 0, tkbR.Value / 10) End Sub Private Sub cmbControllerRefreshTime_SelectedIndexChanged(sender As Object, e As EventArgs) Handles cmbControllerRefreshTime.SelectedIndexChanged Select Case cmbControllerRefreshTime.Text Case "50 ms" timXBOX.Interval = 50 Case "100 ms" timXBOX.Interval = 100 Case "200 ms" timXBOX.Interval = 200 Case "500 ms" timXBOX.Interval = 500 Case "1 s" timXBOX.Interval = 1000 End Select End Sub Private Sub cmbRXRefreshTime_SelectedIndexChanged(sender As Object, e As EventArgs) Handles cmbRXRefreshTime.SelectedIndexChanged Select Case cmbRXRefreshTime.Text Case "50 ms" timIO.Interval = 50 Case "100 ms" timIO.Interval = 100 Case "200 ms" timIO.Interval = 200 Case "500 ms" timIO.Interval = 500 Case "1 s" timIO.Interval = 1000 End Select End Sub Private Sub cmdAbout_Click(sender As Object, e As EventArgs) Handles cmdAbout.Click frmAbout.Show() End Sub End Class
frmOutputs:
Public Class frmOutputs Private Sub cmdCancel_Click(sender As Object, e As EventArgs) Handles cmdCancel.Click ' Closes form Me.Close() End Sub Private Sub cmdOK_Click(sender As Object, e As EventArgs) Handles cmdOK.Click ' Closes form and assigns user-defined data to main form If checkStrings() = False Then If txtActL1.Text <> "" Then LeftMotorSpeed1 = tkbL1.Value / 10 LeftMotorActivationWord1 = txtActL1.Text End If If txtActL2.Text <> "" Then LeftMotorSpeed2 = tkbL2.Value / 10 LeftMotorActivationWord2 = txtActL2.Text End If If txtDeact.Text <> "" Then MotorDeactivationWord = txtDeact.Text End If If txtActR2.Text <> "" Then RightMotorSpeed2 = tkbR2.Value / 10 RightMotorActivationWord2 = txtActR2.Text End If If txtActR1.Text <> "" Then RightMotorSpeed1 = tkbR1.Value / 10 RightMotorActivationWord1 = txtActR1.Text End If Me.Close() Else MsgBox("Strings have to be different.", MsgBoxStyle.Exclamation) End If End Sub Private Sub tkbL1_Scroll(sender As Object, e As EventArgs) Handles tkbL1.Scroll lblL1.Text = tkbL1.Value / 10 End Sub Private Sub tkbR1_Scroll(sender As Object, e As EventArgs) Handles tkbR1.Scroll lblR1.Text = tkbR1.Value / 10 End Sub Private Sub tkbL2_Scroll(sender As Object, e As EventArgs) Handles tkbL2.Scroll lblL2.Text = tkbL2.Value / 10 End Sub Private Sub tkbR2_Scroll(sender As Object, e As EventArgs) Handles tkbR2.Scroll lblR2.Text = tkbR2.Value / 10 End Sub Function checkStrings() As Boolean Dim txt1 As String Dim txt2 As String Dim txt3 As String Dim txt4 As String Dim txt5 As String txt1 = txtActL1.Text txt2 = txtActL2.Text txt3 = txtActR1.Text txt4 = txtActR2.Text txt5 = txtDeact.Text If (txt1 = txt2 And txt1 <> "") Or (txt1 = txt3 And txt1 <> "") Or (txt1 = txt4 And txt1 <> "") Or (txt1 = txt5 And txt1 <> "") Or (txt2 = txt3 And txt2 <> "") Or (txt2 = txt4 And txt2 <> "") Or (txt2 = txt5 And txt2 <> "") Or (txt3 = txt4 And txt3 <> "") Or (txt3 = txt5 And txt3 <> "") Or (txt4 = txt5 And txt4 <> "") Then Return True Else Return False End If End Function Private Sub frmOutputs_Load(sender As Object, e As EventArgs) Handles MyBase.Load txtActL1.Text = LeftMotorActivationWord1 txtActL2.Text = LeftMotorActivationWord2 txtActR1.Text = RightMotorActivationWord1 txtActR2.Text = RightMotorActivationWord2 txtDeact.Text = MotorDeactivationWord tkbL1.Value = LeftMotorSpeed1 * 10 tkbL2.Value = LeftMotorSpeed2 * 10 tkbR1.Value = RightMotorSpeed1 * 10 tkbR2.Value = RightMotorSpeed2 * 10 lblL1.Text = tkbL1.Value / 10 lblR1.Text = tkbR1.Value / 10 lblL2.Text = tkbL2.Value / 10 lblR2.Text = tkbR2.Value / 10 End Sub End Class
frmInputs:
Public Class frmInputs Private Sub cmdCancel_Click(sender As Object, e As EventArgs) Handles cmdCancel.Click ' Closes form Me.Close() End Sub Private Sub cmdOK_Click(sender As Object, e As EventArgs) Handles cmdOK.Click ' Closes form and updates key mapping A_char = txtSendCA.Text B_char = txtSendCB.Text X_char = txtSendCX.Text Y_char = txtSendCY.Text LB_char = txtSendCLB.Text RB_char = txtSendCRB.Text LS_char = txtSendCLS.Text RS_char = txtSendCRS.Text PU_char = txtSendCPU.Text PD_char = txtSendCPD.Text PL_char = txtSendCPL.Text PR_char = txtSendCPR.Text BA_char = txtSendCBA.Text ST_char = txtSendCST.Text LT1_char = txtSendCLT1.Text LT2_char = txtSendCLT2.Text RT1_char = txtSendCRT1.Text RT2_char = txtSendCRT2.Text LSX0_char = txtSendCLSX0.Text LSX2_char = txtSendCLSX2.Text RSX0_char = txtSendCRSX0.Text RSX2_char = txtSendCRSX2.Text LSY0_char = txtSendCLSY0.Text LSY2_char = txtSendCLSY2.Text RSY0_char = txtSendCRSY0.Text RSY2_char = txtSendCRSY2.Text Me.Close() End Sub Private Sub l_Load(sender As Object, e As EventArgs) Handles MyBase.Load ' Reloads the existing mapping when reopening this form txtSendCA.Text = A_char txtSendCB.Text = B_char txtSendCX.Text = X_char txtSendCY.Text = Y_char txtSendCLB.Text = LB_char txtSendCRB.Text = RB_char txtSendCLS.Text = LS_char txtSendCRS.Text = RS_char txtSendCPU.Text = PU_char txtSendCPD.Text = PD_char txtSendCPL.Text = PL_char txtSendCPR.Text = PR_char txtSendCBA.Text = BA_char txtSendCST.Text = ST_char txtSendCLT1.Text = LT1_char txtSendCLT2.Text = LT2_char txtSendCRT1.Text = RT1_char txtSendCRT2.Text = RT2_char txtSendCLSX0.Text = LSX0_char txtSendCLSX2.Text = LSX2_char txtSendCRSX0.Text = RSX0_char txtSendCRSX2.Text = RSX2_char txtSendCLSY0.Text = LSY0_char txtSendCLSY2.Text = LSY2_char txtSendCRSY0.Text = RSY0_char txtSendCRSY2.Text = RSY2_char End Sub End Class
Module1:
Module Module1 Public LeftMotorSpeed1 As Single Public RightMotorSpeed1 As Single Public LeftMotorSpeed2 As Single Public RightMotorSpeed2 As Single Public LeftMotorActivationWord1 As String Public LeftMotorActivationWord2 As String Public MotorDeactivationWord As String Public RightMotorActivationWord1 As String Public RightMotorActivationWord2 As String Public A_char As Char Public B_char As Char Public LB_char As Char Public RB_char As Char Public X_char As Char Public Y_char As Char Public LS_char As Char Public RS_char As Char Public BA_char As Char Public ST_char As Char Public PU_char As Char Public PD_char As Char Public PL_char As Char Public PR_char As Char Public LT1_char As Char Public LT2_char As Char Public RT1_char As Char Public RT2_char As Char Public LSX0_char As Char Public LSX2_char As Char Public LSY0_char As Char Public LSY2_char As Char Public RSX0_char As Char Public RSX2_char As Char Public RSY0_char As Char Public RSY2_char As Char End Module
Il codice sorgente e l’ultima release possono essere scaricati da GitHub agli indirizzi https://github.com/VikingStormtrooper/XBOX2ARDUINO (codice sorgente) e https://github.com/VikingStormtrooper/XBOX2ARDUINO/releases (release).