Problema consistenza ( o sovrascrittura?) con uno streaming dati da Arduino a PC

Salve a tutti!
Mi sono da poco avvicinato ad Arduino ( o meglio, è da qualche anno, ma sempre per progetti molto semplici) e, pur avendo una preparazione nel campo della programmazione non proprio solidissima :roll_eyes: , grazie ai contributi del forum, sono sempre riuscito a superare i piccoli problemi incontrati.
Ora però mi trovo in una situazione inaspettata che coinvolge non funzioni esotiche ( o esoteriche) ma la funzione più banale, la cara Serial.print().

Arrivando alla questione, sto cercando di inviare uno stream di dati da un micro (ho provato con Arduino UNO , Mini e STM32) a un PC (Win10): il mio sketch legge -al momento- un ingresso analogico e il millis() e invia un pacchetto dati del tipo:

[aaa,bbb,ccc,ddd,eee,fff,ggg,hhh][aaa,bbb,ccc,ddd,eee,fff,ggg,hhh]....

ovvero 8 valori separati da una virgola e racchiusi tra parentesi quadre.

In particolare :
aaa= valore dell'ingresso analogico A0
bbb= valore di millis()
ccc= valore "0"
ddd,eee,fff= i valori inviati nella lettura precedente (a scopo debug)
ggg=ancora il millis() precedente
iii= variabile da usare per test.

Ecco il codice:

#define SERIAL_SPEED 115200
const int y_Pin = A0;

int test = 0;
struct
{
  unsigned long time_x;
  uint16_t y_value;
  uint16_t tr_value;
  unsigned long time_x_old;
  uint16_t y_value_old;
  uint16_t tr_value_old;

} csv_array;

uint16_t y_value_temp;
uint16_t tr_value_temp;
uint16_t y_value_arch;
uint16_t tr_value_arch;

unsigned long time_x_arch;
bool start = true;

void setup()
{

  Serial.begin(SERIAL_SPEED);
  csv_array.time_x = millis();
  Serial.flush();
}

void loop()
{
  for (;;)
  {
    y_value_temp = analogRead(y_Pin);
    tr_value_temp = analogRead(trav_pin);
    csv_array.time_x_old = csv_array.time_x;
    csv_array.y_value_old = csv_array.y_value;
    csv_array.tr_value_old = csv_array.tr_value;

    csv_array.y_value = map(y_value_temp, 0, 1023, 0, 1023);
    csv_array.tr_value = map(tr_value_temp, 0, 1023, 0, 1023);
    csv_array.time_x = millis();
    if (start == false)
    {
      if (y_value_arch != csv_array.y_value_old)
      {
        test = 1;
      }
      if (tr_value_arch != csv_array.tr_value_old)
      {
        test = 1;
      }

      if (time_x_arch != csv_array.time_x_old)
      {
        test = 1;
      }
      if (csv_array.time_x_old > csv_array.time_x)
      {
        test = 1;
      }
    }
    start = false;
    Serial.print("[");

    Serial.print(csv_array.y_value);
    Serial.print(",");

    Serial.print(csv_array.time_x);
    Serial.print(",");

    Serial.print(csv_array.tr_value);
    Serial.print(",");

    Serial.print(csv_array.y_value_old);
    Serial.print(",");

    Serial.print(csv_array.time_x_old);
    Serial.print(",");

    Serial.print(csv_array.tr_value_old);
    Serial.print(",");

    Serial.print(time_x_arch);
    Serial.print(",");

    Serial.print(test);
    Serial.print("]");

    Serial.flush();
    y_value_arch = csv_array.y_value;
    tr_value_arch = csv_array.tr_value;
    time_x_arch = csv_array.time_x;
  }
}

Ora la cosa sembra ( ....e probabilmente lo è) elementare, una volta inizializzata la seriale inizio con una serie di Serial.print() ad inviare i dati al PC.
La cosa sembra funzionare bene per un po', poi ho dei valori strani
Avevo inizialmente inviato questa richiesta al forum di QT, proprio perchè pensavo che questi problemi potessero essere legati al lato PC e ritenevo -a torto- che il problema non potesse essere sul lato micro.

