Seriale 0.23 vs 1.02 vs 1.51

vero, i bit di start e stop.
ma i 10bit di ogni carattere entrano nel buffer oppure lo star e stop viene eliminato in hardware dalla uart ?

Il delay 1 e' presente di defoult in tutti gli sketch che gestiscono la seriale, non l'ho messo io, e cmq ripeto che ho rpovato a toglierlo e non riceve quasi piu' nulla, riceve solo una decina di caratteri, quindi e' giusto che ci sia, ed e' giusto che sia di un millisecondo

Testato:
vero, i bit di start e stop.
ma i 10bit di ogni carattere entrano nel buffer oppure lo star e stop viene eliminato in hardware dalla uart ?

Sono segnali usati solo in trasmissione. Fai finta proprio che non esistano. Tu devi ragionare: spedisco 1 byte, mi arriva 1 byte. Non devi fare i conti: allora, 8 bit ma diventano 10 in trasmissione che però tornano 8 quando li salvo... diventi grullo per nulla :stuck_out_tongue_closed_eyes:

Il delay 1 e' presente di defoult in tutti gli sketch che gestiscono la seriale, non l'ho messo io, e cmq ripeto che ho rpovato a toglierlo e non riceve quasi piu' nulla, riceve solo una decina di caratteri, quindi e' giusto che ci sia, ed e' giusto che sia di un millisecondo

Mai visto prima. Novità per me. Dov'è che c'è?

in giro c'e' un po' dappertutto, credevo fosse uno standard, vedi ad esempio questo che usa addirittura 100ms
http://wiring.org.co/cgi-bin/yabb/YaBB.pl?num=1218069222

cmq se lo tolgo puff, solo 10 caratteri arrivano. a questo punto posso provare a cambiare metodo di ascolto della seriale, quale mi consigli ?
ho visto ad esempio che uno degli esempi ufficiali si riserva uno spazio proprio per la strnga da ricevere, vedi esempi-Communication-SerialEvent, e' buona cosa secondo te ?

void setup() {
  // initialize serial:
  Serial.begin(9600);
  // reserve 200 bytes for the inputString:
  inputString.reserve(200);
}

Ultima idea che mi e' venuta, ma non c'e' modo di dichiarare buffer differenti per rx e tx. se non devo spedire nulla sono veramente sprecati 256byte per tx

Testato:
in giro c'e' un po' dappertutto, credevo fosse uno standard, vedi ad esempio questo che usa addirittura 100ms
http://wiring.org.co/cgi-bin/yabb/YaBB.pl?num=1218069222

L'esempio citato è agganciato ad un post del 2008, però su Wiring. Conosci Wiring? Com'era Wiring nel 2008? Usava la seriale gestita da interrupt oppure no? Io non so risponderti. Un delay(1) a che serve? A far sì che arrivi un carattere altrimenti esci dal check? Allora forse è da rivedere quel check?
Boh, senza vedere tutto il codice non so risponderti. Io non ho mai usato delay di 1 ms prima di controllare la seriale.

cmq se lo tolgo puff, solo 10 caratteri arrivano. a questo punto posso provare a cambiare metodo di ascolto della seriale, quale mi consigli ?
ho visto ad esempio che uno degli esempi ufficiali si riserva uno spazio proprio per la strnga da ricevere, vedi esempi-Communication-SerialEvent, e' buona cosa secondo te ?

void setup() {

// initialize serial:
 Serial.begin(9600);
 // reserve 200 bytes for the inputString:
 inputString.reserve(200);
}

Secondo me questo l'hanno fatto per aggirare il buffer di 64 byte senza metter mano alla libreria. Quindi è una soluzione che va bene anche per utenti non capaci/non desiderosi di armeggiare con i file del core.

Ultima idea che mi e' venuta, ma non c'e' modo di dichiarare buffer differenti per rx e tx. se non devo spedire nulla sono veramente sprecati 256byte per tx

Certamente.
Basta cambiare quella porzione di codice che ti ho linkato inserendo 2 define al posto di uno (per mettere la dimensione del buffer RX e di quello TX) e poi modificare i file CDC.cpp e HardwareSerial.cpp: ci sono 19 occorrenze in cui compare SERIAL_BUFFER_SIZE, devi controllarle tutte e verificare se sono da cambiare.

attenzione che sono buffer circolari: se lo riempi non rimani in attesa ma sovrascrivi i dati più vecchi. il fatto che se mandi più di circa 200 caratteri si impalla tutto è perchè immagino che hai creato la stringa di 200 e passa caratteri, quindi un 3° "buffer" nella ram! anche se la salvi in flash nel momento in cui viene usata mi pare venga caricata in un'area ram ad hoc.
Se invece in un for scrivi i numeri da 0 a 1000, ti accorgerai del fatto del buffer circolare (perdita di dati) però dovresti vedere arrivare gli utimi TX buffer size byte!

grazie leo del tuo parere, faro' delle rpove con il reserve e riporto i risultati.

lesto la stringa mi arriva dal pc, non la creo internamente ad arduino.
tu cosa intendi ?
la stringa che ricevo resta sempre nella ram, non la scrivo mai su flash, perche' cambia spesso, cioe' ogni volta che premo un pulsante sul pc parte sta stringa via seriale, e la acchiappo da arduino che la visualizza su lcd, quindi non la scrivo mai sulla flash di arduino. se spengo arduino perdo la stringa, e' voluto.

io credo funzioni cosi', datemene conferma:
Quando inizio a ricevere la stringa i caratteri vanno nel buffer, ci entrano a 115200bps. Arduino per conto suo, in modo asincrono, inizia a prendere carattere per carattere e metterlo nel buffer, che sarebbe un pezzo della ram.
Pero', questo e' importante, ad ogni carattere che preleva dal buffer e lo passa in ram, lo cancella dal buffer. Quindi non e' che i 200 caratteri occupano 200byte nel buffer e 200 nella ram, ne occupano sempre 200 in tutto, anche durante l'operazione di trasferimento.

E' corretto ?

Non potendo velocizzare arduino, mi verrebbe da dire: Basta che abbasso a 9600 la seriale di arduino ?
In questo modo mi rrivano piu' lentamente i caratteri ? (questo va anche nella direzione indicata da Astro credo)

Astro quando dici:

astrobeed:
Dall'IDE 1.x il buffer è di 64 caratteri in ricezione e 64 caratteri in trasmissione, tutti e due sono gestiti tramite interrupt quindi per inviare tot caratteri Arduino non si ferma fino a che non sono stati trasmessi tutti i caratteri

Intendi che non ci sono problemi in trasmissione ? non parli di ricezione. In ricezione il fatto che sia gestita da interrupt e' irrilevante rispetto al problema Ring ? cioe' di sovrascrittura a rotazione dello spazio di memoria ?

karma per tutti :slight_smile:

I buffer di cui si parla sono solo quelli SW, cioè gli array creati e gestiti da HardwareSerial.cpp e .h.
Come buffer hardware l'Atmega328 ha 2 registri e basta. Il primo è un registro a scorrimento in cui viene composto il dato man mano che arrivano i suoi bit. Una volta che è stata completata la ricezione il dato viene copiato in un altro registro, da cui il codice può leggerlo. Quando viene copiato in questo secondo registro, viene attivato un interrupt di ricezione terminata e dato pronto. E' a questo punto che scatta la ISR, che preleva il byte e lo copia nel buffer SW di cui stiamo parlando.

la stringa mi arriva dal pc

ok, ma il problema rimane, credo, vedi dopo

Pero', questo e' importante, ad ogni carattere che preleva dal buffer e lo passa in ram, lo cancella dal buffer. Quindi non e' che i 200 caratteri occupano 200byte nel buffer e 200 nella ram, ne occupano sempre 200 in tutto, anche durante l'operazione di trasferimento.

