Approfondimento sull'accesso alle porte USB

Da Gambas-it.org - Wikipedia.

La presente guida è stata realizzata dall'utente Ste86 del Forum di Gambas-it.org |1|.

PREFAZIONE

Ciò che mi ha spinto a realizzare questa guida è per fornire un supporto pratico per coloro che arrivano da un' ambiente WINDOWS e hanno un minimo di dimestichezza con Visual Basic per gestire le porte USB in LINUX con GAMBAS e vogliono far interagire il proprio PC con un microcontrollore. In questo esempio si usa un ATmega 328 che opera su un Arduino 2009. Con il termine "pratico" intendo che le mie conoscenze si limitano a dimostrare i passaggi necessari per riuscire nell'impresa senza entrare a fondo nei dettagli tecnici.

Tutto il processo qui mostrato è stato eseguito con Linux Lubuntu 11.04 e Gambas 2.22.


SPIEGAZIONE

Nei sistemi UNIX, in questo caso Linux Lubuntu ,tutto ciò che è hardware viene rappresentato e gestito come un file. Chi proviene da ambienti WINDOWS deve tener conto e riflettere un po' su questo per comprendere meglio il seguito di tutto. Questi file sono collocati nella directory “/dev” e sono vitali per il sistema. (Per chi non sapesse come trovare questa cartella può accedervi digitando appunto “/dev” nella barra degli indirizzi di una qualsiasi finestra contenente dei file come mostrato in “figura1”).


PROCEDIMENTO

Il primo passo da affrontare è quello di loggarsi come super-utente perché un utente con account di login normale non può modificare i file contenuti nella cartella “/dev” essendo proprietà dell'utente Root, cioè il super-utente. I file di sistema in questione sarebbero quelli collocati nella cartella “/dev” cerchiati in rosso in “figura1”.

Vedremo ora come creare la password per poi loggarsi come super-utente.

Bisognerà prima di tutto avviare il terminale, in Linux Lubuntu 11.04 si trova nel menu in basso a sinistra come evidenziato in “figura2”.

Cliccando verrà fuori un menù a tendina, al suo interno dovremo cercare la voce “accessori” e poi ancora la voce “Lx terminal”. Eseguiamo quest'ultimo, apparirà un finestra con sfondo Nero come raffigurato sempre in “figura2”. Va ora precisato che l'utente Root ha bisogno di una password che non c'entra con quella che di solito si utilizza per loggarsi nel proprio sistema o per installare programmi. La creiamo appunto attraverso il terminale digitando il comando:

sudo passwd root

Dopo aver digitato il comando il terminale ci farà la richiesta di inserire la password in questo modo:

“Inserire nuova password UNIX:”

Non preoccupatevi se quando digitate la password non vedrete nessun carattere comparire, è solo una forma di sicurezza del sistema operativo.

A questo punto inseriremo la nostra password e premeremo il tasto invio, il terminale ci farà un'altra richiesta di reinserire la password in questo modo:

“Reinserire la nuova password UNIX: “

Dopo aver reinserito la password e aver premuto il tasto invio il terminale ci dirà

“password aggiornata correttamente”.

Ora abbiamo inserito la password di Root e finalmente possiamo andare a modificare i file nella cartella “/dev”. Ora possiamo loggarci come Root.

Dobbiamo cliccare su termina sessione attraverso il menù in basso a sinistra dello schermo come abbiamo visto prima cerchiato in rosso in “figura2”. Ora dobbiamo cercare la voce “chiudere sessione” e cliccarla. Il sistema operativo ci chiederà il nome utente e digiteremo “Root”, poi ci chiederà la password e inseriremo quella che abbiamo scelto nel procedimento sopra affrontato. Accediamo ora alla cartella “/dev” e cerchiamo i file omonimi a quelli cerchiati in rosso nella “figura1”. Una volta individuati dovremmo andare nelle proprietà di ciascuno di essi (cliccando col tasto destro del mouse sopra a ciascun file).

Una volta aperte le proprietà dovremmo cliccare su “permessi” come cerchiato in rosso nella “figura4”. Nella parte inferiore di questa finestra troveremo: proprietario, gruppo, altro. Imposteremo queste utenze in modo che possano leggere e scrivere il file come raffigurato in “figura 4”.

Da qui in poi riporto parte di una guida che ho trovato su internet da cui ho imparato io stesso a fare queste cose. Potete trovarla completa all'indirizzo: www.emcu.it/GAMBAS/Coman_di_Gambas.pdf:

Aprite Gambas2 e caricate l'esempio SerialPort.
Lanciate SerialPort e se tutto funziona siete a posto ma se
non vi funziona, il programma da errori o sembra bloccarsi,
allora serve fare le modifiche sotto riportate.

1) Tipicamente l'installazione di Gambas2 viene fatta in:
/usr/share/gambas2 ed è in sola lettura per cui bisogna andare nella directory:
/usr/share/gambas2/examples/Networking/SerialPort
e cambiare le proprietà di tutti i file presenti mettendoli in
lettura e scrittura nello stesso modo che abbiamo visto sopra.
2) Un altro problema deriva dal fatto che viene caricato:
gb.gui al posto del gb.qt
Per modificare l'impostazione (nell'installazione di Gambas2 Italiana) fate così:
Una volta aperto il progetto selezionate PROGETTO e poi PROPRIETA'
- Dalla finestra che compare selezionate COMPONENTI
disabilitate gd.gui e abilitate gd.qt
- In generale i componenti che devono essere abilitati sono riportati nella finestra sotto.

Lanciate il programma e tutto deve funzionare


Da qui in poi le parole che leggete sono di nuovo le mie...:)

Arrivati a questo punto dopo aver avviato l'esempio “serial port” vi troverete nella situazione raffigurata in “figura5”.

Andiamo a visualizzare ora il codice facendo doppio click su uno spazio vuoto qualsiasi della form. (Non volendo dare niente per scontato.... fate doppio click più o meno nel punto cerchiato in rosso in “figura5”). Ora prenderò in considerazione le parti di codice che a mio parare sono le più importanti. Inizio dalla classe “SPort_Read()” che si presenterà in questo modo:

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

Faccio notare che è stata dichiarata una variabile “s” nella seconda riga “DIM s AS String” della classe “SPort_Read()” sopra riportata. Questa variabile legge ciò che la porta seriale prescelta riceve. A parer mio è il punto di partenza per capire come il computer possa interagire col mondo esterno e poter farlo “giocare” semplicemente con l'istruzione IF.

Poco sopra ho usato le parole “porta seriale prescelta”; si vuole intendere quale porta seriale che il computer deve usare, nel nostro caso una porta USB. Ci tengo a fare una precisazione: con il termine “porta seriale” non si intende solo la cara e vecchia RS-232 raffigurata in “figura6” ma anche le porte USB. Per cui ora definisco che la porta USB è una porta di tipo seriale. In “figura7” si vedono le varianti in commercio.

Interagire con Arduino

Nella prefazione di questa guida ho specificato che è mia intenzione far interagire Gambas con Arduino. Per chi non lo sapesse spiego in poche parole cos'è Arduino. 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


Note

[1] L'utente Ste86 ha inserito questa guida già nel Forum: http://www.gambas-it.org/smf/index.php?action=dlattach;topic=2266.0;attach=2561

[2] Fonti utilizzate per creare questa guida: