Velocità di scrittura su scheda SD

buongiorno a tutti,
sto cercando di scrivere su una scheda sd il valore di vari sensori che si aggiornano a 100Hz.
ho notato che con il passare del tempo (2 ore circa) il tempo di scrittura dei dati sulla scheda sd aumenta drasticamente, utilizzo la libreria SD di Arduino.

sto lavorando con IMU e GPS e quando il programma inizia a salvare riesco ad avere dei tempi tra un ciclo e l'altro di circa 20ms (50Hz invece che 100Hz) questo penso sia dovuto alla velocità di scrittura sulla scheda SD in quanto ogni 5Hz scrivo su un file diverso dal precedente gli stessi dati (su un file campiono al massimo della velocità raggiungibile mentre su un altro campiono a 5Hz) e vedo che il tempo tra una scrittura e l'altra raddoppia solo in quel caso.
il problema arriva dopo circa un ora dall'inizio di esecuzione del programma, i tempi di scrittura nella scheda SD raddoppiano! (da 20ms a 40).

non essendo un informatico non ho le conoscenze sufficienti per capire il vero e proprio funzionamento della libreria SD ma posso intuire che con il passare del tempo, il file diventa più grosso e di conseguenza più pesante ed è come se ci mettesse di più ad aprirlo. potrebbe essere questo il problema (scrivo tutto su un file .CSV)?

grazie mille in anticipo della vostra risposta!

Di che scheda stiamo parlando?

Potresti provare ad acquisire "a blocchi" aggiornando il file sulla SD ad intervalli regolari.
Avresti comunque il rallentamento quando la dimensione dello stream (il file) diventa grande, ma quantomeno sarebbero in qualche modo prevedibili.

Non so ... forse lavorare con record a lunghezza fissa (così da poter fare accessi diretti) e preallocare lo spazio inizialmente per il massimo di record previsti, probabilmente porterebbe ad accessi costantemente della stessa durata (una seek() per posizionarsi sul record già preallocato e successiva scrittura) ... :roll_eyes:

Guglielmo

grazie a tutti del consiglio, per ora ho risolto limitando il file a 20000 righe.
il problema grande è che risulta molto scomodo in quanto alla fine ho circa 18-20 file da unire facendo coppia e incolla.

puoi spiegarti meglio? teoricamente io non conosco a priori le righe massime che andrò a creare.

Teoricamente non è necessario: visto che l'istruzione write() restituisce il numero dei byte che sono stati scritti, a questo punto sarebbe sufficiente aggiornare un contatore globale del numero totale dei byte del file e fare il seek() come suggerivi.

Con questa simulazione io ottengo dei valori costanti di circa 10/12 millisecondi per record (mentre non usando l'istruzione seek() i tempi incrementano mano a mano come è stato riscontrato da @nocentini)

allora, ho studiato un pochino il programma che mi hai fornito e se ho capito bene (non sono troppo pratico con la classe string e tutte le conversioni del caso)

  1. vado a leggere quanti byte sono stati scritti nel file e lo salvo nella variabile "pos" (così ho indicazione di dove dovrò andare a scrivere nel file)
  2. tramite: "file.seek(pos);" vado a posizionarmi dopo i byte già scritti sul file
  3. crei un array di caratteri che contiene i dati dei sensori raccolti.
  4. tramite "pos += file.write(line);" vai a scrivere l'array di caratteri sulla scheda sd e incrementi il valore dei byte scritti
    corretto?

Esattamente.
Il tutto è stato testato solo online ovviamente... rimane da vedere come si comporta nella realtà.

Vero, deformazione professionale :grin: sono un normale utilizzatore di accessi random e/o ISAM e il record a lunghezza fissa è un po' una mia fissazione, lo trovo estremamente comodo per accessi diretti e velocissimi :wink:

Guglielmo

ovviamente si, penso che proverò a farlo girare per qualche ora e vedo cosa succede.
grazie anche a @gpb01 per i consigli!

Anche io tendenzialmente farei con un record a lunghezza fissa.
In questo caso però ho pensato che @nocentini abbia bisogno di una frequenza di campionamento elevata ed ogni manipolazione delle stringhe aggiuntiva avrebbe impiegato risorse e tempo (penso ad esempio a quanto può essere "onerosa" l'istruzione sprintf() per una piccola MCU come quella dell'Arduino).

Magari no, in effetti sarebbe il caso di verificare :rofl:

edit:
In effetti mi ero posto un non-problema...
Usando snprintf e formattando a lunghezza fissa ogni linea, il tempo di esecuzione è pressoché uguale (ho aggiornato anche lo sketch online).

1 Like

ho provato e tutto funziona correttamente! grazie mille delle vostre risposte.
ho un'altra domanda, non so se devo aprire un nuovo post...
praticamente essendo che la velocità di scrittura sulla scheda SD alla fine dei conti è di circa 10ms e la frequenza di aggiornamento dell'IMU è di 100Hz=10ms alla fine tutto il ciclo dura 20ms, di conseguenza vado a perdere una lettura del sensore mentre Arduino salva i dati.
sarebbe possibile (ovviamente non avendo un multicore) poter salvare i dati e contemporaneamente leggere i dati del sensore? utilizzo MKR1010 :frowning:

Di quale IMU si tratta?
Forse si può migliorare un po' usando l'interrupt (se previsto).

utilizzo MKR IMU con la libreria ufficiale di arduino, penso che l'interrupt si attivi solo quanto è impostata una soglia massima di "G" impostata.

Guardando nel datasheet sembrerebbe possibile impostare anche il "Data Ready Interrupt", il problema è che la libreria che usi non ha alcuna istruzione al riguardo.

grazie mille della tua osservazione, la serie MKR con le sue librerie ufficiali si conferma sempre molto castrata di funzionalità sfortunatamente...... chi fa da sé fa per tre...... :grimacing: :neutral_face:

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.