Ora vediamo cosa intendo per "strani" (sono andato a capo per questioni di leggibilità):

...
[290,862252,0,290,862249,0,862249,0]
[290,862254,0,290,862252,0,862252,0]
[290,862256,0,290,862254,0,862254,0]
[290,862258,0,290,862256,0,86226,0,866206,0] <-----
[368,866211,0,368,866208,0,866208,0]
[368,866213,0,368,866211,0,866211,0]
[370,866215,0,368,866213,0,866213,0]
[370,866217,0,370,866215,0,866215,0]
....
[372,866571,0,372,866569,0,866569,0]
[372,866573,0,372,866571,0,866571,0]
[372,866575,0,372,866573,0,866573,0]
[372,866577,0,372,8665723,0] <------
[308,862627,0,309,862625,0,862625,0]
[309,862629,0,308,862627,0,862627,0]
...

Da notare che il tempo prima "salta" avanti di circa 4sec e poi torna indietro di circa 4sec.
I valori di controllo (4°,5° e 6° valore) sembrano conservati come se non fosse un errore di trasmissione ma, piuttosto , come se fosse stato sovrascitta la parte evidenziata tra le due frecce e, in effetti, i due valori di tempo "esterni" all'errore (862258 e 862627) coprono circa lo stesso intervallo di quello "interni" ( 866211 e 866577).

La mia impressione è che ci sia una sorta di buffer "circolare" che ad un certo punto vada in overflow e inizi a sovrascrivere dei valori precedentemente archiviati, ma non capisco il perchè...
Il valore finale della terz'ultima riga "8665723" potrebbe essere il 866575 con il 5 troncato- quindi (86657) - che ha sovrascritto un 862623 (valore plausibile per la riga precedente) ->(86657)(23).

La parte finale del file (interrotta perchè ho interrotto il test...) , è:

