[JAVA] recuperare dati string da Arduino

Salve a tutti,

da poco sto usando Arduino con java.
il mio progetto è quello di creare 2 contametri utilizzando 2 pin di arduino con i risultati visualizzati in un pannello della mia applicazione in java e contemporaneamente salvarlo sulla SD in due file uno per contatore.

sono praticamente riuscito a fare tutto, ma una cosa non mi è chiara quando uso il println per visualizzare i dati sul JPanel.

codice Arduino

void loop() {
  digit6=digitalRead(6);
  if(digit6==1){
    if(switchState6==0){
        metriNP1=metriNP1+1;
       SD.remove("NP1.txt");
         File myFile = SD.open("NP1.txt", FILE_WRITE);
         // if the file is available, write to it:
         if (myFile) {
            myFile.print(metriNP1);
            myFile.close();
             // print to the serial port too:
         Serial.println(String(metriNP1)+"&"+String(metriNP2));
         delay(100);
       }
         // if the file isn't open, pop up an error:
         else {
           Serial.println("error opening text.txt");
            }
    }
    switchState6=1;
  }else{
    switchState6=0;
  }

  digit7=digitalRead(7);
  if(digit7==1){
    if(switchState7==0){
        metriNP2=metriNP2+1;
       SD.remove("NP2.txt");
         File myFile2 = SD.open("NP2.txt", FILE_WRITE);
         // if the file is available, write to it:
         if (myFile2) {
            myFile2.print(metriNP2);
            myFile2.close();
             // print to the serial port too:
         Serial.println(String(metriNP1)+"&"+String(metriNP2));
         delay(100);
       }
         // if the file isn't open, pop up an error:
         else {
           Serial.println("error opening text.txt");
            }
    }
    switchState7=1;
  }else{
    switchState7=0;
  }

}

codice java

public synchronized void serialEvent(SerialPortEvent event) {
		 
		if (event.isRXCHAR()) {
			   try {
			   String valore=serialPort.readString(event.getEventValue());
			   System.out.println(valore);
			    } catch (SerialPortException ex)  {
					setContaNP1("NO DATA Error 2");
					setContaNP2("NO DATA Error 2");
				} 
		}
	}

il risultato sulla console di Arduino è perfetto :

16:26:16.376 -> 124575&611
16:26:19.910 -> 124575&612
16:26:20.182 -> 124575&613
16:26:20.386 -> 124575&614
16:26:20.624 -> 124575&615
16:26:21.066 -> 124576&615
16:26:21.338 -> 124577&615
16:26:21.678 -> 124578&615

su quella di java no è non riesco a manipolare la stringa :

124578&615
1245

79&6

15

1245

79&6
16

avete qualche consiglio ?

Grazie mille e scusate se è una richiesta banale.

Buonasera,
essendo il tuo primo post nella sezione Italiana del forum, nel rispetto del nostro regolamento, ti chiedo cortesemente di presentarti QUI (spiegando bene quali conoscenze hai di elettronica e di programmazione ... possibilmente evitando di scrivere solo una riga di saluto) e di leggere con MOLTA attenzione il su citato REGOLAMENTO ... Grazie. :slight_smile:

P.S.: Ti ricordo che, purtroppo, fino a quando non sarà fatta la presentazione nell’apposito thread, nessuno ti potrà rispondere, quindi ti consiglio di fare il tutto al più presto. :wink:

fcorsa:
sono praticamente riuscito a fare tutto, ma una cosa non mi è chiara quando uso il println per visualizzare i dati sul JPanel.

Su Arduino tu mandi i due dati sotto forma di stringa, separati tra loro da "&" e terminanti con la coppia di caratteri terminatori di linea ossia '\r' e '\n' (CR e LF, ovvero caratteri byte 13 e 10) che sono aggiunti dal Serial.println() dopo il dato.

Tu in Java dov'è che attendi di ricevere i caratteri terminatori?
Se ho ben capito come funziona (non programmo in Java, e mi sta anche un poco antipatico, ma sono io... :wink: ) tu in quel codice leggi sotto forma di stringa i caratteri che FINORA hai ricevuto nel buffer seriale, ma tu devi interpretare i dati solo DOPO che avrai ricevuto \r\n (o, come si fa spesso, il carattere '\r' lo ignori perché potrebbe essere opzionale, ed analizzi quello che hai ricevuto solo quando ricevi '\n').
O magari hai una funzione che attende il terminatore di linea, oppure una qualche funzione che restituisce la stringa solo se questa è completa di terminatore.

Io consiglierei di chiedere consigli su forum di Java.
Non conosco Java, ma su internet vedo codici come questo:

/* Handle an event on the serial port. Read the data and print it. */
@Override
public synchronized void serialEvent(SerialPortEvent oEvent) 
{ if (oEvent.getEventType() == SerialPortEvent.DATA_AVAILABLE) 
  { try 
    { String inputLine = input.readLine();
      System.out.println(inputLine);
    } catch (Exception e) 
    { System.err.println(e.toString());
    }
  }
  // Ignore all the other eventTypes, but you should consider the other ones.
}

Dove vedo che viene fatto un test per tipo evento diverso da quello che testi tu

Salve ragazzi,
innanzitutto volevo ringraziarvi per le risposte date.
Sono stato fuori per un paio di giorni e non ho potuto vedere le risposte.

potrebbe essere un problema di BAUDRATE ?
anche se nella connessione alla seriale ho messo la stessa di Arduino (9600).

mando i due dati concatenati da un "&" perché credevo che il problema fosse la doppia Serial.println.

ma non è cosi.

testerò if (oEvent.getEventType() == SerialPortEvent.DATA_AVAILABLE) come indicatomi da nid69ita e cercherò in rete qualche consiglio per intercettare lo \n .

grazie mille per la disponibilità.

fcorsa:
testerò if (oEvent.getEventType() == SerialPortEvent.DATA_AVAILABLE) come indicatomi da nid69ita e cercherò in rete qualche consiglio per intercettare lo \n .

Non è esatto, nid69ita non ti ha indicato di usare la DATA_AVAILABLE, ma solamente che se tracci quell'evento quel test/if, analogamente alla Serial.available() di Arduino, sarà true non appena ti arriva anche solo UN carattere.
Quindi nid69ita ti ha consigliato, se vedi bene, di usare la input.readLine() (e non la readString) che dovrebbe attendere, appunto, una intera linea di testo cioè aspetta il carattere terminatore '\n'.

Ma questa, che esiste anche su Arduino, è in genere una funzione "bloccante" ossia il tuo codice (Java nel tuo caso) credo che non faccia altro ma resta in quella funzione finché non riceve una linea completa. Se non devi far altro e sei sicuro che avrai sempre linee complete, va anche bene così, ma non è in genere una soluzione proprio valida, cerca nei forum Java per capire come si gestisce questa cosa (immagino sempre che quantomeno dovresti verificare con una qualche funzione se nel buffer esiste un '\n' e SOLO ALLORA leggere con readLine).

potrebbe essere un problema di BAUDRATE ?
anche se nella connessione alla seriale ho messo la stessa di Arduino (9600).

Se sono impostati alla stessa velocità non vedo perché debba essere questo il problema.

mando i due dati concatenati da un "&" perché credevo che il problema fosse la doppia Serial.println.

Invece va bene perché in questo modo tu sei sicuro di interpretare il primo dato come primo valore ed il secondo come secondo: senza la distinzione rischi di interpretarli esattamente al contrario. Quindi va bene che il tuo "protocollino" preveda:

valore1&valore2\r\n

Grazie docdoc,

io uso la libreria jssc e non include la readLine().

devo spulciarmi la libreria per vedere qualche funzione che fa la stessa cosa.

Salve Ragazzi,

leggendo un po in giro per il web e come suggeritomi nelle vostre risposte sono riuscito a risolvere il problema passando in readBytes e analizzando ogni singolo byte.

posto il codice cosi da essere di aiuto per gli altri.

Grazie mille a docdoc e nid69ita per avermi dedicato del tempo.

 public void serialEvent(SerialPortEvent event) { 
		             String str="";
		             byte[] by= new byte[1];                       
		             while(true){
		                 try {             
		                     by = serialPort.readBytes(1);
		                     if(by[0]!=10 && by[0]!=13){                            
		                          if((by[0]>47 && by[0]<58)||by[0]==38){   //se è un numero oppure &
		                             str +=(char)by[0];      //accumola nella stringa 
		                          }                        
		                     }else{                       
		                         if(by[0]==13) {                                  
		                        	 System.out.println(str); 
		                        	 str="";
		                         }
		                      }               
		                 }catch (SerialPortException ex) {
		                    System.out.println(ex);
		                 }                    
		             }                           
		         }

fcorsa:
leggendo un po in giro per il web e come suggeritomi nelle vostre risposte sono riuscito a risolvere il problema passando in readBytes e analizzando ogni singolo byte.

Perfetto! E guarda che è la soluzione che in genere si usa anche in Arduino, ossia testi Serial.available e se true, leggi un carattere per volta con Serial.read() e lo accumuli dentro ad una stringa fino a che non ricevi un '\n' (ignorando '\r' se lo ricevi).