Come usare la scheda SD con esp8266 e Arduino

Spread the love
  •  
  •  
  •  
  • 3
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
    3
    Shares

Quando si utilizza un microcontrollore, una funzionalità importante è l’archiviazione dei dati, per il logging o salvare impostazioni, o magari per gestire un server Web oppure per mostrare un’immagine.

La soluzione migliore è una scheda SD, perché è un dispositivo semplice, piccolo e di bassa potenza.

Protocollo

La scheda SD ha un’interfaccia host nativa oltre alla modalità SPI per la comunicazione con i dispositivi master. L’interfaccia nativa utilizza quattro linee per il trasferimento dei dati ed il microcontrollore ha un modulo controller separato e per utilizzarlo richiede una licenza. Poiché SPI è un protocollo ampiamente utilizzato ed è disponibile nella maggior parte dei microcontrollori a basso costo, la modalità SPI è un’interfaccia ampiamente utilizzata nei sistemi embedded a basso costo. La tensione di lavoro della famiglia SD va da 2,7 V a 3,6 V e questo è indicato nel registro delle condizioni operative (OCR). Esiste una scheda SD a bassa potenza che funziona a 1,8 V, ma non è così utilizzata.

Pinout

Esistono vari fattori di forma, ma la piedinatura di base è la stessa.

MMC SD miniSD microSD pins and size factor
Pin NumberPin NameIn SD ModeIn SPI Mode
1DAT2/XConnector Data line 2No use
2DAT3/CSConnector Data line 3Chip Select
3CMD/DICommand / Response LineData Input
4VDD/VDDPower supply (+3.3V)Power supply (+3.3V)
5CLK/SCLKClockSerial Clock
6VSS/VSSGroundGround
7DAT0/D0Connector Data line 0Data Out
8DAT1/XConnector Data line 1No use

Per prima cosa interfacciamo la scheda SD.

SD pinout

Caplaggio

La tensione operativa ci obbliga a creare 2 distinti schemi di connessione in base al tipo di microcontrollore. Per interfacciare la scheda SD uso un adattatore SD per micro SD, e il risultato è questo.

Vista frontale dei pins dell’adattatore SD
SD adapter pins back

Arduino UNO

Come sapete, Arduino UNO funziona a 5 V, quindi è necessario aggiungere nella linea di ingresso un partitore di tensione per evitare di danneggiare la scheda SD.

Per maggiori informazioni sul partitore di tensione potete vedere qui “Partitore di tensione (voltage divider): calcolatore e applicazioni“.

Uso 2 resistenze di 1K e 2K per ottenere 3,3v da 5v e metto una resistenza di pull-up il pin MISO per prevenire disturbi.

Arduino wiring SD card adapter

Nello schema è più semplice identificare il partitore di tensione e le connessioni.

Arduino SD Card adapter schema

Uso i pins esempi standard di Arduino, quindi in seguito useremo del codice che puoi trovare anche nell’Arduino IDE.

Arduino breadboard SD Card adapter

esp8266 (esp32)

Qui la tensione è la stessa, quindi tutto è più semplice.

WeMos D1 mini breadboard with SD Card adapter

ed ecco lo schema.

SDCard adapter and WeMos D1 mini schema

Usiamo il pin D2 che identifica il pin 4 come negli esempi SD di Arduino.

WeMos D1 mini breadboard SD Card adapter

RICORDA!! puoi usare solo i file con pattern 8.3, ad esempio un file come config.txt è accettato ma configuration.text no, perché la lunghezza massima del file è di 8 caratteri e l’estensione 3.

Moduli

Esistono vari moduli per interfacciare il tuo microcontrollore con il tuo dispositivo ed in pratica sono fatti esattamente come lo schema di connessione Arduino per adattatore 5v e come lo schema di connessione esp8266 per 3.3v. Quando ne acquisti uno, devi prestare attenzione alla tensione di lavoro.

Esistono alcune varianti che supportano 3.3v e 5v, come quella qui collegata.

Puoi trovarla qui!

Comandi

Classe SD

sd.begin() sd.begin(cspin)
Inizializza la libreria e la scheda SD. Questo inizializza l’uso del bus SPI e del pin di selezione del chip, il cui valore predefinito è il pin SS dell’hardware. Restituisce vero in caso di successo; falso in caso di fallimento.

sd.exists(filename)
Verifica se esiste un file o una directory sulla scheda SD. Restituisce vero se esiste il file o la directory, falso in caso contrario.

