How to use SD card with esp8266 and Arduino

Spread the love
  •  
  •  
  •  
  • 5
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
    5
    Shares

When you use a microcontroller an important features is store data, for logging or setting, for a web server or to show image.

The better solution is an SD card, because It’s simple, small and low power device.

Protocol

SD card has a native host interface apart from the SPI mode for communicating with master devices. The native interface uses four lines for data transfer where the microcontroller has SD card controller module and it needs separate license to use it. Since the SPI is a widely used protocol and it is available in most low-cost microcontrollers, the SPI mode is the widely used interface in low cost embedded systems. The working voltage range of SD family is 2.7V to 3.6V and this is indicated in the operation condition register (OCR). Exist a low power SD Card that operate al 1.8V, but isn’t so used.

Pinout

Exists various form factor, but the base pinout are the same.

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

Now we are going to interface SD card for first.

SD pinout

Wiring

The operating voltage forces us to make 2 distinct connection schema based on the type of microcontroller. To interface the SD card I use an SD adapter with micro SD, and the result is this.

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

Arduino UNO

As you know, Arduino UNO operate at 5V, so we must add in the input line a voltage divider to prevent the firing of SD Card.

If you want more information about Voltage Divider you can read this article “Voltage divider: calculator and application“.

I use 2 resistence of 1K and 2K to get 3.3v from 5v, and I pull-up MISO pin to prevent noise.

Arduino wiring SD card adapter

In the schema is more simple to identify voltage divider and connections.

Arduino SD Card adapter schema

I use standard pins of Arduino examples, so next we are going to use some code that you can find in Arduino IDE also.

Arduino breadboard SD Card adapter

esp8266 (esp32)

Here the voltage is the same, so all is more simple.

WeMos D1 mini breadboard with SD Card adapter

And the schema

SDCard adapter and WeMos D1 mini schema

We use D2 pin that identify pin 4 as Arduino SD examples.

WeMos D1 mini breadboard SD Card adapter

REMEMBER!! you can use only 8.3 file, for example a file like config.txt is accepted but configuration.text no, because max file lenght is 8 character and extension 3.

Modules

Exists variuos modules to interface your microcontroller with your device, and It’s work exactly the Arduino connection schema for 5v adapter and like esp8266 connection schema for 3.3v. When you buy one, you must pay attention on working voltage.

Exists some variant that support 3.3v and 5v, like the one linked here.

You can find here

Commands

SD Class

sd.begin() sd.begin(cspin)
Initializes the SD library and card. This begins use of the SPI bus and the chip select pin, which defaults to the hardware SS pin. Returns true on success; false on failure.

sd.exists(filename)
Tests whether a file or directory exists on the SD card. Returns true if the file or directory exists, false if not.

sd.mkdir(filename)
Create a directory on the SD card. This will also create any intermediate directories that don’t already exists; e.g. SD.mkdir(“a/b/c”) will create a, b, and c. Returns true if the creation of the directory succeeded, false if not.

sd.open(filepath) sd.open(filepath, mode)
Opens a file on the SD card. If the file is opened for writing, it will be created if it doesn’t already exist (but the directory containing it must already exist). Parameter mode (optional): the mode in which to open the file, defaults to FILE_READ – byte. one of:FILE_READ: open the file for reading, starting at the beginning of the file. FILE_WRITE: open the file for reading and writing, starting at the end of the file. Returns a File object referring to the opened file; if the file couldn’t be opened, this object will evaluate to false in a boolean context, i.e. you can test the return value with “if (f)”.

sd.remove(filename)
Remove a file from the SD card. Returns true if the removal of the file succeeded, false if not. (if the file didn’t exist, the return value is unspecified)

rs.rmdir(filename)
Remove a directory from the SD card. The directory must be empty. Returns true if the removal of the directory succeeded, false if not. (if the directory didn’t exist, the return value is unspecified)

File class

file.name()
Returns the file name

file.available()
Check if there are any bytes available for reading from the file. Returns the number of bytes.

file.close()
Close the file, and ensure that any data written to it is physically saved to the SD card.

file.flush()
Ensures that any bytes written to the file are physically saved to the SD card. This is done automatically when the file is closed.

file.peek()
Read a byte from the file without advancing to the next one. That is, successive calls to peek() will return the same value, as will the next call to read().

file.position()
Get the current position within the file (i.e. the location to which the next byte will be read from or written to). Returns the position within the file (unsigned long).

file.print(data) file.print(data, base)
Print data to the file, which must have been opened for writing. Prints numbers as a sequence of digits, each an ASCII character (e.g. the number 123 is sent as the three characters ‘1’, ‘2’, ‘3’). Parameter data: the data to print (char, byte, int, long, or string), BASE (optional): the base in which to print numbers: BIN for binary (base 2), DEC for decimal (base 10), OCT for octal (base 8), HEX for hexadecimal (base 16). Returns the number of bytes written, though reading that number is optional.

file.println() file.println(data) file.println(data, base)
As print but with final return

file.seek(pos)
Seek to a new position in the file, which must be between 0 and the size of the file (inclusive). Parameters: pos: the position to which to seek (unsigned long). Returns true for success, false for failure (boolean)

file.size()
Get the size of the file. Returns the size of the file in bytes (unsigned long).

file.read()  file.read(buf, len)
Read from the file. Returns the next byte (or character), or -1 if none is available.

file.write(data) file.write(buf, len)
Write data to the file. Returns the number of bytes written, though reading that number is optional

file.isDirectory()
Directories (or folders) are special kinds of files, this function reports if the current file is a directory or not. Returns true if is directory.

file.openNextFile()
Reports the next file or folder in a directory. Returns the next file or folder in the path.

file.rewindDirectory()
Will bring you back to the first file in the directory, used in conjunction with openNextFile().

Examples

In the Arduino IDE you can find some examples very usefully and well commented.

Here a schetck that extract all information about SD card used.

/*
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) {
}

Here an example of read write of an SD card.

/*
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
}

Thanks


Spread the love
  •  
  •  
  •  
  • 5
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
    5
    Shares

You may also like...

4 Responses

  1. hi. Does two board(Arduino and esp)have access to sd card at the same time?

    • Hi,
      At the same time no, but in theory you can use cs pin to check if someone access the sd at the moment and wait to have access.
      But every time you must disconnect and reconnect the sd.
      If you try the experiment let us know the result.
      Bye Renzo

  2. Tom says:

    Hello Renzo, good tutorial and great job!
    please find my correction note for your schematic “SDCard adapter and WeMos D1 miniature circuit diagram”. The picture of the SD card is wrong (mirror-inverted), the pull-up resistor should go to the MISO pin (instead of the SS), as you already mentioned.

    additional notes on my design:
    – usage of ‘WeMos D1 mini’ only, therfore add the pull-up resistor and the GND bridge directly to the SD card adapter
    – Connection ‘SDcard’ according to your tutorial
    – Use of the standard Arduino libraries ‘SPI.h’ and ‘SD.h’
    – tested with code example “ReadWrite” from the standard Arduino SD libraries:
    https://github.com/esp8266/Arduino/tree/master/libraries/SD/examples with adaptation of the ‘chip select’ pin to the standard pin 8 in case of NodeMCU and D8 in my case of ‘WeMos D1’
    best regards
    Tom

    Translated with http://www.DeepL.com/Translator (free version)

Leave a Reply

Your email address will not be published. Required fields are marked *