Comunicazione seriale

Istallazione della libreria ed utilizzo

Ci sto lavorando

 

 

Oggetto: Istalazione della libreria jssc e importazione

 

 

Documentazione:

UNI roma 1 - Trasmissione seriale
wikipedia - USB
Java-simple-serial-connector - Sito dello sviluppatore
Download jssc2.8.0 ultima versione
JSSC Reference

 

Questo è un argomento molto importante in quanto permette la comunicazione del PC con il mondo esterno ed in particolare con Arduino un microcontrollore che fa miracoli. Esso è in grado di interfacciasi con un'infinità di sensori consentendo l'accesso ad un'infinità di applicazioni. La comunicazione seriale avviene attraverso la vecchia porta seriale RS- 232 ormai sostituita dalla più performante USB. Comunicare con Arduino è l'obiettivo principale di queste pagine. Vogliamo farlo mediante l'uso del linguaggio java, per questo bisogna scaricare delle apposite librerie. Se ne trovano alcune in rete, una è la RxTx abbasta complessa da gestire e, sembra non più supportata, quindi dopo alcuni tentativi ho preferito cercare qualcosa di più accessibile e credo di averlo trovato in una libreria il cui nome è esplicativo JSSC acronimo di "Java Simple Serial Connector" scritta dal russo Alexey Sokolov alias scream3r.

 

 

Istallazione:

Il materiale scaricato consta di:

JSSC-2.8.0.jar - è la vera e propria libreria, ossia la collezione di classi compilate (bycode) tipo file.class.

JSSC-2.80-javadoc.jar - è il reference. Qui il jar ha funzione di file zip. Se vogliamo averlo a disposizione in locale possiamo scompattare il file jar con winzip ed inserire il tutto in una direttory sul pc bastera eseguire l'index.html. Se si vuole risparmiare spazio c'è chi lo ha messo online per noi lo troviamo nei link della documentazione (qui sopra) alla voce JSSC Reference.

JSSC-2.8.0-sources.jar - ci sono i sorgenti i file.java delle 7 classi che compongono la libreria.

 

A questo punto dobbiamo aggiungere la libreria (JSSC-2.8.0.jar) nel posto giusto e questo è:

C:\Program Files\Java\jre1.8.0_151\lib\ext.

Copiamola in questa posizione.

Per utilizzare la libreria nei nostri progetti dobbiamo aggiungerla al progetto e poi importarla. Per comprendere la procedura mi baserò sul progetto ArduinoRGB.

 

Creiamo il progetto ed importiamo la libreria JSSC-2.8.0.jar così:

 

 

Clicchiamo su Add JAR/Folder... e andiamo a pescarla dove l'abbiamo messa ossia in:

C:\Program Files\Java\jre1.8.0_151\lib\ext.

 

 

Dobbiamo infine importarlo, in modo dettagliato o semplicemente con l'omnicomprensivo: import jssc.*;

 

 

  1 package arduinorgb;
  2 
  3 import java.awt.*;
  4 import java.awt.Color;
  5 import java.awt.event.*;
  6 import java.util.Locale;
  7 import javax.swing.*;
  8 import jssc.SerialPort;
  9 import jssc.SerialPortEvent;
 10 import jssc.SerialPortEventListener;
 11 import jssc.SerialPortException;
 12   

 

 

Le parti del codice che interessano la comunicazione seriale sono nel metodo serialInitialize() (righe 249-269) e serialPortReader() (righe 270-302).

 

Iniziamo con l'analizzare serialInitialize()

 

239     public void serialInitialize() { 
240         try {
241             serialPort = new SerialPort("COM3");
242             // open serial port 
243             System.out.println("Port opened: " + serialPort.openPort()); 
244             // set the serial port parameters 
245             System.out.println("Params setted: " + serialPort.setParams(115200, 8, 1, 0)); 
246             Thread.sleep(2000);//Dai tempo ad arduino di resettarsi 
247             //init = true; 
248             int mask = SerialPort.MASK_RXCHAR;
249             //Imposta la maschera
250             serialPort.setEventsMask(mask);            
251             //Aggiungi un'interfaccia attraverso la quale riceveremo informazioni sugli eventi
252             serialPort.addEventListener(new SerialPortReader());
253              System.out.println("La porta è: " + serialPort.getPortName());
254              System.out.println("PRONTI******"); 
255         } catch (SerialPortException | InterruptedException ex){ 
256             System.out.println(ex); 
257           } 
258     }

 

Vediamo cosa accade. Si crea un'istanza della classe serialPort fornendo al costruttore la porta, la COM3 nel nostro caso. C'e anche il modo di fargli rilevare la lista delle com disponibili ma poichè nel mio PC Arduino si collega mediante la COM3 sono andato diretto. Una volta creato l'oggetto porta seriale bisogna aprirla. Questo provoca una singolare reazione da parte di Arduino il quale in seguito alla apertura della porta si resetta. Una volta aperta bisogna impostarla. Il metodo setParams riceve 4 argomenti che sono

  1. baudRate - data transfer rate (115200)
  2. dataBits - number of data bits (8)
  3. stopBits - number of stop bits (1)
  4. parity - parity (0)

La pausa di 2 secondi Thread.sleep(2000); servirà a dare il tempo ad Arduino di resettarsi.

Ora parliamo un attimo di mask. Faccio una premessa molto sintetica (per un approfondimento si veda la documentazione 1° link) nella trasmissione seriale RS 232 ci sono 9 pin (9 cavi) due servono per la trasmissione dei dat uno TX da PC a Arduini e RX da arduino a PC poi ce ne sono altri che servono ai dispositivi per passarsi informazioni di altro tipo per esempio sul RTS il PC dice ad Ar. sei pronto che ti devo inviare dei dati e Ar. se prondo gli risponde sul CTS si ok sono pronto invia pure. Invece il PC avverte Ar di essere pronto a ricevere dati sul DTR ed Ar gli risponde che è pronto adf inviargleli sul DSR. Quindi se parliamo di ricezione avremo i dati su RX ed i messaggi su CTS e DSR. Ora sinceramente di quello che si dicono fra loro il PC con Ar a noi non ci interessa la cosa che invece ci interessa sono i dati in arrivo parliamo di serialPortReader() lettura. La maschera serve a filtrare fa passare solo i dati che ci interessano.

Nella maschera, dobbiamo specificare i tipi di eventi che vogliamo monitorare. Se per esempio, ci interessa sapere solo se ci sono dati in arrivo la maschera deve avere il valore seguente: MASK_RXCHAR. Se, per esempio, abbiamo bisogno di sapere anche dei cambiamenti negli stati delle linee CTS e DSR, la maschera deve apparire così: SerialPort.MASK_RXCHAR + SerialPort.MASK_CTS + SerialPort.MASK_DSR.

Ma poiche a noi interessano solo i dati in arrivo useremo int mask = SerialPort.MASK_RXCHAR;

Nella righa 252 andiamo ad associare un ascoltatore (l'oggetto SerialPortReader) alla serialPort . L'ascoltatore è un oggetto che implementa un'interfaccia di tipo serialPoreEventListener e quindi sarà costretto a definire il metodo serialEvent all'interno del quale andremo a fargli fare quello che vogliamo quando si scatena l'evento, ossia quando arriva qualche dato. Ad esempio leggerlo.

Naturalmete il tutto deve stare all'interno di un blocco try ... catch in quanto si potrebbe verificare una eccezione del tipo SerialPortException. Notare che viene eventualmente catturato anche l'eccezione InterruptedException necessaria per Thread.sleep(2000);

 

 

Ora passiamo a discutere la classe interna SerialPortReader

 

259     public class SerialPortReader implements SerialPortEventListener {
260         @Override
261         public void serialEvent(SerialPortEvent event) { 
262             String str="",stv;
263             byte[] by= new byte[1];                       
264             while(true){
265                 try {             
266                     by = serialPort.readBytes(1);
267                     if(by[0]!=10 && by[0]!=13){                         
268                          if(by[0]>47 && by[0]<58){//se è un numero
269                             str +=(char)by[0];//accumola nella stringa 
270                          }                        
271                     }else{                       
272                         if(by[0]==13) {                                  
273                             try{
274                                 stv=toVolt(str);
275                                 try{
276                                     jLabel3.setText(stv);   
277                                 }catch(NullPointerException ex){
278                                     //System.out.println(ex);
279                                 }                               
280                                 break;
281                             }catch(NumberFormatException ex){
282                                 //System.out.println(ex);
283                             }                                            
284                         }
285                      }               
286                 }catch (SerialPortException ex) {
287                    System.out.println(ex);
288                 }                    
289             }                           
290         }
291     }

 

Questa è la parte che si fa carico di rimanere in acolto da eventuale invio di dati da parte di Arduino.

SerialPortReader è l'ascoltatore ossia la classe che starà in ascolto e che verrà asociata al source cFrame (vedi linea 252 nel metodo serialInitialize()). Nel momento che verrà lanciato un evento, ogni volta che avremo dati in arrivo dalla seriale, verrà eseguito il metodo serialEvent(). Vediamo cosa fa questo metodo:

  • Crea un array di byte di un solo elemento
  • Entra in un ciclo while
  • Legge il primo byte a disposizione by = serialPort.readBytes(1);
  • righe 267-270 se questo carattere letto è diverso da un line feed 10 o carriage return 13 che di solito stanno ad indicare la fine della stringha inviata
  • verifico se è un numero. Per essere un numero deve avere un codice ASCII compreso tra 48 e 57 (0 e 9). Se lo è lo vado ad aggiungere ala stringa str
  • Se invece è un ritorno carrello (13) significa che la stringa inviata è completa e possiamo quindi utilizzarla. Il metodo toVolt trasforma il numero inviato da Arduino con valori da 0 a 1023 in valori espressi in volt da 0 a 5 ed in formato decimale con 2 decimali dopo il punto
  • Questo valore (in forma di stringa) viene visualizzato nella label

I vari cicli try catch sono necessari per intercettare le varie eccezioni che si possono verificare e che farebbero terminare il programma

 

Questo è riferito al progetto ArduinoRGB per approfondimenti vedi qui.