Comunicare con Arduino via Visual Basic

In questo articolo voglio spiegare la procedura che ho seguito di recente per iniziare a creare la mia applicazione per interagire con Arduino tramite il controller dell’Xbox 360, sfruttando l’interfaccia USB tra il computer e Arduino. Per cominciare, è necessario stabilire la comunicazione tra le due parti o, in altri termini, fare in modo che il computer riceva i messaggi inviati da Arduino e che possa inviarne a sua volta. Molto del lavoro qui mostrato è basato su due articoli di Martyn Currey (che ringrazio molto per le dritte utilissime), reperibili agli indirizzi

http://www.martyncurrey.com/arduino-and-visual-basic-part-1-receiving-data-from-the-arduino/ e http://www.martyncurrey.com/arduino-and-visual-basic-part-3-controlling-an-arduino/ .

Chiunque conosca un po’ Arduino ha sicuramente usato più volte la finestra del Monitor seriale, quella in cui si leggono le stringhe inviate da Arduino ed in cui si possono mandare dei caratteri in senso contrario:

Screen2

Nel mio caso ho utilizzato una scheda Arduino Micro che Windows rilevava collegata alla porta COM9. Su Arduino ho caricato un banalissimo programma che fa inviare tramite USB la stringa “1234” ogni secondo, facendo illuminare al contempo il led built-in sul pin 13. Il codice da caricare su Arduino è estremamente breve:

byte LEDpin = 13;
 
void setup() 
{
 pinMode(LEDpin, OUTPUT); 
 Serial.begin(9600);
}
 
void loop() 
{
 Serial.println("1234");
 digitalWrite(LEDpin,HIGH);
 delay(100);
 digitalWrite(LEDpin,LOW);
 delay(900);
}

Una volta controllato tramite il Monitor seriale nell’IDE di Arduino che la nostra scheda invii realmente la stringa desiderata, si può passare al lato computer, che in questo caso ho gestito tramite Visual Basic. Il codice è scritto nella versione di VB contenuta in Visual Studio 2012 e, di conseguenza, ci sono alcune differenze con le versioni precedenti ma, ne sono piuttosto convinto, facendo gli opportuni aggiustamenti sarebbe possibile tradurlo per le versioni precedenti. L’interfaccia del programma è quella che segue:

Screen1

Dalla casella combinata in alto è possibile selezionare la porta COM con la quale si desidera stabilire la comunicazione; il programma carica nella lista solo le porte effettivamente visibili da Windows. Il pulsante “Connect” stabilisce la comunicazione tramite la porta selezionata e attiva un timer che, a intervalli regolari, legge gli eventuali messaggi trasmessi da Arduino e li elenca, con data e ora, nella Rich Text Box di sinistra, relativa alla ricezione da Arduino. In particolare, il timer è stato settato (proprietà Interval) su 1 s, in modo da essere sincronizzato con l’invio dei messaggi da parte di Arduino. Sul lato destro è presente una casella di testo in cui è possibile digitare dei caratteri da inviare ad Arduino premendo “Send”; la Rich Text Box di destra, tiene traccia degli invii. I pulsanti “Clear” cancellano le rispettive Rich Text Box. Il codice VB, relativo al form mostrato in figura, è il seguente:

' Programma VB per comunicare con Arduino tramite interfaccia USB
' Grazie a Martyn Currey per i suoi tutorial:
' 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/
' Importazione delle librerie di sistema
Imports System
Imports System.IO.Ports
Public Class Form1
    Dim comPORT As String    
    Dim receivedData As String = ""    
    Dim connected As Boolean = False

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load        
        ' Inizializza timer, valore di comPORT, e lista delle porte COM        
        Timer1.Enabled = False        
        comPORT = ""        
        For Each sp As String In My.Computer.Ports.SerialPortNames            
            comPort_Combobox.Items.Add(sp)        
        Next    
    End Sub

    Private Sub refresh_BTN_Click(sender As Object, e As EventArgs) Handles refresh_BTN.Click        
    ' Aggiorna la lista delle porte COM premendo il pulsante Refresh        
        comPort_Combobox.Items.Clear()        
        comPORT = ""        
        For Each sp As String In My.Computer.Ports.SerialPortNames            
            comPort_Combobox.Items.Add(sp)        
        Next    
    End Sub

    Private Sub comPort_ComboBox_SelectedIndexChanged(sender As Object, e As EventArgs) Handles comPort_Combobox.SelectedIndexChanged        
        ' Aggiorna il valore di comPORT quando si cambia la selezione nella lista delle porte COM        
        If (comPort_Combobox.SelectedItem <> "") Then            
            comPORT = comPort_Combobox.SelectedItem        
        End If    
    End Sub

    Private Sub connect_BTN_Click(sender As Object, e As EventArgs) Handles connect_BTN.Click 
        ' Pressione del pulsante Connect/Disconnect        
        If (connect_BTN.Text = "Connect") Then            
            ' Se viene attivata la modalità Connect, apre la comunicazione con la porta COM voluta            
            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 = 10000                
                SerialPort1.Open()                
                connect_BTN.Text = "Disconnect"                
                Timer1.Enabled = True                
                connected = True                
                send_BTN.Enabled = True            
            Else                
                MsgBox("Select a COM port first!", vbExclamation)            
            End If        
        Else            
            ' Se viene attivata la modalità Disconnect, chiude la comunicazione           
            SerialPort1.Close()            
            connect_BTN.Text = "Connect"            
            Timer1.Enabled = False            
            connected = False            
            send_BTN.Enabled = False        
        End If    
    End Sub

    Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick        
        ' Aggiorna periodicamente la lista dei messaggi ricevuti        
        Dim dateTimeIndication As String        
        Dim receivedDataLength As Integer        
        Dim dateTimeLength As Integer        
        Dim startPos As Integer     
   
        receivedData = ReceiveSerialData()        
        receivedDataLength = receivedData.Length        
        dateTimeIndication = DateTime.Now.ToString("MM/dd/yyyy HH:mm:ss") & ": "        
        dateTimeLength = dateTimeIndication.Length        
        startPos = RichTextBox1.TextLength        
        RichTextBox1.AppendText(dateTimeIndication)        
        RichTextBox1.Select(startPos, dateTimeLength)        
        RichTextBox1.SelectionColor = Color.Red        
        startPos = RichTextBox1.TextLength        
        RichTextBox1.AppendText(receivedData)        
        RichTextBox1.Select(startPos, receivedDataLength)        
        RichTextBox1.SelectionColor = Color.Black    
    End Sub

    Function ReceiveSerialData() As String        
        ' Funzione per leggere le stringhe inviate da Arduino        
        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 send_BTN_Click(sender As Object, e As EventArgs) Handles send_BTN.Click        
        ' Invia le stringhe inserite dall'utente ad 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 = send_TB.Text & vbCrLf            
            tmpLength = tmp.Length            
            SerialPort1.WriteLine(tmp)            
            startPos = RichTextBox2.TextLength            
            RichTextBox2.AppendText(dateTimeIndication)            
            RichTextBox2.Select(startPos, dateTimeLength)            
            RichTextBox2.SelectionColor = Color.Blue            
            startPos = RichTextBox2.TextLength            
            RichTextBox2.AppendText(tmp)            
            RichTextBox2.Select(startPos, tmpLength)            
            RichTextBox2.SelectionColor = Color.Black        
        End If    
    End Sub

    Private Sub clear_BTN_Click(sender As Object, e As EventArgs) Handles clear_BTN.Click        
        ' Cancella la lista dei messaggi ricevuti        
        RichTextBox1.Text = ""    
    End Sub

    Private Sub clear_BTN2_Click(sender As Object, e As EventArgs) Handles clear_BTN2.Click        
        ' Cancella la lista dei messaggi inviati        
        RichTextBox2.Text = ""    
    End Sub

    Private Sub RichTextBox1_TextChanged(sender As Object, e As EventArgs) Handles RichTextBox1.TextChanged        
       ' Sposta la barra di scorrimento della Rich Text Box di sinistra verso l'ultimo messaggio        
       RichTextBox1.SelectionStart = RichTextBox1.TextLength        
       RichTextBox1.ScrollToCaret()    
    End Sub    

    Private Sub RichTextBox2_TextChanged(sender As Object, e As EventArgs) Handles RichTextBox2.TextChanged        
        ' Sposta la barra di scorrimento della Rich Text Box di destra verso l'ultimo messaggio        
        RichTextBox2.SelectionStart = RichTextBox2.TextLength        
        RichTextBox2.ScrollToCaret()    
    End Sub

End Class

Quando mandiamo in esecuzione il programma, la prima cosa da fare è selezionare la porta e poi premere “Connect”.

Screen3

Se tutto va per il verso giusto, nella Rich Text Box di sinistra possiamo veder comparire la lista di “1234” inviati ad intervalli di 1 secondo l’uno dall’altro.

Screen4

Nell’immagine soprastante vediamo il risultato dello stesso codice caricato in precedenza su Arduino ma con, in aggiunta, una funzione per far rimandare da Arduino un eventuale carattere inviatogli dal computer – nell’esempio qui mostrato, il carattere “h” prima, “3” poi.

byte LEDpin = 13;
char rc;
 
void setup() 
{
 pinMode(LEDpin, OUTPUT); 
 Serial.begin(9600);
}
 
void loop() 
{
 Serial.println("1234");
 digitalWrite(LEDpin,HIGH);
 delay(100);
 digitalWrite(LEDpin,LOW);
 delay(900);

if(Serial.available() >0)
 {
 rc = Serial.read();
 Serial.println(rc);
 }
}

Nel Monitor seriale dell’IDE di Arduino funziona tutto regolarmente mentre, nel nostro programma, al regolare rinvio del carattere inviato segue una sorta di “fluttazione” nei messaggi spediti da Arduino, che si stabilizza solo dopo 3-4 secondi dal rinvio del carattere. I motivi di questo comportamento non mi sono ancora chiari ed ipotizzo che siano connessi al fatto di andare a leggere e a scrivere su Arduino praticamente nello stesso tempo, ma al momento non ho un’idea precisa. In futuro può essere interessante provare a risolvere il problema, ma intanto abbiamo una prima interfaccia di comunicazione a due vie con Arduino realizzata autonomamente! In futuro mi occuperò dell’interfaccia – gestita sempre in Visual Basic – tra il computer e il controller dell’Xbox 360, per poi unire quella parte alla comunicazione Arduino-computer ed utilizzare quest’ultimo come tramite per interfacciare il controller ad Arduino. Alla prossima!

Annunci

Rispondi

Inserisci i tuoi dati qui sotto o clicca su un'icona per effettuare l'accesso:

Logo WordPress.com

Stai commentando usando il tuo account WordPress.com. Chiudi sessione /  Modifica )

Google+ photo

Stai commentando usando il tuo account Google+. Chiudi sessione /  Modifica )

Foto Twitter

Stai commentando usando il tuo account Twitter. Chiudi sessione /  Modifica )

Foto di Facebook

Stai commentando usando il tuo account Facebook. Chiudi sessione /  Modifica )

w

Connessione a %s...