Come utilizzare la libreria SD per scrivere e leggere dalla micro SD

La nuova board Arduino Ethernet ha in dotazione uno slot per scheda micro SD (Secure Digital) utile per dare la possibilità ai nostri programmi di memorizzare varie informazioni. La libreria permette di lavorare su schede formattate con file system FAT16 e FAT32, i nomi dei file devono essere composti da massimo 8 caratteri più 3 per l’estensione (formato 8.3 stile MS-DOS).

Come molte libreria dobbiamo inserire un riferimento nello sketch che la utilizza:

//inserisco riferimento alla libreria SD
#include <SD.h>

 

successivamente, nel blocco setup, bisogna inizializzare la classe utilizzando il metodo begin(). A questo metodo dobbiamo passare il pin relativo alla funzione Card Select (CS) che per la Arduino Ethernet è uguale a 4, come visibile nello schema elettrico

Schema elettrico collegamento micro sd

//inizializza la classe e specifica
//il pin Card Select
SD.begin(4);

 

Il metodo restituisce false se si verificano problemi durante l’inizializzazione. Quindi prima di continuare è fondamentale verificare chequesta si concluda senza errori

if (SD.begin(4) == true)
//inizializzazione ok
//continua con il codice
else
//problemi nell'inizializzazione!

 

Per poter scrivere e leggere file dalla micro SD abbiamo bisogno di utilizzare la classe File che espone metodi che svolgono questo compito.
Creiamo un oggetto dalla classe File subito dopo la dichiarazione della libreria SD:

//inserisco riferimento alla libreria SD
#include <SD.h>

//creo un oggetto dalla classe File
File MioFile;

 

Utilizziamo il metodo open() della classe SD per aprire un file esistente; il metodo restituisce un riferimento che viene associato all’oggetto MioFile:

//dopo l'inizializzazione posso lavorare sulla micro SD
//Apro un file di testo
MioFile = SD.open("filetest.txt", FILE_WRITE);

 

Da notare che se il file non esiste nella micro SD il metodo open() ne crea uno automaticamente.

il metodo open() della classe file accetta come argomenti due parametri, il primo è il nome del file, il secondo è un flag che indica se aprire il file in lettura o in scrittura, le opzioni sono:

FILE_READApre il file per la lettura partendo dall’inizio
FILE_WRITEApre il file per la scrittura

Se non si verificano errori il metodo open() restituisce il riferimento al file, in caso di errore invece restituisce false; è buona norma controllare tramite un blocco if se si sono verificati errori:

//dopo l'inizializzazione posso lavorare sulla micro SD
//Creao un file di testo
MioFile = SD.open("filetest.txt", FILE_WRITE);

if (MioFile == false)
//problemi nell'accesso al file

 

Utilizziamo il metodo println() dell’oggetto MioFile per scrivere dati sul file appena aperto

//se non ci sono problemi nell'apertura dei file scrivi
//qualcosa al suo interno
if (MioFile != false)
MioFile.println("Ciao Mondo");

 

Una volta ultimate le fasi di scrittura, se non intendiamo scrivere altro è consigliabile rilasciare le risorse chiudendo il file con il metodo close()

//chiudo il file
MioFile.close()

 

La fase di lettura è analoga a quella di scrittura, si procede aprendo il file con il metodo open() ed eseguendo il metodo read() dell’oggetto MioFile

//Apro il file per la lettuta
MioFile = SD.open("filetest.txt", FILE_READ);

//Se non si sono verificati errori
//leggo il file
if (MioFile == true)
{

//Leggi fino alla fine del file
while (MioFile.available())
{
//read esegue la lettura di un byte alla volta
Serial.write(MioFile.read());
}

// close the file:
MioFile.close();
}

 

Il metodo available() restituisce il numero di byte disponibili  tra il puntatore e la fine del file. Il puntatore rappresenta un indice, o per rendere meglio l’idea, un cursore all’interno del file aperto.
Quando apriamo il file il puntatore viene posizionato sul primo byte quindi il metodo available() restituisce il numero di byte compresi tra il puntatore e la fine del file stesso. La read() legge il primo byte (dato che il puntatore si trova all’inizio del file) e fa avanzare il cursore di una posizione.
L’illustrazione seguente spiega meglio il concetto, (viene preso in considerazione un file di 100 byte)

Quando il file viene aperto il cursore punta sul primo byte e available() restituisce 100

Puntatore a file

Dopo la read() il cursore avanza di un byte spostandosi al secondo byte del file. Il metodo available() restituisce 99

Puntatore a file micro sdOgni volta che eseguiamo la read() il puntatore scorre fino ad arrivare alla fine del file (EOF) in questa posizione available() restituisce 0.

EOF end of file

Il ciclo while() esegue la read() ciclicamente fino a quando il valore di available() restituisce zero.

Una volta eseguita la lettura, se non intendiamo fare altro con il file, è consigliabile eseguire il metodo close() per rilasciare risorse e chiudere il file correttamente.

//chiudo il file
MioFile.close()

 

Verificare l’esistenza di un file o di una directory

La classe SD espone alcuni metodi utili per gestire la nostra micro SD, uno di questi permette di verificare l’esistenza di un file all’interno di un percorso, il metodo è exists() e viene utilizzato in questo modo

//verifico l'esistenza di un file
if (SD.exists("filetest.txt"))
//true -> il file esiste
else
//false-> il file non esiste

 

possiamo includere anche un percorso di cartelle

//verifico l'esistenza di un file in un percorso
if (SD.exists("arduino/arduino0022/filetest.txt"))
//true -> il file esiste
else
//false-> il file non esiste

 

con lo stesso metodo verifichiamo l’esistenza di una directory

//verifico l'esistenza di un file in un percorso
if (SD.exists("arduino/arduino0022"))
//true -> la directory arduino0022 esiste
else
//false-> la directory arduino0022 NON esiste

 

Come cancellare un file dalla micro SD

Dopo aver eseguito diverse prove creando diversi file sulla micro SD possiamo liberare un po di spazio cancellandone qualcuno. Il metodo remove() della classe SD esegue questo compito, il suo utilizzo è molto semplice e l’unico parametro da passargli è il nome del file da cancellare:

//Cancella il file di test
SD.remove("filetest.txt");

 

Se la cancellazione avviene con successo la funzione restituisce true altrimenti false.

//Cancella il file di test
if (SD.remove("filetest.txt"))
Serial.println("File eliminato!");
else
Serial.println("Problemi nell'eliminazione");

 

Creare ed eliminare directory

Anche per la creazione ed eliminazione di directory è sufficiente utilizzare i metodi della classe SD, per la creazione utilizziamo il metodo mkdir mentre per l’eliminazione utilizziamo il metodo rmdir

//Creo una directory
if(SD.mkdir("arduino"))
Serial.println("Directory creata");
else
Serial.println("Problemi nella creazione della directory");

 

con mkdir è possibile creare anche le sottodirectory in un colpo solo

//Creo directory e sottodirectory
if(SD.mkdir("arduino/arduino1/arduino2"))
Serial.println("Directory create");
else
Serial.println("Problemi nella creazione della directory");

 

il codice precedente crea tre cartelle nidificate (arduino, arduino1 e arduino2) utilizzando solamente una singola istruzione.
Per eliminare le directory utilizziamo il metodo rmdir() in questo modo

//Elimina la directory
if(SD.rmdir("arduino"))
Serial.println("Directory Eliminata");
else
Serial.println("Problemi nell'eliminazione della directory");

 

rmdir() non può eliminare una directory se all’interno sono presenti altre sottodirectory oppure file, bisogna quindi svuotale e poi eliminarle singolarmente

//Elimina le directory vuote
SD.rmdir("arduino2");
SD.rmdir("arduino1");
SD.rmdir("arduino");

 

La gestione della micro SD risulta essere molto semplice e comoda per le diverse applicazioni che hanno bisogno di memorizzare dati piuttosto che recuperarne per eseguire calcoli o comparazioni. Nel prossimo articolo vedremo come utilizzare queste funzioni per creare un data logger.