Far interagire Gambas con Arduino

Da Gambas-it.org - Wikipedia.

(Guida a cura del membro Ste86 del forum www.gambas-it.org)


Arduino è un programmatore per microcontrollori ATmega 328 che vuole fornire una piattaforma di sviluppo per prototipizzare sistemi elettronici in modo pratico, divertente e veloce. Un suo vantaggio è una larga utenza, può quindi vantare molta documentazione e vaste comunità.

L'Arduino va collegato tramite una porta USB. All'inizio ho spiegato che nei sistemi UNIX l'hardware viene visto e gestito come un file. Nel momento in cui viene collegato l'Arduino verrà quindi automaticamente creato un file ad hoc nella cartella “/dev” che contiene i preziosi file di sistema. Solitamente tale file viene nominato “ttyACM0”. A mia esperienza ho notato che tra un computer e l'altro la differenza nel nome di tale file, sta nel variare l' ultimo carattere, cioè la cifra, che nel mio caso è 0. Per cui se avete difficoltà a dichiarare il nome del file che controlla Arduino basta che provate a incrementare a tentavi il valore di tale cifra che per esempio potrà essere “ttyACM1” oppure “ttyACM2” e così via...... . Nel nostro esempio va dichiarato il percorso e il nome del file di sistema con cui il programma fa riferimento ad Arduino. Questo parametro va dichiarato nella textbox denominata “txtport” che si trova alinterno della form (in “figura5” è cerchiata in blu). Una volta avviato il programma se per esempio il nostro file si chiama ttyACM0 al suo interno dovremo ogni volta digitare “/dev/ttyACM0”. Personalmente trovo scomodo che ad ogni avvio del programma vada dichiarato il percorso e il nome del file all'interno di “txtport”. Quindi per semplificarci la vita rendiamo automatico tutto questo. Per ovviare questo problema si deve intervenire sul codice del programma nella classe “Button1_Click()” apportando modifiche sulla riga “Sport.PortName = TxtPort.Text”.

Il codice originale si presenterà cosi:

PUBLIC SUB Button1_Click()
  IF Sport.Status = Net.Active THEN
  CLOSE Sport
  Button1.Text = "Open"

   ELSE
' Line parameters
    Sport.PortName = TxtPort.Text
    Sport.Speed = CmbSpeed.Text
    Sport.Parity = CmbParity.Index
    Sport.DataBits = CmbData.Text
    Sport.StopBits = CmbStop.Text
' keep DTR on
    Sport.FlowControl = ComboBox1.Index
    Sport.Open()
    Check_Status()
    TextArea1.Text = "Port Opened : " & Sport.PortName & " Settings : " &
    Sport.Speed & "," & Sport.Parity & "," & Sport.DataBits & "," &
    Sport.StopBits & Chr(13) & Chr(10)
    Button1.Text = "Close"
  END IF

 Button1_Click()

END

Ecco il codice con inserite le modifiche da apportare, segnate in rosso, nella classe Button1_Click() :

PUBLIC SUB Button1_Click()

 DIM port AS String
  port = "/dev/ttyACM0"

  IF Sport.Status = Net.Active THEN
    CLOSE Sport
    Button1.Text = "Open"
  ELSE
' Line parameters
    Sport.PortName = port
    Sport.Speed = CmbSpeed.Text
    Sport.Parity = CmbParity.Index
    Sport.DataBits = CmbData.Text
    Sport.StopBits = CmbStop.Text
' keep DTR on
    Sport.FlowControl = ComboBox1.Index

    Sport.Open()
    Check_Status()
    TextArea1.Text = "Port Opened : " & Sport.PortName & " Settings : " &
    Sport.Speed & "," & Sport.Parity & "," & Sport.DataBits & "," &
    Sport.StopBits & Chr(13) & Chr(10)
    Button1.Text = "Close"

  END IF

END

Ora eseguiamo il programma, ma non preoccupatevi se nella TxtPort vedrete ancora scritto una cosa del tipo /dev/ttyS0 l'importante è che sia dichiarata correttamente all'interno del codice. Con questo metodo possiamo ora definire tutti i parametri come ad esempio Sport.Speed, Sport.Parity, Sport.DataBits, Sport.StopBits, ecc ecc..

Una altra classe che secondo me ha importanza rilevante è la Form_Open() perché all'interno di essa viene specificato che valore deve aver il baud rate della porta utilizzata. Essa si presenta cosi:

PUBLIC SUB Form_Open()

  cmbSpeed.Index = cmbSpeed.Find("19200")

END

Da WIKIPEDIA: “Il baud rate indica il numero di transizioni al secondo che avvengono sulla linea; il bps indica, come dice il nome, quanti bit al secondo sono trasmessi lungo la linea”.

Nella comunicazione seriale questo valore deve essere uguale per chi riceve e per chi trasmette i dati.
Solitamente Arduino lo si imposta a 9600 e dunque anche il nostro progetto deve essere impostato con lo stesso valore. Possiamo rendere automatico anche questo senza dover andare ad agire nella textbox situata nella form come cerchiato in giallo nella “figura5”.

Ecco il codice con la modifica segnata in rosso:

PUBLIC SUB Form_Open()

  cmbSpeed.Index = cmbSpeed.Find("9600")

END

Siamo arrivati ora al momento di fare qualcosa di pratico dalla situazione che abbiamo ora. L'esempio SerialPort come l'abbiamo impostato farà scrivere in una TextBox il testo

“ciao a tutti”

grazie ad un segnale seriale di Arduino che parte alla pressione di un pulsante su esso. Ecco il codice per Arduino per ottenere questo:

const int buttonPin8 = 8;

int buttonState8 = 0; 

void setup() {

Serial.begin(9600);
pinMode(buttonPin8, INPUT);
}

void loop() {

buttonState8 = digitalRead(buttonPin8);

if (buttonState8 == HIGH) { 
delay (250); 
Serial.print ("ciao a tutti");
 }

}

Questo, invece, è il codice per Gambas con le modifiche in rosso. La struttura della form deve essere quella dell'esempio SerialPort raffigurata in “figura5”:

' Gambas class file

PUBLIC SUB Form_Close()
  IF Sport.Status = Net.Active THEN CLOSE Sport
END


PUBLIC SUB Check_Status()

  ChkDSR.Value = Sport.DSR
  ChkDTR.Value = Sport.DTR
  ChkCTS.Value = Sport.CTS
  ChkRTS.Value = Sport.RTS
  ChkDCD.Value = Sport.DCD
  ChkRNG.Value = Sport.RNG

END


PUBLIC SUB Button1_Click()

 DIM port AS String
 
port = "/dev/ttyACM0"

  IF Sport.Status = Net.Active THEN
    CLOSE Sport
    Button1.Text = "Open"

  ELSE
' Line parameters
    Sport.PortName = port
    Sport.Speed = CmbSpeed.Text
    Sport.Parity = CmbParity.Index
    Sport.DataBits = CmbData.Text
    Sport.StopBits = CmbStop.Text
' keep DTR on
    Sport.FlowControl = ComboBox1.Index
    Sport.Open()
    Check_Status()
    TextArea1.Text = Chr(13) & Chr(10)
    Button1.Text = "Close"

  END IF

END


PUBLIC SUB SPort_Read()
 DIM s AS String
  READ #Sport, s, Lof(Sport) 
  TextArea1.Text = TextArea1.Text & s
END


PUBLIC SUB SPort_RNGChange(iVal AS Boolean)
  ChkRng.Value = iVal
END

PUBLIC SUB SPort_DTRChange(iVal AS Boolean)
  ChkDTR.Value = iVal
END

PUBLIC SUB SPort_DSRChange(iVal AS Boolean)
  ChkDSR.Value = iVal
END

PUBLIC SUB SPort_CTSChange(iVal AS Boolean)
  ChkCTS.Value = iVal
END

PUBLIC SUB SPort_DCDChange(iVal AS Boolean)
  ChkDCD.Value = iVal
END

PUBLIC SUB SPort_RTSChange(iVal AS Boolean)
  ChkRTS.Value = iVal
END

PUBLIC SUB Button2_Click()

  IF Sport.Status = Net.Inactive THEN
    Message("Open port first!")
  ELSE
' WRITE #Sport,TxtSend.Text & Chr(13) & Chr(10), txtSend.Length + 2
    PRINT #Sport, txtSend.Text; Chr$(13); Chr$(10);
  END IF

END

PUBLIC SUB ChkDTR_Click()

  Sport.DTR = ChkDTR.Value
  Check_Status

END

PUBLIC SUB ChkRTS_Click()

  Sport.RTS = ChkRTS.Value
  Check_Status

END


PUBLIC SUB ComboBox1_Click()

  Sport.FlowControl = ComboBox1.Index

END

PUBLIC SUB Form_Open()

  cmbSpeed.Index = cmbSpeed.Find("9600")

END

Con questo è tutto. Spero di essere stato esauriente. Buon divertimento!!

Ste86