ok, il byte viene letto ed entra nella prossima cella del buffer, se il buffer è pieno sovrascrive il byte più vecchio. Lo spazio del buffer è fisso.
Però poi prelevi il byte, e lo metti nel buffer dei dati destinati all'LCD. Sempre che possieda un buffer SW. Magari questo buffer esiste ed è dinamico, quindi è la libreria dell'LCD che intasa la ram. Che libreria usi?

Non potendo velocizzare arduino, mi verrebbe da dire: Basta che abbasso a 9600 la seriale di arduino ?
In questo modo mi rrivano piu' lentamente i caratteri ?

sì ma è un pagliativo, bisogna capire bene da che parte arriva l'intasamento della ram o comunque ciò che impalla il micro.

Intendi che non ci sono problemi in trasmissione ? non parli di ricezione. In ricezione il fatto che sia gestita da interrupt e' irrilevante rispetto al problema Ring ? cioe' di sovrascrittura a rotazione dello spazio di memoria ?

stiamo parlando di ricezione, quindi il problema non si pone. In trasmissione prima la scrittura ti bloccava il codice finchè tutto non era scritto; ora tutto viene salvato in un buffer circolare e l'invio lavora tramite interrupt. Quindi se scrivi nel buffer più velocemente di quanto esso si svuoti vai a riscrivere i byte più vecchi che verranno persi. Ma chissene, ora pensiamo al TX che è più semplice usando un sistema "universale" in tutte le versioni della lib.

non si dice palliativo ? :slight_smile:

cmq la libreria e' la standard dell'IDE arduino

uff precisino :stuck_out_tongue:

la libreria è bloccante, quindi in teoria nessun problema da quella parte... uhmmm molto strano

stavo pensando pero', che al primo invio io ricevo sti 200byte, li metto in ram, e quindi in ram sono occupati 200byte, quando invio per la seconda volta i 200Byte prima devono essere ricevuti, e poi vanno a sostituire i 200 vecchi giusto ?

dato = stringadaseriale

ora quando ricevo i nuovi 200byte, nell'istante prima che vengono copiati in "dato" la ram e' occupata sia dalla stringa vecchia che dalla nuova secondo voi ? a questo punto occuperei 400Byte per un tot di tempo

che poi, scusate se rompo troppo, ma voi potete fare una prova in tal senso ? quindi un programmino che invia 500 caratteri via seriale ad arduino. se anche voi avete problemi e' interessante.

allora esiste un piccolo buffer HW, una specie di micro ram dedicata alla seriale (credo forse un paio di registri, ma non ho mai letto nulla al riguardo). quando arriva un byte seriale, viene parcheggiato in questo buffer e viene lanciato un inerrupt. l'interrupt prende questo byte e lo "sposta" nel buffer seriale.

Il buffer seriale è creato dal setup, ed è fisso, quindi dal memnto in cui chiami setup hai X byte di RAM in meno ma non cambiano più.

credo ti riferisci a quello che ha gia' spiegato leo la pagina precedente.

cmq non mi sono spiegato, intendo dire questo:
0) i dati dall'esterno entrano in questo buffer hw che non ha modo di perderli, se ho capito, cioe' il rpoblema non e' qui

  1. i dati passano nel buffer ring da 256byte (l'ho modificato io, originariamente era 64, grazie a leo)
  2. pianpiano questo viene svuotato e i caratteri passano nella ram di arduino (li' restano, li visualizzo su lcd ma non li metto in nessun altro posto)
  3. la ram tiene in questo momento i 200char, quando invio i nuovi 200char questi fanno la stessa strada dei primi, pero' non so come si comporta la fase finale, cioe' i 200 nuovi sovrascrivono i 200 vecchi ? un carattere alla volta ? oppure ci saranno due spazi di ram occupati, quelli vecchi e quelli nuovi ? cioe' in un determinato istante servono 400Byte di spazio utile per fare la copia ?

lesto:
allora esiste un piccolo buffer HW, una specie di micro ram dedicata alla seriale (credo forse un paio di registri, ma non ho mai letto nulla al riguardo). quando arriva un byte seriale, viene parcheggiato in questo buffer e viene lanciato un inerrupt. l'interrupt prende questo byte e lo "sposta" nel buffer seriale.

Il buffer seriale è creato dal setup, ed è fisso, quindi dal memnto in cui chiami setup hai X byte di RAM in meno ma non cambiano più.

Non si legge più quello che scrivono gli amici? :stuck_out_tongue:

leo72:
I buffer di cui si parla sono solo quelli SW, cioè gli array creati e gestiti da HardwareSerial.cpp e .h.
Come buffer hardware l'Atmega328 ha 2 registri e basta. Il primo è un registro a scorrimento in cui viene composto il dato man mano che arrivano i suoi bit. Una volta che è stata completata la ricezione il dato viene copiato in un altro registro, da cui il codice può leggerlo. Quando viene copiato in questo secondo registro, viene attivato un interrupt di ricezione terminata e dato pronto. E' a questo punto che scatta la ISR, che preleva il byte e lo copia nel buffer SW di cui stiamo parlando.

  1. pianpiano questo viene svuotato e i caratteri passano nella ram di arduino (li' restano, li visualizzo su lcd ma non li metto in nessun altro posto)

no, nel momento in cui estrai un byte dal buffer e lo invii all'LCD, se non sei tu a salvarlo viene perso. Quindi nessun consumo aggiuntivo di ram.

?

spetta io ho scritto che metto in una variabile la stringa ricevuta

dati=chardaseriale

in questo momento i dati sono in Ram e li' restano, anche se faccio il print su lcd.

Solo col secondo invio la variabile dati riceve la nuova stringa e poi la si riprinta su lcd.
ma nella ram come vedi c'e' sempre la stringa, mentre il buffer seriale, quello da 64byte si svuota.

non e' cosi' ?

proprio credendo che sia cosi' mi chiedevo l'istante prima in cui "dati" contiene stringa1 e vuole ricevere stringa2 la ram deve avere 200Byte liberi ? (200 gia' 0ccupati da stringa 1, e 200 per la nuova stringa ?)

Ho fatto un test con lo sketch standard serial event, e riesco a ricevere e trasmettere 1,7KB
x leo, quel .reserve che hanno messo non mi apporta nessun vantaggio, anche se lo tolgo ricevo sempre 1700char

sulmio progetto invece riceve solo una decina di caratteri, aggiungendo il famoso delay di 1ms ritorna tutto come prima, cioe' una sessantina di caratteri con 'lide arduino non modificato

puo' essere colpa dell' I2C ? (uso un lcd i2c, quello che ho in firma, la libreria che io sappia e' derivata da quella originale)

Posto i risultati di tutti i miei test:

delayMicroseconds
0ms : ricevo 10 caratteri
10 --- 10
25 --- 30
50 --- 60
100 --- 130
200 --- 80
100+reserve128 180
100+reserve256 190
100+reserve350 180
delay100 0 reserve + modificando hardwareserial.cpp buffer a 256 = 220

Ho scoperto che abbassando il delay di cui parlavamo a 100microsecondi, riesco ad alzare a 130char senza toccare i buffer. aggiuggendoci un piccolo Reserve da 128Byte, arrivo a 180, e' poco utile aumentare questo valore.

Come vedete la situazione migliore resta quella di modificare il buffer in hardwareserial.cpp, che mi fa arrivare a 220.

Per voi e' facile capire di preciso cosa fa questo comando ? va a modificare i buffer e quindi "perdo" 256byte, oppure non tocca i buffer e "perdo" solo 128byte ?

CharDaSeriale.reserve(128);