Pages: [1] 2   Go Down
Author Topic: Non riesco a leggere una stringa da seriale .....RISOLTO!!!!  (Read 2069 times)
0 Members and 1 Guest are viewing this topic.
Oristano
Offline Offline
Sr. Member
****
Karma: 0
Posts: 252
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Non riesco a leggere un stringa dalla seriale come vorrei io..
cioè sto cercando di mettere in un vettore di char la stringa che invio dalla seriale .. per il processamento successivo.

cioè se invio "ABCDEFGHIL" (senza gli apici) e fisso la lunghezza del vettore a 4, vorrei avere questo
stringa(0) ---> A
stringa(1) ---> B
stringa(2) ---> C
stringa(3) ---> D

ho cercato e letto decine di post che riguardano questo problema.
Ho capito che il problema è originato dalla velocità di lettura rispetto alla velocità di ricezione dei dati sulla seriale ..

ho fatto questo script e funziona, fintanto che ci sono le stampe su serial monitor per il debug:



Code:
#define dimVettore 5            // lunghezza max del buffer di lettura (stringa seriale)
char stringaSERIALE[dimVettore + 1]; // stringa buffer for contenente le letture estratte dal GPS
boolean fineLettura;                 // controllo sul checksum della stringa Seriale ricevuta

void setup()
{Serial.begin(4800);}

void loop()
{if (Serial.available()>0){leggiSeriale();}}

void leggiSeriale()
 {
   unsigned long count;      //interrompe la lettura dalla seriale se passano più di countMax ms senza che arrivino caratteri
   int const countMax = 5;  // limite max millisecondi senza che arrivino caratteri .. oltre chiude il ciclo di lettura (non scendere sotto i 5)
  
   int index=0;
   do    
     {
        if(Serial.available()> 0)                
         {
           stringaSERIALE[index]=Serial.read();  
           Serial.print("\n\t"); Serial.print(stringaSERIALE[index]); Serial.print("  \t"); Serial.print(stringaSERIALE[index], DEC); Serial.print("   \t index:"); Serial.print(index);
           index++; count = millis();                            
            }
            
      fineLettura = ( (index >= dimVettore) || (millis() - count > countMax));
      }
    while (!fineLettura);  
    Serial.print("\n   dopo do ---------------------\n");
 
  
     Serial.print("\n  VUOTA il BUFFER: eliminati:");
     byte tempByte;
     while (Serial.available()) {tempByte = Serial.read(); Serial.write(tempByte);}
     Serial.print("\n    ---------------------\n");
      
  
  
     Serial.print("\n INIZIO VETTORE MEMORIZZATO");
     Serial.print("\n index:"); Serial.print(index);
     for(int k=0; k<index; k++){
                            Serial.print("\n\t k=")   ; Serial.print(k);
                            Serial.print("\t   ")     ; Serial.print(stringaSERIALE[k], DEC);
                            Serial.print("\t   ")     ; Serial.print(stringaSERIALE[k]);
                          }
      Serial.print("\n FINE VETTORE MEMORIZZATO \n\n\n");
}

tutto questo funziona, ma basta che elimino una riga e già non funziona più...
Code:
#define dimVettore 5            // lunghezza max del buffer di lettura (stringa seriale)
char stringaSERIALE[dimVettore + 1]; // stringa buffer for contenente le letture estratte dal GPS
boolean fineLettura;                 // controllo sul checksum della stringa Seriale ricevuta

void setup()
{Serial.begin(4800);}

void loop()
{if (Serial.available()>0){leggiSeriale();}}

void leggiSeriale()
 {
   unsigned long count;      //interrompe la lettura dalla seriale se passano più di countMax ms senza che arrivino caratteri
   int const countMax = 5;  // limite max millisecondi senza che arrivino caratteri .. oltre chiude il ciclo di lettura (non scendere sotto i 5)
  
   int index=0;
   do    
     {
        if(Serial.available()> 0)                
         {
           stringaSERIALE[index]=Serial.read();  
           //Serial.print("\n\t"); Serial.print(stringaSERIALE[index]); Serial.print("  \t"); Serial.print(stringaSERIALE[index], DEC); Serial.print("   \t index:"); Serial.print(index);
           index++; count = millis();                            
            }
            
      fineLettura = ( (index >= dimVettore) || (millis() - count > countMax));
      }
    while (!fineLettura);  
    Serial.print("\n   dopo do ---------------------\n");
 
  
     Serial.print("\n  VUOTA il BUFFER: eliminati:");
     byte tempByte;
     while (Serial.available()) {tempByte = Serial.read(); Serial.write(tempByte);}
     Serial.print("\n    ---------------------\n");
      
  
  
     Serial.print("\n INIZIO VETTORE MEMORIZZATO");
     Serial.print("\n index:"); Serial.print(index);
     for(int k=0; k<index; k++){
                            Serial.print("\n\t k=")   ; Serial.print(k);
                            Serial.print("\t   ")     ; Serial.print(stringaSERIALE[k], DEC);
                            Serial.print("\t   ")     ; Serial.print(stringaSERIALE[k]);
                          }
      Serial.print("\n FINE VETTORE MEMORIZZATO \n\n\n");
}

... mi sta facendo impazzire.... se già non lo sono!!!! ... che cavolo gli devo fare perchè funzioni sempre ..
« Last Edit: January 07, 2013, 10:10:59 am by Paolo S » Logged

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 325
Posts: 22498
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Non ho capito assolutamente il problema
Logged


BZ (I)
Online Online
Brattain Member
*****
Karma: 252
Posts: 21282
+39 349 2158303
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Non ho capito assolutamente il problema
Se Tu non lo capisci come posso pensare di capirlo io?
Ciao Uwe
Logged

Genova
Offline Offline
Faraday Member
**
Karma: 38
Posts: 3287
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Non ho capito assolutamente il problema
Se Tu non lo capisci come posso pensare di capirlo io?
Ciao Uwe

????????????????????? questa poi non l'ho capita nemmeno io ....  smiley-grin smiley-grin
« Last Edit: January 05, 2013, 08:25:23 pm by pablos » Logged

no comment

Rovereto
Offline Offline
Full Member
***
Karma: 5
Posts: 172
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

penso che il concetto sia che non riesce ad allocare un array di char da seriale,  dando in ingresso un vettore più lungo dell'array di char dichiarato.

p.s non fai prima a salvare tutto un vettore e poi salvarti (magari in un altro array) solamente in primi n valori che ti interessano?
Logged

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 325
Posts: 22498
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Se il problema è salvare e manipolare dati di cui non si conosce la dimensione, può venire in aiuto l'oggetto String che, a differenza degli array di char, è modificabile quindi può aggiungere elementi man mano che arrivano dal canale di input.
http://arduino.cc/en/Reference/StringObject
Logged


Rome (Italy)
Offline Offline
Tesla Member
***
Karma: 120
Posts: 9183
"Il Vero Programmatore ha imparato il C sul K&R, qualunque altro testo è inutile e deviante."
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Non riesco a leggere un stringa dalla seriale come vorrei io..
cioè sto cercando di mettere in un vettore di char la stringa che invio dalla seriale .. per il processamento successivo.
cioè se invio "ABCDEFGHIL" (senza gli apici) e fisso la lunghezza del vettore a 4, vorrei avere questo
stringa(0) ---> A
stringa(1) ---> B
stringa(2) ---> C
stringa(3) ---> D

Ti sei spiegato malissimo, però se ho capito realmente il tuo problema devi estrarre i dati dalle sentenze NMEA del gps, per fare questo ti serve un parser, se è realmente per il gps esistono librerie per Arduino pronte all'uso.
Logged

Oristano
Offline Offline
Sr. Member
****
Karma: 0
Posts: 252
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Chiedo scusa ma ieri è successo un piccolo problema dopo che ho insrito mezzo post.... è mancata l'energia elettrica, poi non c'era collegamento, posi sono dovuto uscire e sono rientrato tardissimo.. quindi in realtà ho postato solo metà della descrizione...

e vi ringrazio anche per esserevi trattenuti negli improperi ....

adesso l'ho corretto ed all'incirca si dovrebbe leggere tutta la descrizione del problema che cerco di riassumere anche qui ..

il problema consiste nel mettere in un array di char (voglio fare così.. non con una stringa) ... i primi n caratteri ricevuti dalla seriale e svuotare i caratteri che eventualmente ancora ci fossero in attesa di essere letti ...


il primo schetc funziona, finche ci sono anche le righe di serial.print che uso per il debug ... nel secondo script, dove cancello una riga di debug .. non funziona più..... ci sono sopra due giorni e non trovo soluzione .. porka miseria!!!!!

... se per esempio, digito la seguente stringa "abcdefghilmno"  mi da questo output

 
Code:
dopo do ---------------------

  VUOTA il BUFFER: eliminati:
    ---------------------

 INIZIO VETTORE MEMORIZZATO
 index:5
k=0    97    a
k=1    98    b
k=2    99    c
k=3    100    d
k=4    101    e
 FINE VETTORE MEMORIZZATO



   dopo do ---------------------

  VUOTA il BUFFER: eliminati:mno
    ---------------------

 INIZIO VETTORE MEMORIZZATO
 index:5
k=0    102    f
k=1    103    g
k=2    104    h
k=3    105    i
k=4    108    l
 FINE VETTORE MEMORIZZATO
cioè il vettore alla fine contiene "fghil" anzichè i primi 5 caratteri "abcde"

invece di quello corretto che dovrebbe essere questo
Code:
97    index:0
98    index:1
99    index:2
100    index:3
101    index:4
   dopo do ---------------------

  VUOTA il BUFFER: eliminati:fghilmno
    ---------------------

 INIZIO VETTORE MEMORIZZATO
 index:5
k=0    97    a
k=1    98    b
k=2    99    c
k=3    100    d
k=4    101    e
 FINE VETTORE MEMORIZZATO
con il vettore che, correttamemte, alla fine contiene solo i primi 5 caratteri ....

credo di essere stato maggiormente chiaro ... saluti ciao
« Last Edit: January 06, 2013, 03:23:40 am by Paolo S » Logged

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 325
Posts: 22498
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

A parte che il codice è scritto un po' male.... si mette in genere una istruzione per riga, la "riga" che tu elimini in realtà sono più istruzioni.... poi gli spazi tra la fine di una istruzione ed il ";" di fine riga proprio non si possono vedere  smiley-sweat
Poi c'è un controllo che non capisco.
 fineLettura = ( (index >= dimVettore) || (millis() - count > countMax));

Fatto così, che senso ha? Carichi millis subito prima del check. Quella parte lì sarà sempre false finché ricevi caratteri. Sarà sempre vera se non li ricevi perché count non lo inizializzi con millis() prima di fare l'if.
Logged


Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 325
Posts: 22498
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

PS:
ricordati che la seriale ha un buffer in ricezione dove vengono memorizzati i caratteri che arrivano e da cui la Serial.read() va a pescare. Se non ci trova nulla può darsi che esca prima del dovuto.

Altra cosa curiosa è che della stringa
abcde-fghil-mno
guarda caso a te perde proprio i primi 5 byte nonostante sembra li abbia ricevuti.
Logged


Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 325
Posts: 22498
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Altra cosa, sempre riferita al controllo per uscire da do..while

Code:
do {
  ...
  fineLettura = ( (index >= dimVettore) || (millis() - count > countMax));
} while (!fineLettura);
Ragioniamo.
fineLettura è il risultato di un OR logico. Per uscire dal while fineLettura deve essere true perché tu fai un test !fineLettura, che cicla finché fineLettura è false, dato che !false = true. Ma fineLettura sarà vera se anche 1 sola delle 2 condizioni è vera. Per uscire basta che una delle condizioni sia false, così che fineLettura sia anch'essa true e quindi !true = false.
E' corretta questa logica?
« Last Edit: January 06, 2013, 05:02:55 am by leo72 » Logged


Oristano
Offline Offline
Sr. Member
****
Karma: 0
Posts: 252
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Grazie Leo..... allora:
A parte che il codice è scritto un po' male.... si mette in genere una istruzione per riga, la "riga" che tu elimini in realtà sono più istruzioni.... poi gli spazi tra la fine di una istruzione ed il ";" di fine riga proprio non si possono vedere  smiley-sweat
Poi c'è un controllo che non capisco.
 fineLettura = ( (index >= dimVettore) || (millis() - count > countMax));

Fatto così, che senso ha? Carichi millis subito prima del check. Quella parte lì sarà sempre false finché ricevi caratteri. Sarà sempre vera se non li ricevi perché count non lo inizializzi con millis() prima di fare l'if.


Ok... per lo stile che sicuramente è da rivedere....

il controllo dovrebbe disporre l'uscita dal do-while al verificarsi di una delle due condizioni:
1) se l'indice supera la dimesione del vettore (questo si verifica quando la stringa ricevuta  è più lunga della dimesione del vettore dove conservo i byte (char) ricevuti;
2) se invece la stringa è piu corta, al raggiungimento dell'ultimo carattere dovrebbe iniziare a contare millis - count (con count che contiene l'ultimo valore di millis di quando ha letto l'ultimo carattere, quindi appena supera il tempo max di attesa significa che non ci sono più caratteri ed esce lo stesso.

ma questa parte mi pare che funzioni bene...

ciò che non funziona è la parte che dovrebbe cancellare il buffer di ricezione della seriale, cioè questa:
Code:
     Serial.print("\n  VUOTA il BUFFER: eliminati:");
     byte tempByte;
     while (Serial.available()) {tempByte = Serial.read(); Serial.write(tempByte);}
     Serial.print("\n    ---------------------\n");

e questo, io credo, sia dovuto al fatto che mentre prima la riga che contiene le quattro istruzioni di serial print, introducono un certo ritardo, fanno si che quando l'struzine passa sul serial.available lo trova positivo, perchè nel frattempo è arrivato un altro carattere, quindi entra e cancella il buffer ...

se invece tolgo quei serial.print, passa troppo rapidamente a fare quella valutazione e serial.available è false... quindi non entra e non calcella il buffer... io credo sia quasto ma non trovo la soluzione .... ogni volt che mi sembra di aver trovato qualcosa basta che tolgo qualche serial print e non funziona più....


Logged

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 325
Posts: 22498
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Se è questo, metti un delay(5) al posto di quei Serial.print e guarda che succede. Oppure rivedi l'uscita con timeout perché secondo me la sua logica non è corretta (hai letto il mio ultimo post?).
Logged


Oristano
Offline Offline
Sr. Member
****
Karma: 0
Posts: 252
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

si Leo... se metto un delay al posto dei serial print .. funziona di nuovo tutto. Ma non mi piace la soluzione. Voglio trovare una soluziione che vada bene sempre e che non rallenti il codice più di quanto non sa srettaene necessario.

l'uscita con timeout la vedo corretta perchè:
Quote
2) se invece la stringa è piu corta, al raggiungimento dell'ultimo carattere dovrebbe iniziare a contare millis - count (con count che contiene l'ultimo valore di millis di quando ha letto l'ultimo carattere, quindi appena supera il tempo max di attesa significa che non ci sono più caratteri ed esce lo stesso.

il count viene inizializzato con millis al momento della letttura dell'ultimo carattere .... quindi esce se
(millis() - count > countMax) ... che diventa vero dopo che sono passati countMax  mS ...
mi pare che questa logica sia correttà...

sto pennsando di controllare la cancellazione del buffer con un altro controllo anzichè con seruial.available... perchè e lì che cè il punto critico...

ciao







Logged

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 325
Posts: 22498
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Se col delay funziona, allora significa che c'è qualcosa nell'implementazione dell'uscita con timeout. La logica dovrebbe essere come dici tu, ma lo sviluppo della funzione non la ricalca. Almeno penso.
Logged


Pages: [1] 2   Go Up
Jump to: