Visualizzazione dei risultati da 1 a 4 su 4
  1. #1
    Utente di HTML.it
    Registrato dal
    Feb 2004
    Messaggi
    51

    Error: java.lang.NumberFormatException: empty String

    Salve,
    Sto cercando di far comunicare Arduino con un programma in java. Per fare questo sto usando la libreria JSSC. In Arduino ho scritto un semplice sketc che invia sulla porta seriale i valori generati da un potenziometro su una porta analogica, diciamo che invia valori compresi tra 0 e 255. Dall'altra parte il programma in java deve ascoltare l'invio di questi dati e visualizzarli a monitor. Bene e la cosa funziona, ma quando vado a trasformare questi valori (0-255) in valori che esprimono i volt (0-5V) mediante un metodo di conversione da me scritto (pubblic String toVolt(String str)) e che ho testato e funziona perfettamente, dopo un po il programma termina con il seguente errore:

    Exception in thread "EventThread COM3" java.lang.NumberFormatException: empty String
    at sun.misc.FloatingDecimal.readJavaFormatString(Floa tingDecimal.java:1842)
    at sun.misc.FloatingDecimal.parseDouble(FloatingDecim al.java:110)
    at java.lang.Double.parseDouble(Double.java:538)
    at rserial.Rserial.toVolt(Rserial.java:61)
    at rserial.Rserial.access$000(Rserial.java:8)
    at rserial.Rserial$SerialPortReader.serialEvent(Rseri al.java:25)
    at jssc.SerialPort$EventThread.run(SerialPort.java:11 12)

    Per tamponare la situazione ho filtrato cos� (dove str � la stringa in arrivo sulla COM):

    if(str!=null && !str.isEmpty()){
    str=toVolt(str);
    System.out.println(str);
    }


    Ma non ne vuole sapere, gira per un po, mi da diversi valori in volt poi ad un certo punto va in crash e mi da l'errore. Ora come � possibile che possa passare una stringa vuota se l'if la dovrebbe bloccare?
    Vi allego il codice:

    Java
    import jssc.SerialPort;
    import jssc.SerialPortEvent;
    import jssc.SerialPortEventListener;
    import jssc.SerialPortException;

    public class Rserial {
    SerialPort serialPort;

    public Rserial(){
    serialInitialize();
    }
    public static void main(String[] args) {
    Rserial rs = new Rserial();
    }

    public class SerialPortReader implements SerialPortEventListener {

    public void serialEvent(SerialPortEvent event) {
    try {
    String str = serialPort.readString();

    //if(str!=null && !(str.compareTo("")==0)){
    if(str!=null && !str.isEmpty()){
    str=toVolt(str);
    System.out.println(str);
    }
    }catch (SerialPortException ex) {
    System.out.println(ex);
    }
    }
    }
    public void serialInitialize() {
    try {
    serialPort = new SerialPort("COM3");
    // apri la porta seriale
    System.out.println("Port opened: " + serialPort.openPort());
    // imposta i parametri della porta
    System.out.println("Params setted: " + serialPort.setParams(115200, 8, 1, 0));
    Thread.sleep(2000);//Dai tempo ad arduino di resettarsi

    //Aggiungi un'interfaccia attraverso la quale riceveremo informazioni sugli eventi
    serialPort.addEventListener(new SerialPortReader());
    System.out.println("La porta �: " + serialPort.getPortName());
    System.out.println("PRONTO");
    } catch (SerialPortException | InterruptedException ex){
    System.out.println(ex);
    }
    }
    private String toVolt(String str){
    double dbt,dbr;
    if(str.length()>3) str=str.substring(0, 2);
    dbt = Double.parseDouble(str);//da stringa a double
    dbr=(dbt*5)/255;
    dbr=roundD(dbr,2.0);
    String ris=Double.toString(dbr);
    return(ris);
    }
    private double roundD(double dap,double cfr){
    double dv = Math.pow(10,cfr);
    double n=Math.round(dap*dv);
    double res = n/dv;
    return(res);
    }
    }

    Arduino
    int ledPin = 9;
    int potPin = A0;
    int valPot, numPot;
    int memPot;

    void setup(){
    Serial.begin(115200);
    pinMode(ledPin, OUTPUT);
    pinMode(potPin, INPUT);
    }


    void loop(){
    valPot=analogRead(potPin);
    numPot = map(valPot,0,1023,0,255);
    if ((numPot < memPot-1 || numPot > memPot+1)){//se lo muovi
    memPot=numPot;
    analogWrite(ledPin,numPot);
    Serial.println(numPot);
    }
    }


    Sto impazzendo non riesco a capire il perch�.
    Se mi date una mano ne sarei grato.
    Grazie

  2. #2
    Utente di HTML.it
    Registrato dal
    Oct 2014
    residenza
    Padova
    Messaggi
    361
    Guarda del contesto non me intendo minimamente, ma fossi in te io userei un blocco try-catch (che vedo già nel codice) anche per la parte in cui fai la conversione da String a double (ad ora stai "catturando" solo SerialPortException).

    Questo almeno che tu non sia sicuro che puoi avere solo stringhe ben formate o al limite vuote, ma con il try-catch ti metti al riparo da ogni situazione pericolosa, e non credo che faccia alcuna differenza in termini di efficienza. Poi nel blocco catch puoi fare quello che vuoi, anche lanciare una nuova eccezione più informativa, per ora mi sembra che tu ignori semplicemente il valore ...

    Quando al isEmpty (), la documentazione di String è chiara:


    public boolean isEmpty()


    Returns true if, and only if, length() is 0.
    Bisognerebbe quindi vedere cosa passi effettivamente, anche uno spazio farebbe fallire il test. In teoria con un banale print con la stringa racchiusa tra apici o qualsiasi altra cosa dovresti accorgertene però ...

  3. #3
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,254
    Quote Originariamente inviata da cersil Visualizza il messaggio
    Sto impazzendo non riesco a capire il perché.
    Premetto che conosco poco/vagamente la jssc. Il punto è che stai "impazzendo" perché molto probabilmente non conosci bene la jssc e/o la comunicazione su seriale. Una prima questione: sei sicuro che ad ogni serialEvent hai sempre la lettura della stringa completa? Non è affatto detto che sia così!
    Se guardi ad esempio qui vedrai che il serialEvent è stato scritto in modo più "oculato": if(event.isRXCHAR() && event.getEventValue() > 0)
    Ovvero, se l'evento è per la ricezione di byte, allora usa getEventValue() per sapere quanti byte sono disponibili. E lo usa anche per il readString. Questo però vuol dire che non è detto che ricevi l'intera stringa.
    E allora ... vuol dire che non puoi elaborare la stringa ad ogni evento. Devi fare in modo che chi riceve possa accumulare i dati ed elaborarli solo al termine esatto della stringa. Dato che per inviare usi Serial.println(numPot), questa terminazione ce l'hai! Perché è il "newline", Carriage return + Line feed. Quindi devi attendere questi due byte e solo allora scarti questi CR/LF e puoi elaborare la stringa che hai ricomposto.

    In sostanza: prima di "partire in quarta", cerca di comprendere meglio come vengono letti i byte, con quali/quanti eventi della jssc.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    Java Versions Cheat Sheet

  4. #4
    Utente di HTML.it
    Registrato dal
    Feb 2004
    Messaggi
    51
    Grazie per avermi risposto.
    Ho utilizzato il codice che mi a suggerito andbin ma il problema persiste e deve dipendere dal fatto che non ho ad ogni serialEvent la stringa completa. L'ho verificato cosi: System.out.println("|"+str+"|"); ed ho avuto questo:
    |164
    |
    |170
    |
    |1|
    |80
    |
    |185
    |
    ...
    |160
    |
    |
    |
    |
    |155
    |

    Come si può notare, sto muovendo il potenziometro e dovrebbero arrivare dati tipo: 164 170 180 185 ma invece di 180 è arrivato 1 senza \n poi un 80 con \n. Si può notare che arrivano anche con un solo \n (le prime 2 | ), anche se non capisco cosa significhi la terza | ?.
    Scusate ma sono proprio agli inizi e non saprei come fare ad accumulare i dati per ricomporre la stringa.
    Se mi scrivete due righe di codice ve ne sarei grato.

    Rimane il problema della conversione a volt mediante l'uso di str=toVolt(str); è giusto che se le do in pasto una stringa vuota come ogni tanto mi arrivano lui mi da errore. Diciamo ho risolto (secondo me in modo sporco) catturando l'eccezione con un try catch e nel catch le faccio leggere la successiva stringa:

    try{
    str=toVolt(str);
    }catch (NumberFormatException ecp) {
    System.out.println(ecp);
    str = serialPort.readString();
    }

    Ma non mi sembra il massimo.
    Per escludere i dati null e stringhe vuote avevo messo:

    if(str!=null && !str.isEmpty(){ esegui se no salta...

    ma come dice Ansharja isEmpty() ritorna true solo se la stringa è lunga 0 se contiene un solo \n la stringa è vuota ma non la riconosce come tale.
    L'ideale sarebbe dare una ripulita ad i dati in arrivo eliminare quelli vuoti e parziali e far passare solo le stringhe intere, allora non avrei problemi.
    Vi ringrazio ancora per la cortesia.

  5. #5
    Utente di HTML.it
    Registrato dal
    Feb 2004
    Messaggi
    51
    Salve,
    ho risolto il problema ma subito se ne è presentato un'altro.
    Invece di usare serialPort.readStrings(); ho usato serialPort.readBytes(); ed ho accumulato i byte in arrivo in una stringa fino ad incontrare il carattere LF(ascii 13) e CR(ascii10) che la terminano:

    codice:
         static String str="";
         static byte by[]= new byte[1];
         ...
    
         String stv="";
         try { 
               by = serialPort.readBytes(1);
               if(by[0]!=13 && by[0]!=10){//se diverso da LF eCR
                    str +=(char)by[0]; //converti il byte in char ed aggiungilo alla stringa 
               }else{
                    if(by[0]==10) {//se invece siamo giunti alla fin della stringa
                          System.out.println(str);//stampami la stringa ricomposta su consol
                          try{
                                stv=toVolt(str);// converti la stringa 0-1023 in volt 0.00-5.00
                                System.out.println(stv);//stampa i volt su consol
                                //jLabel3.setText(stv);//visualizza i volt sulla label
                          }catch(NumberFormatException nec){
                                System.out.println(nec);
                          }
                          str=""; 
                   }
              } 
          }catch (SerialPortException ex) {
              System.out.println(ex);
         }

    E la cosa funziona:
    1023
    5.00
    1023
    5.00
    1023
    5.00

    Solo che quando vado a far visualizzare il risultato sulla label con jLabel3.setText(stv); (riga 216) mi da questo errore:

    Exception in thread "EventThread COM3" java.lang.NullPointerException
    at arduinorgb.cFrame$SerialPortReader.serialEvent(cFr ame.java:216)
    at jssc.SerialPort$EventThread.run(SerialPort.java:11 12)

    Come è possibile la stringa stv l'ha appena stampata su consol senza problemi (5.00) e poi la valuta come null quando la passo a jLabel3.setText(stv);!?
    Grazie per l'eventuale aiuto.

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2024 vBulletin Solutions, Inc. All rights reserved.