Monday, May 15, 2017

Demo 7: How to use Arduino ESP32 to store data to sdcard

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.
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 IO12 – MISO MICROSD]
[ESP32 IO27 – SCK MICROSD]
[ESP32 GND – GND MICROSD]
[3.3V – VCC MICROSD]
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>

File root;

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

  Serial.print("Initializing SD card...");
  /* initialize SD library with SPI pins */
  if (!SD.begin(26, 14, 12, 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(File dir, int numTabs) {
  
  while(true) {
     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

4 comments:

Alex Grauer 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

iotsharing dotcom said...

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

iotsharing dotcom said...

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.