Oristano
Offline
Full Member
Karma: 0
Posts: 233
Arduino rocks
|
 |
« on: January 05, 2013, 12:56:37 pm » |
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: #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ù... #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
|
|
|
|
|
Forum Moderator
Italy
Online
Brattain Member
Karma: 226
Posts: 17011
Don't know what I do
|
 |
« Reply #1 on: January 05, 2013, 05:21:38 pm » |
Non ho capito assolutamente il problema
|
|
|
|
|
Logged
|
|
|
|
|
BZ (I)
Offline
Brattain Member
Karma: 172
Posts: 16143
+39 349 2158303
|
 |
« Reply #2 on: January 05, 2013, 06:10:15 pm » |
Non ho capito assolutamente il problema
Se Tu non lo capisci come posso pensare di capirlo io? Ciao Uwe
|
|
|
|
|
Logged
|
|
|
|
|
Genova
Offline
Faraday Member
Karma: 14
Posts: 2531
|
 |
« Reply #3 on: January 05, 2013, 06:19:34 pm » |
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 .... 
|
|
|
|
« Last Edit: January 05, 2013, 08:25:23 pm by pablos »
|
Logged
|
Meglio imparare dalle cose inutili piuttosto che non imparare niente. [Arduino Mega R3 + Ethernet shield W5100 + SD card 8Gb FAT32]
|
|
|
|
Rovereto
Offline
Jr. Member
Karma: 1
Posts: 82
|
 |
« Reply #4 on: January 05, 2013, 06:47:13 pm » |
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
|
|
|
|
|
Forum Moderator
Italy
Online
Brattain Member
Karma: 226
Posts: 17011
Don't know what I do
|
 |
« Reply #5 on: January 06, 2013, 01:38:12 am » |
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
Tesla Member
Karma: 76
Posts: 7539
"Il Vero Programmatore ha imparato il C sul K&R, qualunque altro testo è inutile e deviante."
|
 |
« Reply #6 on: January 06, 2013, 01:46:42 am » |
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
Full Member
Karma: 0
Posts: 233
Arduino rocks
|
 |
« Reply #7 on: January 06, 2013, 03:14:28 am » |
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 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 a 97 index:0 b 98 index:1 c 99 index:2 d 100 index:3 e 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
|
|
|
|
|
Forum Moderator
Italy
Online
Brattain Member
Karma: 226
Posts: 17011
Don't know what I do
|
 |
« Reply #8 on: January 06, 2013, 04:48:37 am » |
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  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
|
|
|
|
|
Forum Moderator
Italy
Online
Brattain Member
Karma: 226
Posts: 17011
Don't know what I do
|
 |
« Reply #9 on: January 06, 2013, 04:55:21 am » |
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
|
|
|
|
|
Forum Moderator
Italy
Online
Brattain Member
Karma: 226
Posts: 17011
Don't know what I do
|
 |
« Reply #10 on: January 06, 2013, 04:59:57 am » |
Altra cosa, sempre riferita al controllo per uscire da do..while 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
Full Member
Karma: 0
Posts: 233
Arduino rocks
|
 |
« Reply #11 on: January 06, 2013, 12:16:43 pm » |
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  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: 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
|
|
|
|
|
Forum Moderator
Italy
Online
Brattain Member
Karma: 226
Posts: 17011
Don't know what I do
|
 |
« Reply #12 on: January 06, 2013, 04:12:17 pm » |
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
Full Member
Karma: 0
Posts: 233
Arduino rocks
|
 |
« Reply #13 on: January 07, 2013, 02:16:30 am » |
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è: 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
|
|
|
|
|
Forum Moderator
Italy
Online
Brattain Member
Karma: 226
Posts: 17011
Don't know what I do
|
 |
« Reply #14 on: January 07, 2013, 03:16:06 am » |
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
|
|
|
|
|
|