sd.mkdir(filename)
Crea una directory sulla scheda SD. Questo creerà anche qualsiasi directory intermedia se non esiste già; per esempio. SD.mkdir("a/b/c") creerà a, b e c. Restituisce vero se la creazione della directory ha avuto successo, falso in caso contrario.

sd.open(filepath) sd.open(filepath, mode)
Apre un file sulla scheda SD. Se il file viene aperto per la scrittura, verrà creato se non esiste già (ma la directory che lo contiene deve già esistere). Parametro mode (opzionale): la modalità in cui aprire il file, il valore predefinito è FILE_READ – byte. uno di: FILE_READ: apre il file per la lettura, a partire dall’inizio del file. FILE_WRITE: apre il file per la lettura e la scrittura, a partire dalla fine del file. Restituisce un oggetto File che fa riferimento al file aperto; se non è possibile aprire il file, questo oggetto verrà valutato come falso in un contesto booleano, ovvero è possibile verificare il valore restituito con “if (f)“.

sd.remove(filename)
Rimuovere un file dalla scheda SD. Restituisce vero se la rimozione del file ha esito positivo, falso in caso contrario. (se il file non esisteva, il valore restituito non è specificato)

rs.rmdir(filename)
Rimuove una directory dalla scheda SD. La directory deve essere vuota. Restituisce vero se la rimozione della directory è riuscita, falso in caso contrario. (se la directory non esisteva, il valore restituito non è specificato)

File class

file.name()
Restituisce il nome del file

file.available()
Controlla se ci sono byte disponibili per la lettura dal file. Restituisce il numero di byte.

file.close()
Chiudere il file e assicurarsi che tutti i dati scritti su di esso vengano salvati fisicamente sulla scheda SD.

file.flush()
Assicura che tutti i byte scritti nel file vengano fisicamente salvati sulla scheda SD. Questo viene fatto automaticamente alla chiusura del file.

file.peek()
Leggi un byte dal file senza passare a quello successivo. Cioè, le chiamate successive a peek() restituiranno lo stesso valore, così come la chiamata successiva a read().

file.position()
Ottieni la posizione corrente all’interno del file (ovvero la posizione in cui il prossimo byte verrà letto o scritto). Restituisce la posizione all’interno del file (unsigned long).

file.print(data) file.print(data, base)
Stampa i dati sul file (doveva essere aperto per la scrittura). Stampa i numeri come una sequenza di cifre, ognuna un carattere ASCII (ad es. Il numero 123 viene inviato come i tre caratteri ‘1’, ‘2’, ‘3’).
data: i dati da stampare (char, byte, int, long o string),
base (opzionale): la base in cui stampare i numeri: BIN per binario (base 2), DEC per decimale (base 10), PTOM per ottale (base 8), HEX per esadecimale (base 16). Restituisce il numero di byte scritti, sebbene la lettura di quel numero sia facoltativa.

file.println() file.println(data) file.println(data, base)
Come print ma con il return finale.

file.seek(pos)
Cerca una nuova posizione nel file, che deve essere compresa tra 0 e le dimensioni del file (incluso).
Parametri:
pos: la posizione in cui cercare (unsigned long). Restituisce vero per il successo, falso per il fallimento (booleano)

file.size()
Ottieni le dimensioni del file. Restituisce la dimensione del file in byte (unsigned long).

file.read()  file.read(buf, len)
Leggi dal file. Restituisce il byte (o il carattere) successivo o -1 se nessuno è disponibile.

file.write(data) file.write(buf, len)
Scrivi i dati nel file. Restituisce il numero di byte scritti, la lettura di quel numero è facoltativa

file.isDirectory()
Le directory (o cartelle) sono tipi speciali di file, questa funzione segnala se il file corrente è una directory o meno. Restituisce vero se è directory.

file.openNextFile()
Riporta il file o la cartella successivi in una directory. Restituisce il file o la cartella successivi nel percorso.

file.rewindDirectory()
Riporta al primo file nella directory, utilizzato insieme a openNextFile().

Examples

Nell’IDE di Arduino puoi trovare alcuni esempi molto utili e ben commentati.

Qui uno schetck che estrae tutte le informazioni sulla scheda SD utilizzata.

/*
SD card test
This example shows how use the utility libraries on which the'
SD library is based in order to get info about your SD card.
Very useful for testing a card when you're not sure whether its working or not.
The circuit:
SD card attached to SPI bus as follows:
** MOSI - pin 11 on Arduino Uno/Duemilanove/Diecimila
** MISO - pin 12 on Arduino Uno/Duemilanove/Diecimila
** CLK - pin 13 on Arduino Uno/Duemilanove/Diecimila
** CS - depends on your SD card shield or module.
Pin 4 used here for consistency with other Arduino examples
created  28 Mar 2011
by Limor Fried
modified 9 Apr 2012
by Tom Igoe
*/
// include the SD library:
#include <SPI.h>
#include <SD.h>
// set up variables using the SD utility library functions:
Sd2Card card;
SdVolume volume;
SdFile root;
// change this to match your SD shield or module;
// Arduino Ethernet shield: pin 4
// Adafruit SD shields and modules: pin 10
// Sparkfun SD shield: pin 8
// MKRZero SD: SDCARD_SS_PIN
const int chipSelect = 4;
void setup() {
// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
Serial.print("\nInitializing SD card...");
// we'll use the initialization code from the utility libraries
// since we're just testing if the card is working!
if (!card.init(SPI_HALF_SPEED, chipSelect)) {
Serial.println("initialization failed. Things to check:");
Serial.println("* is a card inserted?");
Serial.println("* is your wiring correct?");
Serial.println("* did you change the chipSelect pin to match your shield or module?");
while (1);
} else {
Serial.println("Wiring is correct and a card is present.");
}
// print the type of card
Serial.println();
Serial.print("Card type:         ");
switch (card.type()) {
case SD_CARD_TYPE_SD1:
Serial.println("SD1");
break;
case SD_CARD_TYPE_SD2:
Serial.println("SD2");
break;
case SD_CARD_TYPE_SDHC:
Serial.println("SDHC");
break;
default:
Serial.println("Unknown");
}
// Now we will try to open the 'volume'/'partition' - it should be FAT16 or FAT32
if (!volume.init(card)) {
Serial.println("Could not find FAT16/FAT32 partition.\nMake sure you've formatted the card");
while (1);
}
Serial.print("Clusters:          ");
Serial.println(volume.clusterCount());
Serial.print("Blocks x Cluster:  ");
Serial.println(volume.blocksPerCluster());
Serial.print("Total Blocks:      ");
Serial.println(volume.blocksPerCluster() * volume.clusterCount());
Serial.println();
// print the type and size of the first FAT-type volume
uint32_t volumesize;
Serial.print("Volume type is:    FAT");
Serial.println(volume.fatType(), DEC);
volumesize = volume.blocksPerCluster();    // clusters are collections of blocks
volumesize *= volume.clusterCount();       // we'll have a lot of clusters
volumesize /= 2;                           // SD card blocks are always 512 bytes (2 blocks are 1KB)
Serial.print("Volume size (Kb):  ");
Serial.println(volumesize);
Serial.print("Volume size (Mb):  ");
volumesize /= 1024;
Serial.println(volumesize);
Serial.print("Volume size (Gb):  ");
Serial.println((float)volumesize / 1024.0);
Serial.println("\nFiles found on the card (name, date and size in bytes): ");
root.openRoot(volume);
// list all files in the card with date and size
root.ls(LS_R | LS_DATE | LS_SIZE);
}
void loop(void) {
}

Ecco un esempio di lettura e scrittura di una scheda SD.

/*
SD card read/write
This example shows how to read and write data to and from an SD card file
The circuit:
SD card attached to SPI bus as follows:
** MOSI - pin 11
** MISO - pin 12
** CLK - pin 13
** CS - pin 4 (for MKRZero SD: SDCARD_SS_PIN)
created   Nov 2010
by David A. Mellis
modified 9 Apr 2012
by Tom Igoe
This example code is in the public domain.
*/
#include <SPI.h>
#include <SD.h>
File myFile;
void setup() {
// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
Serial.print("Initializing SD card...");
if (!SD.begin(4)) {
Serial.println("initialization failed!");
while (1);
}
Serial.println("initialization done.");
// open the file. note that only one file can be open at a time,
// so you have to close this one before opening another.
myFile = SD.open("test.txt", FILE_WRITE);
// if the file opened okay, write to it:
if (myFile) {
Serial.print("Writing to test.txt...");
myFile.println("testing 1, 2, 3.");
// close the file:
myFile.close();
Serial.println("done.");
} else {
// if the file didn't open, print an error:
Serial.println("error opening test.txt");
}
// re-open the file for reading:
myFile = SD.open("test.txt");
if (myFile) {
Serial.println("test.txt:");
// read from the file until there's nothing else in it:
while (myFile.available()) {
Serial.write(myFile.read());
}
// close the file:
myFile.close();
} else {
// if the file didn't open, print an error:
Serial.println("error opening test.txt");
}
}
void loop() {
// nothing happens after setup
}

Grazie


Spread the love
  •  
  •  
  •  
  • 3
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
    3
    Shares

Potrebbero interessarti anche...

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *