Demo 7: How to use Arduino ESP32 to store data to microsdcard (Soft SPI and Hard SPI)

1. Introduction
The use of sdcard is to store the data. Because sdcard has big capacity so it can store more data comparing to EEPROM. Why sdcard is useful for ESP32? As you know ESP8266 and ESP32 are more popular with IoT application. They can keep the roles such as:
 - A client to collect data from sensors such as temperature or humidity or log of an event, and save these data into sdcard.
- A web server using sdcard to store web pages, images, javascript, … that will be returned to the client requests.
Since micro sdcard (microSD) is popular so we will use micro sdcard for our demo. Here is the requirements:
1. ESP32 connect to micro sdcard
2. Traverse the micro sdcard to list all files and folders in it and print to Terminal.
3. Open a file is named “test.txt” to write “Hello world!” text to it and close it
4. Open “test .txt” again for reading the text then print to Terminal and close it.
Note:
This demo used Soft SPI, so you can assign any GPIO pins as SPI pins.
If you just need to store small data, you can consider to use SPIFFS as in Demo 45: Copy data from/to SPIFFS without using mkspiffs (web file server)
If you want to copy data from/to sdcard without plugging in/out, see Demo 46: How to turn ESP with a sdcard or SPIFFS to a web file server.
2. Hardware
In order to connect with sdcard we use the sdcard read-write module :

 
Figure: module micro sdcard with SPI connection

Figure: ESP32 connect microSD module
Here we connect:
[ESP32 IO26 – CS MICROSD]
[ESP32 IO14 – MOSI MICROSD]
[ESP32 IO13 – MISO MICROSD]
[ESP32 IO27 – SCK MICROSD]
[ESP32 GND – GND MICROSD]
[3.3V – VCC MICROSD]

Note: If you want to use Hard SPI, please connect as follow:
MICROSD CS    -      ESP32 IO5
MICROSD SCK   -     ESP32 IO18
MICROSD MOSI  -    ESP32 IO23
MICROSD MISO   -   ESP32 IO19
MICROSD Vcc   -      ESP32 3.3V
MICROSD GND   -    ESP32 GND

3. Software
We will use library sdcard for communication. You can download it here:
https://github.com/nhatuan84/esp32-micro-sdcard
After downloading, unzip it and copy unzipped folder to libraries folder under Arduino folder:
C:/Users/[YOUR_USER_NAME]/Documents/Arduino/libraries
This library supplies some classes and interfaces:
Class SD:
- SD.begin(uint8_t cs , int8_t mosi , int8_t miso , int8_t sck): initialize library with SPI pins
- SD.open(filename, FILE_WRITE): open file for writing
- SD.open(filename): open file for reading
- SD.open("/"): open sdcard at root “/”
Class File:
- openNextFile(): traverse the directory
- name(): get the name of file or directory
- isDirectory(): check if entry is directory
- size(): get size of file
- close(): close the opened entry
- println(text): write text to opened file
- available(): check data available for reading
- read(): if data is available then read data
- close(): close the opened file
Create an Arduino project and Save as esp32msdinfo with code:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#include <mySD.h>

ext::File root;

void setup()
{
  Serial.begin(115200);

  Serial.print("Initializing SD card...");
  /* initialize SD library with Soft SPI pins, if using Hard SPI replace with this SD.begin()*/
  if (!SD.begin(26, 14, 13, 27)) {
    Serial.println("initialization failed!");
    return;
  }
  Serial.println("initialization done.");
  /* Begin at the root "/" */
  root = SD.open("/");
  if (root) {    
    printDirectory(root, 0);
    root.close();
  } else {
    Serial.println("error opening test.txt");
  }
  /* open "test.txt" for writing */
  root = SD.open("test.txt", FILE_WRITE);
  /* if open succesfully -> root != NULL 
    then write string "Hello world!" to it
  */
  if (root) {
    root.println("Hello world!");
    root.flush();
   /* close the file */
    root.close();
  } else {
    /* if the file open error, print an error */
    Serial.println("error opening test.txt");
  }
  delay(1000);
  /* after writing then reopen the file and read it */
  root = SD.open("test.txt");
  if (root) {    
    /* read from the file until there's nothing else in it */
    while (root.available()) {
      /* read the file and print to Terminal */
      Serial.write(root.read());
    }
    root.close();
  } else {
    Serial.println("error opening test.txt");
  }
  
  Serial.println("done!");
}

void loop()
{
}

void printDirectory(ext::File dir, int numTabs) {
  
  while(true) {
     ext::File entry =  dir.openNextFile();
     if (! entry) {
       break;
     }
     for (uint8_t i=0; i<numTabs; i++) {
       Serial.print('\t');   // we'll have a nice indentation
     }
     // Print the name
     Serial.print(entry.name());
     /* Recurse for directories, otherwise print the file size */
     if (entry.isDirectory()) {
       Serial.println("/");
       printDirectory(entry, numTabs+1);
     } else {
       /* files have sizes, directories do not */
       Serial.print("\t\t");
       Serial.println(entry.size());
     }
     entry.close();
   }
}
4. Result

 Figure: ESP32 connect to module microSD to display list of files/folders of sdcard and write file and read "Hello world!" text from file

Post a Comment

20 Comments

Unknown said…
Hi IOTSHARING DOTCOM,