[368,866017,0,368,866015,0,866015,0]
[368,866019,0,368,866017,0,866017,0]
[368,866021

e potrebbe essere sensato come ordine di grandezza.
Qualcuno ha qualche consiglio? Il problema non sembra influenzato dalla velocità di trasmissione,
Grazie 1000 e scusate per il post lungo come Guerra e Pace!

Alcune cose non mi quadrano:
1 non usare virgolette per stampare semplici caratteri, usa l'apostrofo
2 la variabile trav_pin non è dichiarata,
3 perché mappi una lettura sullo stesso ordine di grandezza? Map(x, 0, 1023, 0, 1023) è una operazione inutile
4 sei sicuro sicuro di averci messo l'ultimo programma con la sua uscita?
Perché quello che hai messo non compila, e se compilasse vedresti 1 in ultima posizione sulle stampe, non 0

Secondo me il problema è che ad ogni ciclo di loop scrivi sulla seriale, se il ricevente non è altrettanto rapido a leggere i dati vai in buffer overflow.
Forse ridurre l'invio dei dati su seriale potrebbe aiutare, ovvero trasmettendoli ogni tot millisecondi anziché ad ogni ciclo di loop.
A proposito quel

for

dentro al loop è innutile, puoi rivuoverlo visto che il loop viene già richimata di continuo con un for identico al tuo

Quoto in pieno fabpolli

lagodolio:
Il problema non sembra influenzato dalla velocità di trasmissione,

Oltre alle precedenti osservazioni, giustissime, vorrei aggiungere qualche mia considerazione.

Intanto tu qui spari i dati ogni 2msec, sicuro che ti servano 500 letture al secondo?

Poi usi il flush() che se non erro attende che i dati siano effettivamente stati inviati sulla seriale, per cui in linea di massima escluderei un overflow del buffer di Arduino (semmai del ricevente).

La cosa più probabile è quindi proprio la possibilità che il ricevente non elabori i dati inviati alla velocità di trasmissione.

Ma quell'output tu l'hai ottenuto dal serial monitor o dal tuo programma?

In ogni caso ti consiglierei di usare un normale software di terminale (anche putty), collegarlo alla seriale di Arduino, e vedere cosa ricevi esattamente. Se così ricevi bene, allora devi vedere nel programma che riceve i dati (io oltre a togliere la for(;:wink: inutile, metterei anche un delay(200) o maggiore per dare misure ad intervalli maggiori).

Fornisco un po' di chiarimenti, il post iniziale era già lungo di suo e non volevo uccidere per sfinimento gli utenti al primo messaggio...
Allora:

  • trav_pin è stata cancellata insieme ad un commento per errore , ecco cole dovevano apparire le prime righe:
#include <stream.h>
#define SERIAL_SPEED 115200
int y_Pin = A0;
int trav_pin = A1;

mi scuso se questo ha generato confusione, avrei dovuto guardare il codice meglio.

  • La funzione map è in effetti buttata lì, dovrei ancora vedere altri dati e condizionare eventualmente il segnale.
  • Il problema dello zero... è questo che non mi torna, non vedendo mai ' 1 ' ad indicare un errore , inizialmente avevo pensato ad un problema nel software in QT ( e infatti lì sono andato a rompere le scatole in prima battuta!). Mi hanno consigliato di verificare i dati ricevuti utilizzando putty o simile, e in effetti il problema è a livello di ricezione .
    Ho usato QTComPort , ho salvato l'output su un file e ho aggiunto un \n dopo ogni ] per rendere il tutto più leggibile.
  • Il ciclo for era per evitare continui ingressi /uscite dal loop, probabilmente è un'idiozia :confused:
  • Avevo pensato ad un problema risolvibile con un delay(avevo messo anche 20, senza risolvere nulla), ma vorrei rimanere sulle 100-150. Il micro dovrà anche leggere dati inviati dal pc (con interrupt) è quindi volevo avere un bel po' di margine...

La mia impressione che il micro "riscrivesse" sul suo buffer (cosa che spiegherebbe la mancata segnalazione dell'errore da parte della variabile "test") mi aveva fatto pensare ad un errore nella gestione del buffer stesso (a livello PC o Arduino),ma nel forum di QT hanno escluso la possibilità dell'overflow del buffer del PC, quindi ho spostato l'attenzione sul micro.
Forse dovrei cercare librerie più performanti di Serial.print, se avete suggerimenti postate pure! :smiley:

Forse dovrei cercare librerie più performanti di Serial.print, se avete suggerimenti postate pure!

Veramente la classe Serial e già il massimo che puoi avere su Arduino (salvo non voler andare a scrivere a basso livello usando i registri) ed è gestita ad interrupt; comunque, a 115Kbps NON c'è alcun problema con la Serial (se usata bene).

Ovvio una cosa ... a quella velocità riesci a smaltire al massimo circa 11 KByte al secondo, se le chiamate sono più veloci, il buffer di TX si riempie e ... il tutto si blocca con la possibilità di avere problemi.

Potresti, prima di scrivere sulla seriale, verificare la disponibilità di spazio nel buffer di trasmissione con il metodo availableForWrite() e verificare se hai questo problema.

Lato PC sei invece sicuro che sia in grado di riceve uno streaming continuo a 115Kbps ?

Guglielmo

Aggiungo le mie considerazioni e suggerimenti.

Scusa ma stando a quanto hai postato tu mandi pacchetti da almeno 36 caratteri, quindi se ne mandi 500 al secondo sono circa 180.000bps (10 bit per byte per via dei bit di start e stop) per cui a 115.200bps e considerando il fatto che NON ha alcun handshake che io sappia (né hardware né software) qualsiasi buffer prima o poi si satura se la velocità di trasmissione è inferiore alla quantità di dati da trasferire per secondo!

Quindi io credo che tu debba intanto definire meglio il flusso e capire i limiti "fisici". Tu dici di aver provato con delay(20) ma senza successo, in quel caso siamo attorno ai 18-20.000bps per cui con la seriale a 115.200 dovrebbe funzionare.

Per cui io andrei per gradi, ossia per prima cosa vedi esattamente cosa esce dalla COM di Arduino, collegandoci un terminale seriale tipo putty (ma togli il for(;:wink: che non mi convince): se anche qui hai lo stesso problema allora o è effettivamente il buffer di Arduino che nonostante i flush() non ce la fa (possibile, anche se lo ritengo poco probabile se abbassi la quantità di dati), o il driver della COM virtuale su USB ha qualche problema (mi pare strano).

Se quindi è in questa fase il problema, potresti cambiare il protocollo attendendo un ACK dalla controparte prima di mandare il successivo pacchetto ed evitare overflow in trasmissione e/o ricezione, ma questo potrebbe far rallentare l'invio dei dati.

Oppure potresti provare a collegare il PC tramite una "vera" seriale collegata sui pin 0 e 1 (ma non avendo handshake resterebbe il problema degli eventuali overflow).

Se invece da putty vedi tutto correttamente, il problema è su QT o come gestisce la seriale, e qui non ti posso aiutare.

Lui flussa la seriale, che dovrebbe garantire di non perdere nulla, in trasmissione
Il fatto di non avere caratteri strani dovrebbe garantire anche che non ci sono problemi in ricezione (almeno non hw)
Secondo me il problema è nel "trattamento" dei dati ricevuti, a 500 righe al secondo, 800 e passa secondi danno 400 mila righe (sì, vero, lui non mette un fine riga, ma è per capirci)
dopo 400mila righe trova scritto qualcosa di strano, a quel punto il file di log, o qualunque cosa sia usata lato pc, ha superato i 12 mega
Io guarderei lato pc
Rimane il fatto che abbassarei sia velocità della seriale che cadenza di trasmissione
E metterei un println da ultimo, per avere le righe divise nel terminale

Appena possibile provo a metterci mano. Inizialmente avevo fissato la velocità a 230400, ma QTComPort supporta al massimo 115200, quindi ho bovinamente (con rispetto per i bovini) abbassato a 115200.
Il ciclo for nasce da un pallido( e vago e nebuloso....) ricordo di un esame con il C, in cui si diceva che a volte la chiamata della funzione porta via più tempo del ciclo in essa contenuto, mi era sembrata quasi quasi una genialata... :zipper_mouth_face: . Togliamolo, non serve a nulla e peggiora la leggibilità.
L'uso di availableForWrite() potrebbe essere quello che mi serve, magari impacchettando tutti i dati in uscita e inviandoli quindi tutti insieme solo se ne ho la possibilità.
La cosa fastidiosa - infatti ho modificato lo sketch per avere un contatore incrementale come primo termine, in modo da semplificare il debug con Notepad++, confrontando la coerenza tra il numero riga e il contatore stesso- è che l'errore anche a 230400 non arriva subito ma, come evidenziato da Standardoil (che sento vicino per il suo nick...) al termine di file di testo con dimensioni da sistema operativo (anche 24Mb!) .
Purtroppo non ho Arduino sottomano, appena posso vi faccio sapere.
P.S : Vado un po' OffTopic ,ma sono veramente colpito dall'apporto di questa comunità, in qualche ora mi avete dato tanti suggerimenti su cui lavorare, spero -un giorno- di poter essere utile come voi lo siete stati a me

lagodolio:
Appena possibile provo a metterci mano. Inizialmente avevo fissato la velocità a 230400, ma QTComPort supporta al massimo 115200

Pure Arduino...

L'uso di availableForWrite() potrebbe essere quello che mi serve, magari impacchettando tutti i dati in uscita e inviandoli quindi tutti insieme solo se ne ho la possibilità.

Non l'ho mai usato, ma se il flusso dati è superiore (o comunque paragonabile) alla massima capacità del canale seriale temo che non cambierebbe un granché...

il contatore stesso- è che l'errore anche a 230400 non arriva subito ma, come evidenziato da Standardoil (che sento vicino per il suo nick...) al termine di file di testo con dimensioni da sistema operativo (anche 24Mb!) .

Beh certo che non arriva subito, dipende dalla velocità di trasmissione e dalla dimensione del/dei buffer seriali...

Per me, ripeto, comunque devi anche abbassare la frequenza di invio per stare con almeno un margine del 20-25% sotto al limite del canale. Se imposti 115200 sarebbero circa 10kbyte/sec quindi attestati a non oltre gli 7kbyte/s, per cui con circa 40 byte a pacchetto siamo a 170 pacchetti al secondo per cui ti direi che in queste condizioni basterebbe un delay tra 5 e 10ms. Ma poiché hai detto di aver provato anche con 20, sospetto che il problema non sia questo, quindi prima dovresti fare quella prova per isolare il problema e capire da cosa possa dipendere, quantomeno se si trova lato Arduino o lato PC/Qt, ed in base a questa indicazione investigare ulteriormente.

PS: ma perché mandare dati numerici interi come stringa invece di usare semplici sequenze di byte? Per semplicità puoi anche usare la tua attuale struct csv_array (formato unsigned integer 2 byte, ed i millis, unsigned long 4 byte), al massimo con un byte iniziale (magari proprio lo standard SOH, Start Of Header, 0x01), ed uno finale di chiusura (es. il carattere EOT, End Of Transmission, 0x04). Totale 18 byte invece di 40, e dimensione fissa invece di separatori a carattere!

Poi non capisco bene lo scopo di debug, con la ripetizione dei dati precedenti: se ora hai introdotto un ID di pacchetto, sai già se quello precedente non lo hai ricevuto.

docdoc:
Non l'ho mai usato, ma se il flusso dati è superiore (o comunque paragonabile) alla massima capacità del canale seriale temo che non cambierebbe un granché...

... beh, quello ti dice se c'è spazio nel buffer di TX e se non ce n'è .. ti DEVI fermare e aspettare che ci sia prima di scrivere ancora sulla seriale o, comunque, il tuo programma rimarà bloccato sulla prima scrittura che fai.

Guglielmo

Eccomi, dovendo andare da un fornitore ho fatto un salto a casa e ho preso Arduino, quindi posso informarvi sulle novità.
Premessa doverosa, tutti quei dati servono a testare il comportamento di un sistema elettromeccanico che riceve alcuni input da sottosistemi (LVDT, encoder ,ecc ) e invia dei pacchetti secondo un protocollo prefissato, dove le variabili indicheranno la modalità di funzionamento, alcuni parametri funzionali ecc.
Inizialmente avevo pensato di usare dei byte e non delle stringhe per definire le funzioni e i parametri (moolto approssimativamente, tipo modbus che passa dei valori esadecimali con cui sono definiti diversi parametri), ma non pensando che ci fossero dei limiti stringenti sulla seriale di Arduino ho preferito gestire dati in modo più amichevole.
Solitamente ho usato Arduino con seriale a 9600, ho però visto che il monitor seriale arriva a 250000 e Merlin sulla mia stampante 3d è impostato a quella velocità, quindi non ho riflettuto troppo su eventuali limiti.
Il grosso del lavoro è la parte in QT, con l' interfaccia, la gestione dati (mysql) e la loro elaborazione , mentre attualmente Arduino serve solo a "sfamare" il programma, quindi tutto è decisamente embrionale.
Lavorandoci su, però, mi è venuta la curiosità di vedere fino a dove poteva arrivare con la seriale e vederne i limiti.
Penso che per un flusso di dati più importanti sarebbe meglio usare uno shield ethernet, ma mi piacerebbe sapere se le prestazioni sono interessanti o sono vincolate da sottositemi di Arduino (come avviene su certi microPC -penso a una versione dell'OrangePC ora fuori produzione che aveva una porta SATA ma gestita dall'USB, in pratica collegare un HD SATA era equivalente a collegare un HD esterno USB)

Tornando al programma, ho concatenato tutte le variabili in una variabile stringa chiamata sign , quindi ho inserito:

Serial.print(sign);
Serial.print(" Lungh :");
unsigned int lunghezza=sign.length();  
Serial.print(lunghezza);
Serial.print("  free:");
Serial.print(Serial.availableForWrite());
       Serial.flush();
Serial.print("  FaF:"); //Free after Flush()
 Serial.println(Serial.availableForWrite());

Questo rende più durala vita alla povera seriale, ma mi permette di vedere come vanno i dati.
Ho inserito un delay di 10ms e sembra andare abbastanza bene per tempi brevi (diciamo 7-8minuti) mentre con delay(5) la situazione peggiora visibilmente, con problemi dopo poco più di un minuto.

[5753,187,63363,186,199,63351,196,0] Lungh :36 free:17 FaF:59
[5754,203,63374,200,187,63363,186,0] Lungh :36 free:17 FaF:59
[5755,184,63385,184,203,63374,200,0] Lungh :36 free:17 FaF:59
[5756,204,63395,200,184,63385,184,0] Lu4,199,0] Lungh :36 free:17 FaF:59
[6816,204,75137,200,185,75125,185,0] Lungh :36 free:17 FaF:59
[6817,185,75148,185,204,75137,200,0] Lungh :36 free:17 FaF:59

Questi sono i dati presi da un programma che monitora i dati sulla seriale; la cosa che mi ha stupito maggiormente è quel Faf (Free after Flush()) di 59, quindi il buffer di Arduino è solo di 64byte (59+4 di "Faf:" +1 di"\n")?
In QT la funzione arduino->bytesAvailable() mi forniva valori nell'ordine dei 32500byte ma probabilmente si riferiva al buffer del pc e questo mi ha tratto in inganno.

Comunque è evidente che il flusso di dati è eccessivo, basta un piccolo rallentamento e la stringa verrebbe troncato a metà (cosa che sembra succedere), quindi dovrei inserire un delay maggiore ma i campionamenti scenderebbero sotto i 50-60sps.
La strada suggerita da docdoc è probabilmente quella che potrebbe risolvere il problema, oppure pensare subito ad implementare l'ethernet in vista magari di sviluppi successivi.
Vorrei provare anche a usare un adattatore seriale-USB ( una economicissima SiliconLabs CP210x) o l' STM32, magari senza accedere dalla USB.... insomma un po' di esperimenti che non guastano mai!
P.S: lo so, sarò stucchevole, ma siete veramente una super comunità!

Forse il mio messaggio precedente non è stato abbastanza chiaro:
il problema non è lato Arduino: Un buffer di 64 byte non può conservare 2000 letture e sbagliare di 4 secondi.
il Problema è certamente lato pc
Poi se questo non basta a convincere...
Nulla potrà

Il problema è cercare di capire a che livello, sul lato PC, si genera il problema per poter trovare una soluzione.
Nel senso che non dipende dal programma in QT , dal momento che altri software di controllo seriale (putty,QTComPort evidenziano lo stesso problema, come anche il monitor seriale dell'IDE arduino).
Non dipende da un errore di Arduino, visto il buffer viene svuotato dopo ogni scrittura, i caratteri sono sempre coerenti (non compaiono cose strane , tipo quando imposti il monitor seriale su velocità diverse da quella inizializzata ecc).
Il problema è nel mondo di mezzo, Win10 -mi è sembrato di capire- si comporta meno bene di Linux o Mac nella gestione delle comunicazioni seriali (poi bisogna capire se la cosa ha un fondamento o è chiacchiera da bar... :smiley: ), tra antivirus,firewall, programmi che corrono qualche rallentamento ci può essere, anche se credevo che il buffer del sistema compensasse (32500byte ,stando a QT, dovrebbero essere un bel polmone...).
Analizzando la questione alla luce di quanto ho visto ieri , con l'andamento del buffer durante l'esecuzione, mi sono fatto quest'idea:
allora, 4 secondi persi, in realtà, non sono dati propriamente non acquisiti perchè , più avanti , il sistema ritorna indietro di circa 4 sec e l'intervallo coperto è coerente.
Sembra -è questa la cosa che vorrei capire, al di là delle prestazioni della seriale- che avvenga una cosa del genere:

  • Il sistema acquisisce normalmente i dati:
    1
    2
    3
    4
    5
    6
    7
    8
  • Succede qualcosa di imprevisto, vengono acquisiti i valori

9
10
11
ma per un qualche motivo, invece di accodarli, li mette dove non andrebbero messi

  • Vado a leggere il buffer e mi ritrovo:
    1
    2
    3
    9
    10
    11
    7
    8

Se guardo localmente ho l'impressione che il sistema non abbia letto 5 valori (intervallo tra 4 e 8 ), in realtà l'errore è stato di "indice".
Ora è -o almeno mi sembra- impossibile che questo possa avvenire nel piccolo buffer di arduino che non può certo contenere e 4 secondi di dati. Credendo che il buffer della seriale di Arduino fosse molto più grande (32K, ho interpretato male i byte liberi riportati da QT e riferiti alla seriale del PC) ho pensato che questo potesse avvenire anche nel micro.
Il problema è quindi nel lato PC, quando ho scritto:

"Comunque è evidente che il flusso di dati è eccessivo, basta un piccolo rallentamento e la stringa verrebbe troncato a metà (cosa che sembra succedere)"

mi riferivo alla gestione complessiva che viene fatta , nel suo complesso, proprio dal PC: il computer rallenta, non acquisisce i dati e riprende a leggere da metà.

Ora mi viene però il dubbio che se avvenisse questo dovrei trovarmi nel mio log anche caratteri non numerici, un po' come avviene quando si inizia a leggere la seriale (i primissimi caratteri) ma questo non si è mai verificato....
Il problema della sovrascittura del buffer, però, mi sembra ugualmente strano....

lagodolio:
Il problema è cercare di capire a che livello, sul lato PC, si genera il problema per poter trovare una soluzione.

Beh considera comunque che tra la UART di Arduino (pin 0 e 1) e la porta COM del PC ci sta di mezzo l'interfaccia USB ma soprattutto il driver che rimappa la seriale di Arduino. non dico che sia questo, ma quando ci sono catene di componenti è possibile che il problema sia nel limite di "qualcosa" in mezzo.

Vado a leggere il buffer e mi ritrovo:
1
2
3
9
10
11
7
8

Questo è stranissimo, un buffer è una coda FIFO, mai visto un effetto del genere (a meno che non ci siano cose strane legate a puntatori, ma non mi pare questo il caso).

La violazione del principio di causalità e le inversioni temporali sono più della fisica quantistica (o della fantascienza), che della comunicazione seriale... :wink:

Ormai i sospetti si concentrano proprio sulla gestione della seriale (emulata) da parte del PC...
Non ho capito se il buffer sia di tipo "a pila" o se sia "circolare": in quest'ultimo caso - ma non capisco perchè dovrebbe accadere- il sistema sembrerebbe voler caricare es 32600byte, pur avendone liberi solo -ad esempio- 32400. I 200 in più vanno a scrivere la parte iniziale del buffer circolare.
Ho visto che questi errori avvengono sempre quando il PC inizia una nuova operazione di lettura del suo buffer(che è molto più grosso di quello di Arduino, è nell'ordine dei 34Kb): ecco i dati sbagliati sono sempre all'inizio di un nuovo "pacchetto" . Io mi ero fatto questa idea, ma se il buffer fosse a "pila" la cosa non avrebbe senso , a meno che non ci fosse un problema di driver macroscopico.
Mi era venuta l'idea di affiancare un circuito di buffer con una SRAM SPI, potrebbe essere di aiuto o aggiungerebbe solo complicazioni ? Appena posso faccio la prova con macchine diverse e sistemi operativi diversi, vediamo se cambia qualcosa.
Buon fine settimana a tutti!