Go Down

Topic: Serial.flush() ide 1.03 NON FUNZIONA (Read 10091 times) previous topic - next topic

lestofante

Quote
Ma le informazioni sulle grandezze dei buffer, sull'interrupt usato, sul fatto che i buffer siano circolari, dove sono scritte? Sono io incapace (possibilissimo) oppure nella guida di riferimento non ci sono?


tempo fa misi le mani nel codice della libreria, per questo lo so. Purtoppo la documentazione di arduino è frammentaria e alle volte errata, molto spesso si risparmia tempo leggendosi direttamente le librerie.

Guida per principianti http://playground.arduino.cc/Italiano/newbie
Unoffical Telegram group https://t.me/genuino

testato

Grazie Lesto della spiegazione karma+1  :)

Quando scrivi che il flush ti da garanzia cge sia stato ricevuto il dato crwdo intendessi garanzia che sia stati inviato, poi se viene ricevuto non si sa, servw una gestione degli handshake per quello.

Ma il flush quindi esiste solo in trasmissione ? Oppure anche in ricezione ? Come lo si deve intendere per la ricezione ?
- [Guida] IDE - http://goo.gl/ln6glr
- [Lib] ST7032i LCD I2C - http://goo.gl/GNojT6
- [Lib] PCF8574+HD44780 LCD I2C - http://goo.gl/r7CstH

lestofante

non esiste in ricezione, o meglio esisteva per la vecchia versione di SoftSerial e svuotava il buffer di lettura... cosa abbastanza inutile data la sua natura circolare, oltre che essere fuorviante con la flush() che come spiegato è uno standard di fatto; esiste in tutti i linguaggi e in tutti funziona allo stesso modo. Diciamo che al massimo potevano chiamarla clear()  :smiley-mr-green:

non a caso, ora che tutto ciò che scrive/legge su flusso è sottoclasse della classe Stream, la funzione flush è stata uniformata allo standard. Tra l'altro, in teoria, ora anzichè usare serial potete usare:
Code: [Select]
Stream qualcosa = Serial;
e fare le vostre cose con qualcosa (ovviamente limitati da ciò che offre la classe Stream). Quando vorrete passare da Serial a File, basterà cambia la riga di codice nel modo corretto, tipo
Code: [Select]
Stream qualcosa = File("log.txt");

e così via. In teoria anche i2c, spi etc. POTREBBERO divenire sottoclassi di strem.
Guida per principianti http://playground.arduino.cc/Italiano/newbie
Unoffical Telegram group https://t.me/genuino

astrobeed

Scientia potentia est

testato

e' un nuovo modello arduino ?  :smiley-yell:

x Lesto:
Quote
Sorry, you can't repeat a karma action without waiting 1 hours.

:)
- [Guida] IDE - http://goo.gl/ln6glr
- [Lib] ST7032i LCD I2C - http://goo.gl/GNojT6
- [Lib] PCF8574+HD44780 LCD I2C - http://goo.gl/r7CstH

lestofante


Questa è la vera flush()  :smiley-mr-green:


uff hanno recentemente bloccato anche youtubba al lavoro... ma immagino di che genere di flush si tratti :)
Guida per principianti http://playground.arduino.cc/Italiano/newbie
Unoffical Telegram group https://t.me/genuino

testato

sono ricapitato su questo topic perche' sto' cercando info per un rpoblema che ho su seriale.

due domande:
1) lesto dice che il buffer della seriale e' di tipo Ring, ma ricordo un intervento di Astro che diceva fosse di tipo normale, cioe' 64byte da riempire, una volta pieno si perde tutto quello che arriva (c'e' un nome tecnico per questo tipo di buffer ?) Come stanno le cose ? e' cambiato qualcosa con la 1.5 ?

2) ho uno sketch pesantissimo che impiega molto tempo per concludere un ciclo di loop, questo mi comporta (almeno e' la mia prima ipotesi di diagnosi) che il buffer della seriale vada in overfow. Non potendo velocizzare il loop quali sono le soluzioni ?

3) Nel caso in cui non sia importante ricevere tutti i dati si puo' interropmere il funzionamento della seriale via interrupt ed usarla in polling ?

Grazie di eventuali vostri pareri
- [Guida] IDE - http://goo.gl/ln6glr
- [Lib] ST7032i LCD I2C - http://goo.gl/GNojT6
- [Lib] PCF8574+HD44780 LCD I2C - http://goo.gl/r7CstH

lestofante

1. il buffer è un ring buffer, ovvero funziona ad anello. Quando l'array di buffer è pieno, si continua a scrivere partendo dall'inizio. Ci sono 2 indici, uno indica dov'è l'ultimo byte letto, l'altro il prossimo byte da scrivere. Se non leggi abbastanza velocemente, il byte più nuovo sovrascrive quello vecchio.

vedi: http://en.wikipedia.org/wiki/Circular_buffer

se invece quando è pieno fai in modo che perda i dati NUOVI, allora sarebbe una coda con limite di dimensione.

2. o incrementi il buffer, oppure ogni tanto ti fermi a svuotarlo, fino a raggiungere una situazione di consistenza. Oppure invii un segnale es. "BBB" prima di un comando, in modo che quando leggi la seriale cerchi quel valore e leggi il contenuto successivo. In tal modo butti via tutti i comandi arrivati e totalmente/parzialmente sovrascritti.
Oppure mettui in piedi un sistema in cui arduino quando è prondo manda un seganle/carattere (richiesta) e l'altra parte risponde con i dati. (risposta)

3. Sì, si può fare, è la vecchia SoftSerial (ide <1.0) si metteva in ascolto SOLO quando facevi read()... però perdi tutte le accelerazioni HW, ed in oltre alla fine devi comunque devi mettere in piedi un sistema di richiesta/risposta o individuazione di inizio messaggio... tanto vale usare il sitema 2.
Guida per principianti http://playground.arduino.cc/Italiano/newbie
Unoffical Telegram group https://t.me/genuino

astrobeed

1) lesto dice che il buffer della seriale e' di tipo Ring, ma ricordo un intervento di Astro che diceva fosse di tipo normale, cioe' 64byte da riempire, una volta pieno si perde tutto quello che arriva (c'e' un nome tecnico per questo tipo di buffer ?) Come stanno le cose ? e' cambiato qualcosa con la 1.5 ?
Ante 1.0 il buffer della seriale era un normale array, una volta pieno perdevi i dati in arrivo fino a che non lo svuotavi, post 1.0 è diventato un ring buffer, una volta pieno perdi i dati più vecchi non letti.
Scientia potentia est

testato

#24
Nov 02, 2014, 05:19 pm Last Edit: Nov 02, 2014, 05:38 pm by Testato
karma ad entrambi,
prima di leggere il messaggio ero gia' andato verso la soluzione 2  :)
leggo il primo byte con la Serial.read, e solo se e' il mio marcatore continuo a leggere con la Serial.readBytes.

vi faro' sapere se funge
- [Guida] IDE - http://goo.gl/ln6glr
- [Lib] ST7032i LCD I2C - http://goo.gl/GNojT6
- [Lib] PCF8574+HD44780 LCD I2C - http://goo.gl/r7CstH

lestofante

funge a meno che non invii dati grezzi.
Spesso a me capita di inviare i float "grezzi" (cioè 4 byte invece che la rappresentazione a char che può usare molti più byte) e ovviamente questi 4 byte possono avere qualsiasi valore; quindi il mio "marcatore" deve essere di 5 byte. Poi in realtà io invio più float di seguito, quindi la lunghezza del marcatore dobrebbe essere 4*numeroFloat + 1, però dato che so che il valore di float è all'interno di dati parametri, uso un float fuori parametro come divisiore, risparmianbdo un sacco di byte.
Guida per principianti http://playground.arduino.cc/Italiano/newbie
Unoffical Telegram group https://t.me/genuino

lestofante

dopo aver litigato un pò con il problema di testato, ho analizzato il codice della HarwdareSerial e a quanto il pare il circular buffer NON viene sovrascritto; quando il buffer è pieno (metodo http://en.wikipedia.org/wiki/Circular_buffer#Always_Keep_One_Slot_Open) i dati successivi vengono scartati.

Sono andato indietro con la storia di HardwareSerial e pare che sia SEMPRE stato così.
Guida per principianti http://playground.arduino.cc/Italiano/newbie
Unoffical Telegram group https://t.me/genuino

testato

yep  :)
ci stiamo lavorando a 4 mani.
la mia impressione, accreditata da un debugging hadrware, e' sempre stata che il buffer si riempiva e quando andavo a creare il payload al limite del riempimento mi si alterava l'array che andavo appunto a rimepire con serial.readbytes.
Per questo chiedevo se si fosse sicuri che il buffer fosse di tipo Ring o Standard.

Con l'opzione2 messa in campo, passando per un ipotesi anche di staccare gli interrupt, il risultato non cambiava, sto buffer sembrava comportarsi come un normale array standard in cui dopo aver letto il byte 64 si va a leggere il byte presente nell'indice 0.

A questo punto Lesto leggendo nel sorgente si accorge che abbiamo a che fare con un Ring Buffer per quanto rigiarda la tipologia, ma che non e' implementata la sovrascrittura ad anello in caso di overflow

Ho risolto usando il vecchio Flush (inteso nel vecchio modo di svuotatore di buffer entrata) cosi':
Code: [Select]
while (Serial1.read() >= 0);

- [Guida] IDE - http://goo.gl/ln6glr
- [Lib] ST7032i LCD I2C - http://goo.gl/GNojT6
- [Lib] PCF8574+HD44780 LCD I2C - http://goo.gl/r7CstH

lestofante

il problema, però, è che NON essendo a riscriuttura è un bel problema.

mettiamo in chiaro un pò di concetti;
quando prendiamo i nostri dati (payload) e ci aggiungiamo la seiuqyenza di inizio (header), otteniamo quello che possiamo definire un pacchetto (header + payload, notare che l'header puoi anche metterlo in fondoi se ti garba)

quando il buffer si riscrive, sei sicuro che buttai via X byte fino ad ottenere l'header, poi il pacchetto è corretto e valido
questo perchè l'array circolare taglia sempre ad inizio messaggio, quindi basta trovare la sequenza per essere certi che i dati da lì in poi sono corretti (se letti bloccando gli interrupt, per evitare sovrascritture mentre si legge)

invece con un buffer che non si riscrive, si vanno a perdere dati a FINE buffer, ovvero tra 64byte.. e chi lo sa cosa ci sarà tra 64byte? quel pacchetto diventa invalido, ma non esiste modo di individuare la sua invalidità se non ci và di sedere che è un byte di seuqenza, o non si implementa un controllo del pacchetto con CRC

credo che il problema di arduino di usare il taglio alla fine permetta di avere una readByte che NON usa bloccare gli interrupt, ma insertisce questo problema di dati invalidi impossibili da individuare. Trovate la mia analisi corretta?
Guida per principianti http://playground.arduino.cc/Italiano/newbie
Unoffical Telegram group https://t.me/genuino

PaoloP


Go Up