Im trying to make you code work with the boards I have but im not being able to do it.
I have a this ESP-WROOM-32 board: http://www.ebay.com.au/itm/262953936783
And this micoSD shield: http://www.ebay.com.au/itm/191736124794

And the connections im doing are just directly from the ESP to the SD shield like this:
IO13 -> CS
IO15 -> MOSI
IO2 -> MISO
IO14 -> CLK
GND -> GND
3.3V -> 3.3V (I also tried with the 5V)

And of course I change your example code to:

SD.begin(13, 15, 2, 14)

I tried with two different microSD cards, but nothing.
I always get this:

rst:0x1 (POWERON_RESET),boot:0x1b (SPI_FAST_FLASH_BOOT)
ets Jun 8 2016 00:22:57

rst:0x10 (RTCWDT_RTC_RESET),boot:0x1b (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0010,len:4
load:0x3fff0014,len:708
load:0x40078000,len:0
load:0x40078000,len:11460
entry 0x400789f4
Initializing SD card...initialization failed!

Any clue about what could be that im doing wrong?
Thanks very much in advance.

Alex
Hi Alex,

Your microSD shield seems not to be similar to my module:
https://www.quora.com/Whats-the-difference-between-a-TF-card-and-a-Micro-SD-card

I also looked the pcb of both. They are also different.

Regards,

:)

Tony said…
How do you setup your code to do a rename or copy? Thanks
Hi,
A rename is equivalent to actions:
- Open old file
- Open new file
- Copy content from old file to new file
- Delete old file
A copy: you can not have 2 files with the same name in same folder. So just do:
- Open new file
- Open old file
- Copy content from old to new file.
Unknown said…
With the shield microSD reader, working. This link; https://ft81xmania.com/comunidad/Tema-microsd-reader-for-esp32
Francis said…
Hi,

I have
https://www.banggood.com/Wemos-Lolin-ESP32-OLED-Module-For-Arduino-ESP32-OLED-WiFi-Bluetooth-Dual-ESP-32-ESP-32S-ESP8266-p-1148119.html

GPIO 27 not exist..
if I do SD.begin(25, 14, 12, 26)
Then
>ets Jun 8 2016 00:22:57

rst:0x10 (RTCWDT_RTC_RESET),boot:0x3f (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
cmd len -1
Falling back to built-in command interpreter.
OK

Help !
Anonymous said…
Hi,
I have same SD card module but I always get sd card initalization failed message.
I am using LOLIN32 board with selected pins 32, 23, 19, 18.
I even did soldering modification of SD card reader: https://forum.mysensors.org/topic/6724/solved-nodemcu-esp8266-and-spi-with-nrf24l01-sd-card-module-sanity-errors/4
Allen said…
Is there any way to enable your library to use long file names?
Unknown said…
Hi:
Thanks for your instructions.
I had some success writing text to my SD card, BUT I was not able
to write numbers. The problem is in converting numbers to strings.
This seems to be much trickier than I thought.
I thought I understood the problem but kept getting compile errors.
I hope that you or someone could make an example program that
converts the numbers to strings and writes the strings to the SD card.

Chuck
yhe said…
Hi, I meet the same problem. I followed your blogger step by step but the monitor said that

"rst:0x10 (RTCWDT_RTC_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
flash read err, 1000
ets_main.c 371
ets Jun 8 2016 00:22:57"

I really do not know how to solve, please help me!
Anonymous said…
On my module (looks like the first picture) the 3.3V didn't work!
Had to be 5Volt! ... now it works fine! THX!
Anonymous said…
Thank you for the mySD library.
it's working with ESP32. it allows the files timestamp to be the right one.
Unknown said…
HI
there is a problem with some of my libraries and I can not use mysd.h because somewhere the sd.h is used by other libs
so is there any possibility to use sd.h with this ///boolean begin(uint8_t csPin = SD_CHIP_SELECT_PIN, int8_t mosi = -1, int8_t miso = -1, int8_t sck = -1);
Unknown said…
hello im using your code but with different pins, here im getting error in printDirectory.
the error is printDirectory was not decalre in this scope.

sketch_jul26a:24:27: error: 'printDirectory' was not declared in this scope

printDirectory(root, 0);
Unknown said…
Iam getting SD card initialization failed with esp32
Anonymous said…
Hi, thank you for your guide. I am having a hard time understanding an issue, I connected the hard pins and uploaded the code as guided but I am getting SD card initialization failed. I edited the SD.begin(); as mentioned but it is no help. I even tried 5v to VCC. Note I am using the same ESP32 module and sd card module.
Unknown said…
Hi! The script works perfectly in arduino for me
Do you know hot to implement the same script in esp-idf framework?
I really need that but I can't figure it out

Thank you in advance for any help
Unknown said…
em chào anh. e xem qua github thấy hình như anh là ng VN :)) a cho e hỏi e đang bị lỗi khởi tạo thiết bị lỗi. em cảm ơn
Anonymous said…
Did anybody find a fix for this problem I am using ESP32-WROOM and I used Pin 13 for CS on SD card and I get the exact same error
rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0018,len:4
load:0x3fff001c,len:1216
ho 0 tail 12 room 4
load:0x40078000,len:10944
load:0x40080400,len:6388
entry 0x400806b4
E (143) psram: PSRAM ID read error: 0xffffffff
Card Mount Failed