ESP32 Data Logging Temperature to MicroSD Card

This project shows how to log data with timestamps to a microSD card using the ESP32. As an example, we’ll log temperature readings from the DS18B20 sensor every 10 minutes. The ESP32 will be in deep sleep mode between each reading, and it will request the date and time using Network Time Protocol (NTP).

Project Overview

Before getting started, let’s highlight the project’s main features:

  • The ESP32 reads temperature using the DS18B20 temperature sensor.
  • After getting the temperature, it makes a request to an NTP (Network Time Protocol) server to get date and time. So, the ESP32 needs a Wi-Fi connection.
  • The data (temperature and timestamp) are logged to a microSD card. To log data to the microSD card we’re using a microSD card module.
  • After completing these previous tasks, the ESP32 sleeps for 10 minutes.
  • The ESP32 wakes up and repeats the process.

Parts Required

Here’s a list of the parts required to build this project (click the links below to find the best price at Maker Advisor):

You can use the preceding links or go directly to MakerAdvisor.com/tools to find all the parts for your projects at the best price!

Preparing the microSD Card Module

To save data on the microSD card with the ESP32, we use the following microSD card module that communicates with the ESP32 using SPI communication protocol.

Formatting the microSD card

When using a microSD card with the ESP32, you should format it first. Follow the next instructions to format your microSD card.

1. Insert the microSD card in your computer. Go to My Computer and right click on the SD card. Select Format as shown in figure below.

2. A new window pops up. Select FAT32, press Start to initialize the formatting process and follow the onscreen instructions.

Schematic

Follow the next schematic diagram to assemble the circuit for this project.

You can also use the following table as a reference to wire the microSD card module:

MicroSD Card ModuleESP32
3V33V3
CSGPIO 5
MOSIGPIO 23
CLKGPIO 18
MISOGPIO 19
GNDGND

The next figure shows how your circuit should look like:

Preparing the Arduino IDE

There’s an add-on for the Arduino IDE that allows you to program the ESP32 using the Arduino IDE and its programming language. Follow one of the next tutorials to prepare your Arduino IDE to work with the ESP32, if you haven’t already.

After making sure you have the ESP32 add-on installed, you can continue with this tutorial.

Installing Libraries

Before uploading the code, you need to install some libraries in your Arduino IDE.  The OneWire library by Paul Stoffregen and the Dallas Temperature library, so that you can use the DS18B20 sensor. You also need to install the NTPClient library forked by Taranais to make request to an NTP server.

Follow the next steps to install those libraries in your Arduino IDE:

OneWire library

  1. Click here to download the OneWire library. You should have a .zip folder in your Downloads
  2. Unzip the .zip folder and you should get OneWire-master folder
  3. Rename your folder from OneWire-master to OneWire
  4. Move the OneWire folder to your Arduino IDE installation libraries folder
  5. Finally, re-open your Arduino IDE

Dallas Temperature library

  1. Click here to download the DallasTemperature library. You should have a .zip folder in your Downloads
  2. Unzip the .zip folder and you should get Arduino-Temperature-Control-Library-master folder
  3. Rename your folder from Arduino-Temperature-Control-Library-master to DallasTemperature
  4. Move the DallasTemperaturefolder to your Arduino IDE installation libraries folder
  5. Finally, re-open your Arduino IDE

NTPClient library

  1. Click here to download the NTPClient library. You should have a .zip folder in your Downloads
  2. Unzip the .zip folder and you should get NTPClient-master folder
  3. Rename your folder from NTPClient-master to NTPClient
  4. Move the NTPClientfolder to your Arduino IDE installation libraries folder
  5. Finally, re-open your Arduino IDE

Uploading Code

Here’s the code you need to upload to your ESP32. Before uploading, you need to modify the code to include your network credentials (SSID and password). Continue reading to learn how the code works.

/*********
  Rui Santos
  Complete project details at https://randomnerdtutorials.com  
*********/

// Libraries for SD card
#include "FS.h"
#include "SD.h"
#include <SPI.h>

//DS18B20 libraries
#include <OneWire.h>
#include <DallasTemperature.h>

// Libraries to get time from NTP Server
#include <WiFi.h>
#include <NTPClient.h>
#include <WiFiUdp.h>

// Define deep sleep options
uint64_t uS_TO_S_FACTOR = 1000000;  // Conversion factor for micro seconds to seconds
// Sleep for 10 minutes = 600 seconds
uint64_t TIME_TO_SLEEP = 600;

// Replace with your network credentials
const char* ssid     = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

// Define CS pin for the SD card module
#define SD_CS 5

// Save reading number on RTC memory
RTC_DATA_ATTR int readingID = 0;

String dataMessage;

// Data wire is connected to ESP32 GPIO 21
#define ONE_WIRE_BUS 21
// Setup a oneWire instance to communicate with a OneWire device
OneWire oneWire(ONE_WIRE_BUS);
// Pass our oneWire reference to Dallas Temperature sensor 
DallasTemperature sensors(&oneWire);

// Temperature Sensor variables
float temperature;

// Define NTP Client to get time
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP);

// Variables to save date and time
String formattedDate;
String dayStamp;
String timeStamp;

void setup() {
  // Start serial communication for debugging purposes
  Serial.begin(115200);

  // Connect to Wi-Fi network with SSID and password
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected.");

  // Initialize a NTPClient to get time
  timeClient.begin();
  // Set offset time in seconds to adjust for your timezone, for example:
  // GMT +1 = 3600
  // GMT +8 = 28800
  // GMT -1 = -3600
  // GMT 0 = 0
  timeClient.setTimeOffset(3600);

  // Initialize SD card
  SD.begin(SD_CS);  
  if(!SD.begin(SD_CS)) {
    Serial.println("Card Mount Failed");
    return;
  }
  uint8_t cardType = SD.cardType();
  if(cardType == CARD_NONE) {
    Serial.println("No SD card attached");
    return;
  }
  Serial.println("Initializing SD card...");
  if (!SD.begin(SD_CS)) {
    Serial.println("ERROR - SD card initialization failed!");
    return;    // init failed
  }

  // If the data.txt file doesn't exist
  // Create a file on the SD card and write the data labels
  File file = SD.open("/data.txt");
  if(!file) {
    Serial.println("File doens't exist");
    Serial.println("Creating file...");
    writeFile(SD, "/data.txt", "Reading ID, Date, Hour, Temperature \r\n");
  }
  else {
    Serial.println("File already exists");  
  }
  file.close();

  // Enable Timer wake_up
  esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);

  // Start the DallasTemperature library
  sensors.begin(); 

  getReadings();
  getTimeStamp();
  logSDCard();
  
  // Increment readingID on every new reading
  readingID++;
  
  // Start deep sleep
  Serial.println("DONE! Going to sleep now.");
  esp_deep_sleep_start(); 
}

void loop() {
  // The ESP32 will be in deep sleep
  // it never reaches the loop()
}

// Function to get temperature
void getReadings(){
  sensors.requestTemperatures(); 
  temperature = sensors.getTempCByIndex(0); // Temperature in Celsius
  //temperature = sensors.getTempFByIndex(0); // Temperature in Fahrenheit
  Serial.print("Temperature: ");
  Serial.println(temperature);
}

// Function to get date and time from NTPClient
void getTimeStamp() {
  while(!timeClient.update()) {
    timeClient.forceUpdate();
  }
  // The formattedDate comes with the following format:
  // 2018-05-28T16:00:13Z
  // We need to extract date and time
  formattedDate = timeClient.getFormattedDate();
  Serial.println(formattedDate);

  // Extract date
  int splitT = formattedDate.indexOf("T");
  dayStamp = formattedDate.substring(0, splitT);
  Serial.println(dayStamp);
  // Extract time
  timeStamp = formattedDate.substring(splitT+1, formattedDate.length()-1);
  Serial.println(timeStamp);
}

// Write the sensor readings on the SD card
void logSDCard() {
  dataMessage = String(readingID) + "," + String(dayStamp) + "," + String(timeStamp) + "," + 
                String(temperature) + "\r\n";
  Serial.print("Save data: ");
  Serial.println(dataMessage);
  appendFile(SD, "/data.txt", dataMessage.c_str());
}

// Write to the SD card (DON'T MODIFY THIS FUNCTION)
void writeFile(fs::FS &fs, const char * path, const char * message) {
  Serial.printf("Writing file: %s\n", path);

  File file = fs.open(path, FILE_WRITE);
  if(!file) {
    Serial.println("Failed to open file for writing");
    return;
  }
  if(file.print(message)) {
    Serial.println("File written");
  } else {
    Serial.println("Write failed");
  }
  file.close();
}

// Append data to the SD card (DON'T MODIFY THIS FUNCTION)
void appendFile(fs::FS &fs, const char * path, const char * message) {
  Serial.printf("Appending to file: %s\n", path);

  File file = fs.open(path, FILE_APPEND);
  if(!file) {
    Serial.println("Failed to open file for appending");
    return;
  }
  if(file.print(message)) {
    Serial.println("Message appended");
  } else {
    Serial.println("Append failed");
  }
  file.close();
}

View raw code

How the Code Works

In this example, the ESP32 is in deep sleep mode between each reading. In deep sleep mode, all your code should go in the setup() function, because the ESP32 never reaches the loop().

Importing libraries

First, you import the needed libraries for the microSD card module:

#include "FS.h"
#include "SD.h"
#include <SPI.h>

Import these libraries to work with the DS18B20 temperature sensor.

#include <OneWire.h>
#include <DallasTemperature.h>

The following libraries allow you to request the date and time from an NTP server.

#include <WiFi.h>
#include <NTPClient.h>
#include <WiFiUdp.h>

Setting deep sleep time

This example uses a conversion factor from microseconds to seconds, so that you can set the sleep time in the TIME_TO_SLEEP variable in seconds.

In this case, we’re setting the ESP32 to go to sleep for 10 minutes (600 seconds). If you want the ESP32 to sleep for a different period of time, you just need to enter the number of seconds for deep sleep in the TIME_TO_SLEEP variable.

// Define deep sleep options
uint64_t uS_TO_S_FACTOR = 1000000; // Conversion factor for micro seconds to seconds
// Sleep for 10 minutes = 600 seconds
uint64_t TIME_TO_SLEEP = 600;

Setting your network credentials

Type your network credentials in the following variables, so that the ESP32 is able to connect to your local network.

// Replace with your network credentials
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

Initializing sensors and variables

Next, define the microSD card SD pin. In this case, it is set to GPIO 5.

#define SD_CS 5

Create a variable called readingID to hold the reading ID. This is a way to get your readings organized. To save a variable value during deep sleep, we can save it in the RTC memory. To save data on the RTC memory, you just need to add RTC_DATA_ATTR before the variable definition.

// Save reading number on RTC memory
RTC_DATA_ATTR int readingID = 0;

Create a String variable to hold the data to be saved on the microSD card.

String dataMessage;

Next, create the instances needed for the temperature sensor. The temperature sensor is connected to GPIO 21.

// Data wire is connected to ESP32 GPIO21
#define ONE_WIRE_BUS 21
// Setup a oneWire instance to communicate with a OneWire device
OneWire oneWire(ONE_WIRE_BUS);
// Pass our oneWire reference to Dallas Temperature sensor 
DallasTemperature sensors(&oneWire);

Then, create a float variable to hold the temperature retrieved by the DS18B20 sensor.

float temperature;

The following two lines define an NTPClient to request date and time from an NTP server.

WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP);

Then, initialize String variables to save the date and time.

String formattedDate;
String dayStamp;
String timeStamp;

setup()

When you use deep sleep with the ESP32, all the code should go inside the setup() function, because the ESP32 never reaches the loop().

Connecting to Wi-Fi

The following snippet of code connects to the Wi-Fi network. You need to connect to wi-fi to request date and time from the NTP server.

Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
  delay(500);
  Serial.print(".");
}

Initializing the NTP client

Next, initialize the NTP client to get date and time from an NTP server.

timeClient.begin();

You can use the setTimeOffset(<time>) method to adjust the time for your timezone.

timeClient.setTimeOffset(3600);

Here are some examples for different timezones:

  • GMT +1 = 3600
  • GMT +8 = 28800
  • GMT -1 = -3600
  • GMT 0 = 0

Initializing the microSD card module

Then, initialize the microSD card. The following if statements check if the microSD card is properly attached.

SD.begin(SD_CS); 
if(!SD.begin(SD_CS)) {
  Serial.println("Card Mount Failed");
  return;
}
uint8_t cardType = SD.cardType();
if(cardType == CARD_NONE) {
  Serial.println("No SD card attached");
  return;
}
Serial.println("Initializing SD card...");
if (!SD.begin(SD_CS)) {
  Serial.println("ERROR - SD card initialization failed!");
  return; // init failed
}

Then, try to open the data.txt file on the microSD card.

File file = SD.open("/data.txt");

If that file doesn’t exist, we need to create it and write the heading for the .txt file.

writeFile(SD, "/data.txt", "Reading ID, Date, Hour, Temperature \r\n");

If the file already exists, the code continues.

else {
  Serial.println("File already exists");
}

Finally, we close the file.

file.close();

Enable timer wake up

Then, you enable the timer wake up with the timer you’ve defined earlier in the TIME_TO_SLEEP variable.

esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);

Initializing the library for DS18B20

Next, you initialize the library for the DS18B20 temperature sensor.

sensors.begin();

Getting the readings and data logging

After having everything initialized, we can get the readings, timestamp, and log everything into the microSD card.

To make the code easier to understand, we’ve created the following functions:

  • getReadings(): reads the temperature from the DS18B20 temperature sensor;
  • getTimeStamp(): gets date and time from the NTP server;
  • logSDcard(): logs the preceding data to the microSD card.

After completing these tasks, we increment the readingID.

readingID++;

Finally, the ESP32 starts the deep sleep.

esp_deep_sleep_start();

getReadings()

Let’s take a look at the getReadings() function. This function simply reads temperature from the DS18B20 temperature sensor.

sensors.requestTemperatures(); 
temperature = sensors.getTempCByIndex(0); // Temperature in Celsius

By default, the code retrieves the temperature in Celsius degrees. You can uncomment the following line and comment the previous one to get temperature in Fahrenheit.

//temperature = sensors.getTempFByIndex(0); // Temperature in Fahrenheit

getTimeStamp()

The getTimeStamp() function gets the date and time. These next lines ensure that we get a valid date and time:

while(!timeClient.update()) {
  timeClient.forceUpdate();
}

Sometimes the NTPClient retrieves the year of 1970. To ensure that doesn’t happen we force the update.

Then, convert the date and time to a readable format with the getFormattedDate() method:

formattedDate = timeClient.getFormattedDate();

The date and time are returned in this format:

2018-04-30T16:00:13Z

So, we need to split that string to get date and time separately. That’s what we do here:

// Extract date
int splitT = formattedDate.indexOf("T");
dayStamp = formattedDate.substring(0, splitT);
Serial.println(dayStamp);
// Extract time
timeStamp = formattedDate.substring(splitT+1, formattedDate.length()-1);
Serial.println(timeStamp);

The date is saved on the dayStamp variable, and the time on the timeStamp variable.

logSDCard()

The logSDCard() function concatenates all the information in the dataMessage String variable. Each reading is separated by commas.

dataMessage = String(readingID) + "," + String(dayStamp) + "," + String(timeStamp) + "," + String(temperature) + "\r\n";

Note: the “\r\n” at the end of the dataMessagevariable ensures the next reading is written on the next line.

Then, with the following line, we write all the information to the data.txt file in the microSD card.

appendFile(SD, "/data.txt", dataMessage.c_str());

Note: the appendFile() function only accepts variables of type const char for the message. So, use the c_str() method to convert the dataMessage variable.

writeFile() and appendFile()

The last two functions: writeFile() and appendFile() are used to write and append data to the microSD card. They come with the SD card library examples and you shouldn’t modify them.

To try other examples to work with the microSD card, go to File > Examples > SD(esp32).

Uploading the Code

Now, upload the code to your ESP32. Make sure you have the right board and COM port selected.

Demonstration

Open the Serial Monitor at a baud rate of 115200.

Press the ESP32 Enable button, and check that everything is working properly (the ESP32 is connected to your local network, and the microSD card is properly attached).

Note: If everything is wired properly and you keep getting an error initializing the SD card, powering your microSD card module with 5V might solve the issue.

Let the ESP32 run for a few hours to test if everything is working as expected. After the testing period, remove the microSD card and insert it into your computer. The microSD card should contain a file called data.txt.

You can copy the file content to a spreadsheet on Google Sheets for example, and then split the data by commas. To split data by commas, select the column where you have your data, then go to Data > Split text to columns… Then, you can build charts to analyse the data.

Wrapping Up

In this tutorial we’ve shown you how to log data to a microSD card using the ESP32. We’ve also shown you how to read temperature from the DS18B20 temperature sensor and how to request time from an NTP server.

You can apply the concepts from this tutorial to your own projects. If you like ESP32 and you want to learn more, make sure you check our course exclusively dedicated to the ESP32: Learn ESP32 with Arduino IDE.

You might also like reading other articles related with ESP32:

Thanks for reading.



Learn how to build a home automation system and we’ll cover the following main subjects: Node-RED, Node-RED Dashboard, Raspberry Pi, ESP32, ESP8266, MQTT, and InfluxDB database DOWNLOAD »
Learn how to build a home automation system and we’ll cover the following main subjects: Node-RED, Node-RED Dashboard, Raspberry Pi, ESP32, ESP8266, MQTT, and InfluxDB database DOWNLOAD »

Enjoyed this project? Stay updated by subscribing our newsletter!

135 thoughts on “ESP32 Data Logging Temperature to MicroSD Card”

      • hi, i hope that you are doing well
        you said that the code for this project is not compatible with the esp8266
        what should I do or change in the code to make it compatible with it
        I’ve lot of errors
        1-const char to char
        2-cardType

        but “listfiles” example code work

        Reply
  1. It was very useful, Roy. thanks,.
    I hope, you work on projects that connecting esp8266 or esp32 to LABVIEW (Control & Monitor).

    Reply
  2. Hey Rui, how are you?!
    Thankx for sharing your projects, they are clear and educationals!
    I´m not working with the NTPClient, but i has add in my project! hehehe

    Only one point… in the NPT offset, the example you show, for plus eigth hours, maybe you writing wrong, because the paramter is the hours in seconds, is this?
    I´m live in Brazil, and here we have -3 hours. So im use 10800?

    Rui, very thankyou for showing the code, was very clarance efor me!

    Reply
    • Hi Carlos.
      Yes, you are right. The offset for the eight hours was wrong. We’ve already updated that.
      Thanks for noticing and for reading our projects.
      Regards,
      Sara 🙂

      Reply
  3. Great tutorial, and nice to see deep sleep illustrated. It would be great to show how to do battery powered projects. I have a couple of related questions on this project– on this dev board (or other dev boards with a LiPo charger) is the USB-UART always powered on via the same 3.3V ESP module supply? (An unused USB-UART could drain a battery.) In deep sleep what is the power consumption, i.e. how long can a battery last?

    BTW, I would suggest a sleep calculated to wake at the next 10 minute real-clock interval rather than 600s, so the some seconds to make a WiFi + NTP connection doesn’t shift the interval. But that’s a pretty straightforward change in your tutorial code.

    Reply
    • For a real lower power application with the ESP32, you shouldn’t use an ESP32 Development board. It’s recommended to use an ESP32 chip directly on your own PCB, because any dev board has many unnecessary components draining the batteries (even in deep sleep).

      Reply
  4. Thanks !
    I have to use a battery and it seems that the largest drain is getting the network time.
    have you tried to get it once every 24hours ? or maybe every 6 hours ?

    Reply
    • Hi Dave.
      I haven’t tried with 24 hours interval.
      But you can edit the deep sleep time in the code. It doesn’t have to be every 10 minutes.
      Getting the network time consumes a lot of power because the ESP32 needs to connect via Wi-Fi.
      To get very low power consumption during deep sleep, you need to use the bare ESP32 chip instead of the full development board (as we do here, but with the ESP8266 – only 7uA during deep sleep)
      Regards,
      Sara

      Reply
  5. more on the delayed fetch of time
    Can the ESP32 re-set it’s internal time so that it can wake and datalog every 5 minutes, and once an hour reset the time and post error?
    jan5 6:06:02 21.3C
    jan5 6:11:122 21.5C
    jan5 6:16:24 21.3C
    jan5 6:21:33 20.9C
    jan5 6:25:04 21.3C time adjust 2951ms

    Reply
  6. Hi Rui and Sandra, i have some problem with sd card. Com port show this massage:

    ets Jun 8 2016 00:22:57

    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:1100
    load:0x40078000,len:10312
    load:0x40080400,len:6460
    entry 0x400806a4
    Card Mount Failed

    Can u help me with this?

    Reply
    • Hi Andrey,
      Please double check that the microSD card module is wired correctly to the ESP32. Make sure you are using a microSD card formatted as FAT32.
      Before continuing with the project, can you try the microSD card example available on Arduino IDE? Go to File > Examples > SD(esp32) > SD_Test.
      Upload that code and see how the microSD responds.
      Regards,
      Sara

      Reply
      • Hi Sara, microSD card module is wired correctly and its work with esp12e module, but didnt work with esp32. The SD_tesr example dont work too with same result.

        Reply
        • Hey Andrey, i had the same problem. The datasheet for my SD module says something about VCC-in 3.3v/5v, i used it with the 3.3v output of my esp32, which didn’t work. I then used the 5v and voila, everything worked! maybe it can help you!

          Reply
  7. Hi,
    It would be awesome if one could transfer the log file over Wi-Fi (internet even), without removing the SD card !

    Could you provide some pointers on how to achieve this ?

    Reply
      • Hi, I have the same question of Royce J Pereira… a way to save the file_data from SD (ESP32) to windows folder. Removing the SD card is an operation for a caveman!!! 😀 😀
        Have you any suggestion? libraries? link?
        Thanks for your support and for the detailed and usefull blog….IT’S FANTASTIC!!

        Reply
      • I forgot to add an important information to my previous post: the way to save the file from SD and windows folder has to be through wi-fi connection to private network.
        If it is not possible (or too complicated), please consider that the ESP32 it is not connected to pc by USB, only by wi-fi network.
        Thanks in advance.
        regards
        Francesco

        Reply
        • Hi Francesco.
          Your suggestion is a great idea.
          However, at the moment I don’t have any solution for that. That is quite a big project.
          I don’t know if there are any libraries that can do that, I haven’t search much about the subject.
          Sorry that I can’t help much and thank you for following our work.
          Regards,
          Sara

          Reply
          • Hi, thanks for reply.
            I surfed in net to find solutions….and I found it…
            forum.arduino.cc/index.php/topic,93502.msg707104.html#msg707104
            I could use the FTP way. The library WIFI should permit to choose the right address and the right gate for a FTP server. Then with ftp command I can copy the file from sd to server… it seems good… what do you think? 😉
            Bye. Francesco

  8. Should this project work with the newer AI Thinker boards, that have the built in card reader (and camera, but we do not always have to use it)? I imagine that would save a lot of wiring.

    Reply
    • Hi John.
      I haven’t tried it. But I think it should work by doing the proper pin assignment in the code.
      Regards,
      Sara

      Reply
  9. HI,
    I cannot understand why my post is disappearing while it is “awaiting moderation”.

    Anyway this is my 3rd attempt.

    I am always getting ‘Card Mount Failed’.

    But the in built SD_test example works fine.

    Why could this be happening.

    Reply
    • If you try to submit multiple comments very quickly, it will probably block you and flag the comment as spam.
      I’m not sure… That usually means that you either need to double-check your wiring or if you have formatted the MicroSD card in the properly.

      Reply
      • Hi, thanks for the response.

        But as I said in my comment, The inbuilt SD_test example works fine .
        (i.e. File > Examples > SD(esp32) > SD_Test.)

        Only the code from this project is failing.

        The wiring in both cases is the same!

        Thank you!

        Reply
  10. Yes.
    Strangely, after retrying it the next day, it worked fine with both programs, without changing a thing…

    Thank you for taking the trouble to check!
    ——-
    (Unrelated) I have observed the following in your code:

    In line 81:
    SD.begin(SD_CS);
    if(!SD.begin(SD_CS)) { ….

    Is the 1st SD.begin necessary ?

    Again in line 91 once again we have :
    Serial.println(“Initializing SD card…”);
    if (!SD.begin(SD_CS)) { …

    This code will never be reached if already failed in line 82 above.
    Otherwise, SD card is already initialized in line 81/82, so I think no need for this again?

    And let me thank you for all these projects and the courses. I’m learning a lot! 🙂

    Reply
    • I’m glad it is working now.
      Yes, you are right. We have to fix the code.
      Thank you for pointing that out.
      Regards,
      Sara

      Reply
  11. Hello,

    First, an excellent tutorial and guide.

    However, I have the same problem with SD card as reported by Andrey
    on April 3 2019 — “Card Mount Failed” error.

    I have checked that wiring is correct.
    The microSD card is formatted as FAT32.
    I can write/read files to it when plugged into PC.
    I have also tried File > Examples > SD(esp32) > SD_Test: That gives same error.
    ( Contrary to Royce, May 1, for whom the test example worked )
    I have tried suggestion by Andi (Apr 11), connecting SD module VCC to 5V: Still the same error.
    I have tried a second SD card module, also same error.

    Andrey’s thread ends without any solution reported. I wonder if he found a fix?
    In Royce’s case the problem vanished the next day! I don’t hold much hope
    for that to happen for me.

    So for now I am stuck! Any suggestions you can offer?
    Many thanks, Ken.

    Reply
    • Hi Ken.
      If you’ve double-check the wiring, tried an external power source and you’ve tried with 5V and nothing worked, I don’t know what can be the problem.
      I’m sorry that I can’t help much, the example works just fine for me.
      Regards,
      Sara

      Reply
  12. Hello Again,
    To follow-up on my comment of 18 May about “Card Mount Failed” error.
    I have connected my SD card to an ATMega328, and uploaded
    File>Examples>SD>ReadWrite
    using a USBtiny programmer.
    This work just fine; I can write to and read from the SD card.
    So there is nothing wrong with my card or connections.

    But when I use the ESP32 DoIt Dev Board with
    File > Examples > SD(esp32) > SD_Test
    I consistently get “Card Mount Failed” error.

    Compiling the ATMega328 sketch, the following is reported:
    Using library SPI at version 1.0 in folder: C:\Program Files (x86)\arduino-1.8.9\hardware\arduino\avr\libraries\SPI
    Using library SD at version 1.2.3 in folder: C:\Program Files (x86)\arduino-1.8.9\libraries\SD

    But compiling the ESP32sketch, the following is reported:
    Multiple libraries were found for “SD.h”
    Used: C:\Users\Ken\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.2\libraries\SD
    Not used: C:\Program Files (x86)\arduino-1.8.9\libraries\SD
    Using library SPI at version 1.0 in folder: C:\Users\Ken\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.2\libraries\SPI
    Using library SD at version 1.0.5 in folder: C:\Users\Ken\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.2\libraries\SD
    Using library FS at version 1.0 in folder: C:\Users\Ken\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.2\libraries\FS

    So the ESP32 version uses different code for the SD card (as would be expected). This strongly suggests that the problem is with the code.

    It seems from the Comments that quite a lot of your followers have this problem, and some have managed to find a fix. But for now I am completely stuck, and can go no further with my project. Perhaps you can suggest another forum that might be able to help?
    With thanks, ken.

    Reply
  13. Hello Again,

    Solution found to my “Card Mount Failed” error.

    After many hours trying to fix this problem, as a last resort
    I tried using another ESP32 DoIt Dev Board (I had purchased two
    boards). And it worked! The boards are new from RS, so thought
    it very unlikely that one would be faulty, especially as the faulty
    board seemed to work OK in other respects, eg. connecting successfully
    to WiFi.

    As always, the problem is with the last thing you try. Now it’s
    onwards and upwards!

    Thanks, Ken.

    Reply
    • Hi Ken.
      I’m glad you solved your problem.
      So, it was a problem in your previous ESP32 board, right?
      Regards,
      Sara

      Reply
      • Hi Sara,
        Yes, that’s right — faulty board. I have swapped them back and
        forth a few times and one is OK, the other always fails.
        Very unexpected, but maybe I was just unlucky.
        Regards, ken.

        Reply
        • Hi Ken.
          Yes, it is very unexpected.
          I’ve worked with several ESP32 boards from different vendors and I’ve never had a faulty one.
          Maybe it is bad luck 🙁
          Regards,
          Sara

          Reply
  14. Hi,
    Ken here again.
    First, apologies for such a long comment.

    Following my earlier comments, ending on 1 June, everything was working just fine, and continued to work for a couple of weeks. But now, after doing other unrelated stuff for about a week, I have gone back to the data logging project, and a new problem has appeared! As far as I’m aware I have not changed anything significant, in particular, I have changed nothing in the code (anyway, problem is not the code)

    I have selected board “ESP32 Dev Module”
    and programmer “Arduino as ISP”
    (These are what I used when it was working)
    Compile is OK.
    I then attempt Upload Using Programmer.
    I get following error message:

    java.lang.NullPointerException
    at cc.arduino.packages.uploaders.SerialUploader.uploadUsingProgrammer(SerialUploader.java:314)
    at cc.arduino.packages.uploaders.SerialUploader.uploadUsingPreferences(SerialUploader.java:89)
    at cc.arduino.UploaderUtils.upload(UploaderUtils.java:82)
    at processing.app.SketchController.upload(SketchController.java:736)
    at processing.app.SketchController.exportApplet(SketchController.java:703)
    at processing.app.Editor$DefaultExportAppHandler.run(Editor.java:2125)
    at java.lang.Thread.run(Thread.java:748)

    To eliminate code issues, I have tried an absolute minimum sketch, as follows:
    void setup() {
    }
    void loop() {
    }
    Obviously this does nothing, but it compiles OK.
    But on Upload Using Programmer I get same error message:

    If I unplug the board I get exactly same error. This implies the problem occurs before it even get as far as trying to communicate with board.

    This happens when I select any ESP32 board, but does NOT happen when I select any Arduino board, when I just get the expected “programmer is not responding” error.

    I have uninstalled Java and re-installed Java release 1.8.0_211
    I have uninstalled Arduino IDE, deleted folder “C:\Users\Ken\AppData\Local\Arduino15”,
    and then re-installed latest version 1.8.9 (which is what I have been using).
    I then install the ESP32 Board in Arduino IDE (Windows instructions) exactly
    as in the link you give to
    https://randomnerdtutorials.com/installing-the-esp32-board-in-arduino-ide-windows-instructions/

    Following this, no change, still get same error.

    I have uninstalled Arduino IDE again, deleted folder “C:\Users\Ken\AppData\Local\Arduino15”,
    and then re-installed OLDER version 1.8.7

    And again, no change, still get same error.

    All the above indicates that there is nothing wrong with the sketch, and nothing wrong with the board, and to repeat — it all worked fine about a week ago, and I am not aware of having changed anything significant.

    I have spent several hours Googling “java.lang.NullPointerException”.
    There are many links, mostly just confusing and not offering a fix.
    The main message seems to be that there is a mistake in the code, and indeed the error message seems to be pointing at errors at specific lines
    in seven different .java files (see above).

    But I have done a search of my whole C drive and cannot find any of these .java files.

    So I’m stuck again!
    Any suggestions on what I should do?
    Thank you, Ken.

    Reply
  15. Hi,
    Me again!

    I have found what causes problem:
    I have been trying to uploading the sketch with “Upload Using Programmer”.
    If I use “Upload”, NOT “Upload Using Programmer”, everything is fine.

    Strange thing is, I’m fairly sure I used “Upload Using Programmer” earlier, before this latest round of problems. That would seem correct since
    there is no bootloader on the ESP chip.

    Anyway, grovelling apologies for cluttering your comments with this stuff.
    Feel free to delete this and my long previous comment.
    Thanks, Ken.

    Reply
  16. Hi!

    I’m saving data on micro sd with my Esp32 (Wemos WIFI & Bluetooth Battery), and i have a problem, while the esp it´s sleeping, data inside txt file continue writing but the same data, and does this until Esp wakes up again, and send the new data, then happens the same, data it´s repeat again on the txt file even though the esp it´s sleeping, and happens until the esp send data again.

    Do you know how i can solve it?? please, thanks!!!

    Reply
      • Hi Sara,

        I´m using the same example of this tutorial, just with another sensors and without take network time, but just change is in the measurements, write data and sleep is equal to your example, so, each 5 seconds last data is written again while the Esp is sleeping and wake up and send new data, and i don´t know how to solve it!

        ¿Do you know how solve it? or maybe this happened to you?

        Thanks!!

        Duvan!

        Reply
  17. I dont know if someone knows more about SD card mounting than me but I am having trouble getting the card to mount after coming out of deep sleep. It gives the error “sd card mount fail”

    Reply
  18. Hi,

    I am trying to implement a card reader for an ESP32 project and am not making much progress in initialising the card.

    I have done all of the above example and have slightly modified it to run without sleep, wifi and the temp sensor to just test the card element. Pin connections are as per your example. I am using a DOIT DEVKIT ESP32.

    I am getting card mount failure when I run the application. The card is formatted with FAT32 and seems to work fine as a file system on a PC.

    (…)

    Reply
  19. Regarding my issue re initialising the SD card, I have now resolved it.

    It needed to be connected to 5v pin to work not 3.3v

    David

    Reply
    • Hi David.
      I’m glad you’ve solved your issue.
      Some SD card modules need 5V to operate instead of 3.3V. I’ll add a note about that in the tutorial.
      Regards,
      Sara

      Reply
  20. Hi Sara,

    I was trying to create a unique filename to log to, so I was creating a string rather than data.txt. However this does not seem to work with the append and write commands. Is there a way to make this more general with filenames?

    David

    Reply
  21. David,
    The filename appears in 3 places in the code. Did you change all 3 to the new name?
    Does your new name include the “/” as the 1st character?
    Dave

    Reply
  22. Hi, thanks for your “amazing” site.
    I have a question for expansion of that code.
    Can we use an RTC module (like DS3231), in order to get the time for data loggin in case that the internet connection lost (so no NTP info available)?
    Can ESP32 handle the SD module + RTC DS3231 + DS18B20 together? What is the PIN connection and High/Low set?

    BR

    Reply
  23. Hi, I’ve been having a great time reading through the your projects and working through the ESP32 course.

    I recently purchased some card modules on Amazon UK and they are yet to arrive but I have seen that a number of people have had voltage problems so I investigated. There are some great photographs of the PCBs on Amazon UK so it wasn’t difficult.

    It seems that many of the modules have 5V input and the 5V in all cases seems to go to a 3V3 regulator but very few modules have a 3V3 input pin. This is a real nuisance because the modules all seem to run on 3V3 but most don’t have a 3V3 input pin just a 5V pin. This means that the modules with no way to bypass the regulator are likely to misbehave if fed with 3V3.

    The work around is to solder a fine wire to the output leg of the regulator but a steady hand will be necessary.

    This is important to me because I am working on a project that will eventually be powered directly off a LiFePo4 battery that runs at around 3.2V so avoiding the need for a regulator.

    I will do some research into card modules with a 3V3 input pin – this will save a lot of headaches!

    Reply
    • Hi Richard.
      Thanks for sharing that.
      We never had issues with the microSD card modules. However, many of our readers have reported issues that may be precisely because of that.
      Thanks for sharing and let us know the results of your research.
      Regards,
      Sara

      Reply
  24. Hi
    Great tutorial.

    I am caught between the choice of saving data on internal memory (4MB) of ESP32 module and saving it on SD card. Space on ESP32 module is not a problem as I will log data for only 24 hours every 5 minutes, but I am afraid of crossing the limit of 100,000 for write/erase cycles in (100000)/(24*60/5)= 347.22 days.
    Considering the fact that I will use wear levelling library and FATFS library to store files, how realistic is my fear? Is it better to use SD card for data logging?

    Reply
    • Dear Zeni, I have use SD for logging the last 2 years (several controlers). I have install up to 80 controlers with 4 temprature sensors each, and data writing every 5 mins (4 measurments with Controler ID and datetime). Never had a problem (except once with a problematic SD card).

      Reply
  25. Hello, Sara Santos, how are you?
    We have spoken to each other for a while and I am grateful. Return with another problem.
    I’m trying to make an SD card work and I can’t, I’ve done everything. I used the Code you put here at HP but I get this information in the arduin IDE “A fatal error occurred: Timed out waiting for content packet”
    and this is on the serial monitor ”

    rst: 0x10 (RTCWDT_RTC_RESET), boot: 0x33 (SPI_FAST_FLASH_BOOT)
    flash read err, 1000
    ets_main.c 371 “
    how can you help me i am grateful
    Eaves

    Reply
  26. A great article, as usual. The article contributes great tips that I can extract for use in my projects.

    I am converting an Arduino application to ESP32 that accesses files on a microSD. The application works fine on the Arduino, but all the SD commands break on the ESP32. Differences range from simple [SD.open(“data.txt”) has to be tweaked to SD.open(“/data.txt”)] to whole methods that either don’t exist, are spelled or operate differently, or are completely reimagined [card.type() changes to SD.cardType()]. The examples in this article got me started with the conversion, but I still need robust documentation such as that found at https://www.arduino.cc/en/reference/SD for the Arduino.

    Does such documentation exist for ESP32?

    Reply
    • Hi Ron,
      I just spent a half hour looking for a reference. Unfortunately, the only thing I found was that the same link you cited above was referenced in the ESP32 SD library > library.properties as “the” reference! That was NOT a great find!

      It seems like you will need to look for patterns and adjust your code to reflect the patterns you recognize, then try, try again!

      Soon I expect to do something with the SD on ESP32, so your comment got me interested. If you decide to document your findings, I would love to know!

      Sorry not much help,
      Dave K.

      Reply
      • Dave,
        I appreciate your searching for references. I’m beginning to wonder if transitioning my project to ESP32 will be a folly if there is little documentation. I also cannot find references things such as whether there are pullup resistors available on GPIOs, the length of serial buffers, etc. that a developer surely needs to know.

        Reply
        • There are pullups on the GPIOs except the ‘input only’ pins. The serial buffer size would usually be set in software. Have you been to the ESP32 IDF and read the docs @ expressif?

          Reply
          • Thanks Dave,

            Yes, I have been to the site. It dives very deep very quickly – for hardware, software, and development environment. I think you saw a clearer answer than I was able to see when I searched the documents for “pullup”.

            At this point I’m still proceeding to explore porting my application from Arduino to ESP32, but I’m wary because I use a robust set of Arduino features and the going has been slow for each and every one of them. I’m pretty much dependent on finding somebody who has implemented a feature that can give some clues what changed between Arduino and ESP32.

          • Ron,
            AFAIK, there is no direct comparison. I think that is mainly because they simply don’t compare. The ESP32 is a much more powerful Soc then an Atmel ATMEGA. The Arduino IDE was written for the ATMEGA, and has been expanded to include other chips and boards.

            Rui and Sara seem to have the best information here on the RNT sites, if you are not ready to “go very deep, very fast”. The pinouts show some pins are input only…they do not have pullups or pulldowns, all the others do. What module you have determines what exact pins are broken out from the chip. For example, I have some Heltec modules that show GPIOs 33-39 are input only, the pinout from here https://randomnerdtutorials.com/esp32-pinout-reference-gpios/ show only 4 pins as input only. So it really depends on the the module and chip you are using. Those Heltec modules have quite a few differences for several reasons, but that does not mean they can’t be used for RNT projects. I got the for their on board OLEDs, and like the results.

            Also, I have had to look into the hardware abstraction files to find some of my answers. Heltec provided a version of their hardware layer that plugs into the Arduino IDE, just like the generic esp32 files do. The differences are slight, but it provides for dedicated pins and shortcut commands to set up the board. If you have dedicated modules that have their own code, going to look at the files can be helpful, though often tough to decipher what you need!

  27. can I replace sensors with thermocouple?cz I need more good sensitively result,or maybe u have any idea what should I do ? I need more accurate result thx 🙂 rgds from indonesia

    Reply
    • Hi.
      Yes, you can use a thermocouple.
      At the moment, we don’t have any tutorials about thermocouples.
      However, once you’re done with that, it is fairly easy to save the readings to the SD card using our tutorial.
      Regards,
      Sara

      Reply
  28. With help from Sara and Dave K. I have successfully used most of the ideas and code from this project to write temperature and pressure data from a BMP280 to the onboard SD of a ESP32_CAM.
    It wasn’t easy for me as it was my first Arduino project, and I fell into many traps along the way.
    I also had the SD card mount failure, but I assumed it was a code error by me so I completely rewrote the code and then it worked first go!!
    My biggest problem was finding a BMP280 library that worked with the ESP32_Cam. Sara suggested the SparkFunBME280 library, which eventually worked, so long as I didn’t call SoftwareWire library, which I thought I needed to map other pins for I2C.
    I ended up using GPIO16 for I2C SDA and Pin 3 (UoR) for I2C SCL. Remember GPIO 0 is needed when flashing the program as is UoR and UoT, but you can disconnect UoR after flashing and connect I2C SCL to it, and still use the serial monitor for debugging, which is handy.

    Reply
  29. I have now been running this sketch, logging time, date, temp, and pressure on a SD card every 1 minute, for a few days and I thought I had better report what has been happening.
    Firstly some temperature and pressure readings are way out, incorrect about 1 reading in 60 for temperature and 1 in 30 for pressure. I am not sure why the BMP280 readings are getting out of sync occasionally.
    Secondly I have been getting random “Guru meditation errors”, which result in the program resetting itself. Thereafter it runs OK for about 30 to 70 odd one minute readings before another GME occurs.
    Finally, I have been getting three or four “rst:0x7 (TG0WDT_SYS_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)-> flash read err, 1000” occurences which of course stop the whole program.
    I have read up widely on this last problem and it appears the on-board flash is not getting enough time to wake -up after the deep sleep. As for the random GME’s i do not know why they occur. Any help on these problems would be appreciated.

    Reply
  30. I have just received some new BMP280 sensors so I thought I would try out the ESP32 again with a changed sensor. It ran for 371 minutes, logging once a minute before the dreaded flash error stopped logging. In the 371 minutes I got 23 Guru meditation errors, meaning it reset itself. The temperature readings were mostly OK but I had 8 randomly interspersed -111.23 degrees C and 7 random 102.57 degrees C readings, as well as some other odd values in amongst the normal temp readings. I suspect a faulty ESP32, but I am not really sure. The whole shebang was run on a high capacity LiPo battery, regulated down to appropriate voltages.
    Any other info or other peoples observations would be helpful.

    Reply
    • Hi Locke,
      There are a couple of suggestions I would make:
      – If not using WiFi for the project be sure it is turned off. As the ESP has to boot on each wake up, it will drain a lot of power to try to connect, and might even create timing errors on the I2C software bus.
      – Even though there is plenty of power available, power leads have inductance, put a 1-10uF cap very near your dev board, (or on it if you can solder!). Your power leads and all paths should be 22ga or greater if a longer distance. (Like a meter (yard) or more.) Local cap can be bigger too.
      – What are you regulating the voltage with? How far away is the regulator? Is it fast enough to go from sleep power to full power? Switching regulators can cause problems if not filtered properly…another reason for the cap on board.

      That’s about all I have. Power spikes are pretty often a problem with the ESPs.

      Hope it helps,
      Dave K.

      Reply
      • Dave K,

        I’m having symptoms similar to Lockie. No rebooting, but unexplainable issues.

        I am porting an Arduino Mega/ESP8266 combo card application to ESP32 – I KNOW the application works. Both have microSD, BME280, HC-12 transceiver, WiFi, DFPlayer mini, shift registers and RTC. The Arduino/ESP8266 is powered by a 5V switched power supply with no filtering, and is rock solid reliable. Components that ONLY worked at 3.3V are regulated with AMS1117-3.3 with 800uF on the 3.3V side. With ESP32 everything is on the 3.3V regulated side. Initial problem was:
        * Sockets in my breadboard became “sprung” because they contained “fat” ESP32, BME280 and other pins alongside “skinny” resistor and capacitor pins. Even worse, jumper wires with square pins can be inserted diagonally, spreading the sockets wider, leading to unreliable connections. I switched to a new breadboard and inserted components at opposite ends of the 5-hole connection strip
        * I’m not sure jumper wires are 22ga…

        I have encountered numerous problems ONLY with the ESP32, with no viable cause:
        * HC-12 transceiver range is only ~10 feet rather than 1+ blocks. NO difference at all between the two implementations except the microcontroller.
        * DFPlayer mini initially occasionally skipped a song, now plays for 1-2 seconds then quits. NO known reason.
        * Shift register works for awhile then rests for awhile, then works again…

        I’m about to give up with the port because my deadline is approaching. Last thing I’m trying is ferrite beads on the power supply lines, and seeing if a ‘scope will show dropouts or spikes. If I were confident enough that my problem was “inductance” I would go ahead and commit to a PCB design that could help immensely. Do you have a recommended circuit for “filtered properly”?

        Best Regards,
        Ron Brinkman

        Reply
        • Hi Ron,
          Have you tried a second ESP32?
          As I said in the post above to Dave, that is my last option. I’ll be going back to ESP8266 instead.

          Hope it works out, keep us posted as this sort of communication is valuable.

          Reply
        • Hi Ron,
          I don’t have a recommended filter, other than sufficient capacity as close to the ESP as practical. I have no way of knowing what Locke’s actual problem is, and I was recommending the simplest issue to resolve first. When ever there is high impedance inputs and rf, such as WiFi, everything must be routed right, grounded right, and (in my experience) breadboards are a series of antennas! I once built a comparator circuit with an LM393 that triggered the second op amp in the package every time the first fired on a breadboard. The Inputs to the offending amp were tied together and grounded, and I had to remove the output pin from the breadboard to prevent triggering the target amp. Why? As you said, poor connections I’m sure.
          The 22ga was to assure there would be no appreciable drop, and good breadboard connections. Since the ESP can pull 280mA for short periods not counting other loads.
          I too think there may be some issues with the ESP32s. But you may be able to work around them by careful coding and solid design.
          Dave

          Reply
      • That is all very good advice Dave. I had already turned off wifi to see if that made a difference, but alas no it didn’t. I have 100 uF cap close to the ESP32 and it is on a breadboard so distance is not an issue. I have been waiting two months for some extra ESP32Cam boards in case my one is touchy, but with Covid19 lockdowns the postal services are shocking!
        The regulators are stock standard 5V and 3v3 regulators. Voltages look OK on the multimeter. I think I shall bring in my oscilloscope to check on the power surge on wake-up. I’ll report back later.

        Reply
        • Cheers to the scope!
          I am wondering if there are timing issues due to the need to service one core over the other or some such nonsense. WiFi is so demanding, that I thought turning it off would certainly help, and I am surprised it did not.
          All of my ESP32 development to date has been ESP-NOW sending temp sensor data from DS18B20s and so far it works great.
          Good luck!

          Reply
          • Hi Dave,
            The reason I chose the BMP280 was that in a comparison on the web somewhere it outperformed most of the other sensors. I wanted a temp sensor with high resolution (0.01 degree) for a certain application, actual temp accuracy wasnt an issue. I note that the DS18B20 you are using has 12 bit resolution (0.0002 degree) and 0.5 degree accuracy, so it may be even better. I need a very low noise sensor as my background temperature noise will be less than 1/1000 of a degree. I aim to log once a minute for three years.
            (CRO checks not done yet.)

        • Hi,
          A further update. I received two more ESP32_Cams after 2 months of waiting. I popped one in on the breadboard that was set up and loaded my test program that reads temp and barometric pressure and writes to Sd every minute. It has been running flawlessly now for 10 hours. No GME’s or flash read errors! So I guess I had an ESP32 that was out of spec. Pity it took me weeks of hairpulling to find out. Advice to newbies – these boards are so inexpensive that you should buy 3 or 4 in case you brick one or you get a faulty one. It would have saved me countless hours if I simply pooed another board in and found it working OK.

          Reply
  31. Hi, I would have SD card and a display like ST7799.
    All sketches that i saw use quite the same SPI pins.
    It is possible to change SPI pins functon?

    Thanks
    Renzo Giurini

    Reply
    • Hi,
      Unlike the I2C, the SPI bus uses separate lines for sending and receiving data, and it employs an additonal line for selecting which slave device you are talking to. This adds additonal wires, but also eliminates needing different slave device addressses. So what this means is instead of specifying the address of the slave device, we simply address that slave device by turning on its CS pin. It’s a lot more simplistic.

      Arduino has a built-in SPI library and hardware to communicate with SPI devices.
      Check out https://github.com/espressif/arduino-esp32/issues/1904 if you need to interface more than 8 devices.

      Reply
  32. Hi Sara
    Which versions of FS.h, SD.h and SPI.h do we need and where to download them from? Do we use the ones in the Arduino library or do we need special ESP32 ones. My compiler is very confused with what I have atm. Thanks.

    Reply
      • Greetings, Sara! I love what you and Rui do! These tutorials are exceptional and I have many projects I have successfully made because of your tutorials and I so far have purchased two of your books.
        However, I am having trouble with this example in that; although you mention above that there is no need to install the FS.h library as it installs by default, when I try to compile the example, I get an error, I get the following message:
        sketch_oct29a:7:10: error: FS.h: No such file or directory
        I have actually tried several other examples on the internet (the application I am working towards is to actually be able to read a microSD; not write to one) and several other examples use FS.h as well, with the same error. I searched my libraries folder with no luck (o: I struggle with Github, but found some fs.h documentation there, but there’s no download button on the page like on many Github pages.
        Any suggestions? Did I miss something somewhere? (o:

        Reply
  33. Oh, and I do have an SD library folder, but no SPI folder either, which I suspect I will need as well. Your help is greatly appreciated.

    Reply
  34. Well. My bad. I downloaded the ESP32 core library and found fs.h and spi.h, loaded them into my Arduino UI and still no luck.
    Then I realized, after reading the compiler errors that I had inadvertently switched to an Arduino Nano. Switching back to ESP32 I got the initializing the card error. Switching the power supply for the SD card to 5v, it worked!
    Sorry to have bothered you (o: I’m having other issues reading files (I can recognize the files with the generic SD test program, which can create, write and read its own files) but the test program cannot read the contents of the files. I’ll keep working! Cheers!

    Reply
  35. Hi Sara,
    I am trying to use an SD card reader with TTGO T-display. I am using the standard library with a set of alternate SPI pin definitions as the display uses the hardware pins. Unfortunately I get a mount error, meaning that my pin definitions are not being processed. I notice that this seems to be a common issue on many of the ESP32 forums, with the only solution so far being to use some alternate library (Mysd.h). You helped me with my problem using alternate I2C pins with the BMP280 sensor, that necessitated using the Sparkfun library instead of the Adafruit library. Maybe a similar problem exists with SPI and certain ESP32 devices? What experience have you or Rui had with this issue?

    Reply
  36. Hi,very intresting, but when i initializing SD(sd.begin(cs_pin)), i get error: [E][sd_diskio.cpp:739] sdcard_mount(): f_mount failed 0x(3). Maybe you know what is it?

    Reply
  37. Hi Sara,

    Sketch would not Compile ‘getFormattedDate’ No such class in NTPClient.

    Went to NTPClient examples & found ‘getFormattedTime’ & used this instead. Sketch now complies.

    Keep up the good work.

    Alan

    Reply
      • Thank you this great tutorial and others. I was able to make a battery powered temperature logger with two ds18b20 waterproof probes, measuring temperatures within a climate controlled container. I did come across an issue when my Arduino IDE detected a newer version of the NTPClient. I updated, and the code no longer compiled. I was able to revert to the Taranais version, but now I keep having to “ignore” the new version update. Do you know how tell Arduino IDE to ignore the newest version on NTPClient?

        Reply
  38. Just wondering if you are using the 36 pin or the 30 pin ESP32 module, the link shows it is 30 pin but the example shows using the 36pin ESP32 module.

    Reply
  39. Hi
    I’m using some software to graph the output from this but the software expects date and time to be combined eg YYYY:MM:DAY Time.
    This project splits the date and time into two comma seperated fields.
    Can they be combined?

    Thank you

    Reply
  40. Perfect, but I spend 1 day by ERROR: “Card Mount Failed”, to get working on ESP32, please fix:
    //#include <SPI.h>
    #include “SPI.h”

    Reply
  41. I need help to interface a microSD card module to ESP32 on pins 12(), 13(), 14() and 15() using arduino platform.
    I have tried some standard solutions available on NET but neither, has worked.

    Reply
  42. Hi! I was working on the tutorial, but for some strange reason when wanting to compile it returns the following error:

    variable or field ‘writeFile’ declared void
    void writeFile(fs::FS &fs, const char * path, const char * message){

    Do you have any idea what it might be?

    Reply
    • something to expand, is that I base myself on what you did and on the example that the library brings by default 🙁
      so the method is the following

      void writeFile (fs :: FS & fs, const char * path, const char * message) {
      Serial.printf (“Writing file:% s \ n”, path);

      File file = fs.open (path, FILE_WRITE);
      if (! file) {
      Serial.println ("Failed to open file for writing");
      return;
      }
      if (file.print (message)) {
      Serial.println ("File written");
      } else {
      Serial.println ("Write failed");
      }
      file.close ();

      }

      Reply
  43. @Sarah & Rui,
    THX for the excellent tutorials.
    I am fairly new to the ESP32 and subscribed to one of your tutorials. However my question is about this particular one.
    I do not understand how I get multiple ds18b20 sensors to write to the SD card.
    So I understand and got to work the above explanations but combining the two is beyond me.
    Thank you for pointing me in the right direction.

    Jeroen

    Reply
  44. Hello,
    first, thank you for your great tutorials!
    I wanted to ask, what would need to be changed in the code from SD card datalogging tutorial, to be able to save multiple files instead of appending all in one? For example, every time I reset esp32, it would created a new file?
    thank you,

    Maksym

    Reply
    • Hi.
      In our example, we check if the file already exists so it doesn’t overwrite the previous file.
      If you want to have different files every time the ESP resets, you need to be able to give a different name to each file.
      There are different ways to do that. I suggest adding a timestamp to the name of the file, this way, it will always be unique at the time of creation.
      I hope this helps.
      Regards,
      Sara

      Reply
  45. Good afternoon
    How can I remove the Deep Sleep function from ESp32. I’ve tried but it always gives me a compile error
    Thanks

    Jesús Cuesta

    Reply
  46. Thanks for the project. I plan on using this to log data from a solar cell, watching to see what sun location and shading does to output. I was watching a youtube video about solar cars with built-in solar panels, and wondered how much power I would get

    Reply
  47. I have a monitoring device that creates a new file every day.
    I want to have only the 10 latest files in data. any example I can follow?

    Reply
  48. Hi out there, hello Sara (and, of course, Rui)

    I built a chain of 10 sensors of DS18B20 NOT following your tutorial, I found it just yet.
    I am astonished to read throughout the comments, that mounting the SD card is a serious issue.

    Much more because I also ran into the same issue myself.
    (I refrain from describing all the things I tried to solve this)
    First of all i used a micro SD card reader, which refused to work.
    I then connected an SD card reader (without the micro, forcing me
    to add an SD to micro SD adapter)

    In the end:
    Former has a VDD input and is supplied with a 3.3V regulator
    Latter has both a VDD AND a 3.3V input AND provides a 3.3V regulator.
    (I tried to find out how THAT works but in the end I gave it up)
    (Chinese products lack thorough documentation like for instance a
    schematic or even a good, written description)

    Former refused to work till the end (mounting the SD card fails every time), the SD Card
    reader worked and works fine from the start if one does NOT attempt to use 3.3V.

    When I find time, I will dug deeper into the issue and come back with some information.
    Most interestingly this is a major issue, which seems to happen to many users.
    Somewhere along the comments someone stated this “have to be the code”, I assume its the interface of the SD readers themselves, probably timing (Any way on of my trials was to reduce the clock as far as possible, to no avail), another source could be the library, but I think it is the hardware interface between the ESP32 and the readers

    In my case the problem seems to have been the reader, which I switched, NOT the ESP32.
    (WEMOS Mini D1 ESP32)
    If this would be a real fred I could add pictures of the working reader (Can we arrange something if this is of value?)

    NOW I get to my own problem:
    The readings I receive from all the 10 sensors are 10° OFF of the expected (and proven) temperature of 60′C (50°C like)
    The application measures and stores the temperature of my 3D printer bed (I want to gain a temperature profile)
    (Proven using an oven thermometer which works known good)

    The last thing I tried is to connect the sensors to VDD (5V) and pull the 1Wire pin up to 3.3V to communicate safely with the ESP32, assuming the sensors NOT running at full power might infringe their ability to measure higher temperatures.

    Working at room temp was proven by comparing measurements against a room thermometer, arranging the sensors in a cooling box for thermal decoupling. But at 60°C the measurements deviate heavily and when I lower the temp to 35°C (As an arbitrary reference) they are still far off with respect to the error characteristics given in the data sheet to be 0.5° up to +85°C.

    The sensors are connected to the printer bed using temperature pads, so every sensor is “glued” to the surface and all sensors show about 50°C within 0.5°.
    Totally weird, probably I should contact the manufacturer?

    Any idea from the hive?

    Cheers

    Reply
    • Hi.
      It is normal to have some offset when it comes to those sensors +/- 2 or 3 degrees celsius according to my experience.
      If the offset is bigger than that, there might be something wrong with your circuit, you may need to calibrate the sensor, or the sensor is of dubious quality 😐
      I hope this helps.
      Regards,
      Sara

      Reply
  49. hello everything works fine for me i have the right libraries and i connect the micro sd reader to 5v because that is the only way it works for me and the esp32 is at laptop voltage. the first reading gives me the correct one and I send it to deep sleep on esp32 but from there it no longer wakes up to give me the next reading and goes back to sleep):

    I reduce the seconds and nothing, I copy the exact code and nothing, I even leave the esp32 running on direct current, but it only registers the first boot the same as connected to the laptop.

    I need help!!!

    Reply
  50. Hey Rui, comment vas-tu?!
    Merci d’avoir partager vos projets, ils sont très clairs et pédagogiques.
    Cependant j’ai un petit problème au niveau de la boucle, mon ESP y reste coincée:
    void getTimeStamp() {
    while(!timeClient.update()) {
    timeClient.forceUpdate();
    }
    c’est à dire que la date n’est pas mis à jour.
    Sachant que j’ai utilisé la bibliothèque que vous avez donné. Merci de m’apporter votre aide. Et bonne continuation.

    Reply
  51. Hi Sara and Rui,
    I am new at coding and using Microcontrollers. Is there any chance that you tell me how to add 3 more DS18B20 sensors? I would like to analyze several temperaturs of my heating and try to optimize the parameters of my heater in the cellar.

    Reply
  52. Hey,
    How small can the be the parameter “time_to_sleep”?.
    We have a project in which we read data from the sensors 5 times in a seconds. Will this work?

    Reply
  53. Hi Sara,
    I’m here again to ask for help.
    Following your tutorials I was able to realize a system that, based on an ESP32, collected at fixed intervals data from BME280 and SHT3X, saved these data on a SD card with a time stamp ( I’m using a DS3231 RTC clock since in the position where the system works there is no reliable wifi) and displayed it on an OLED screen. When the data were not recorded the ESP32 is in deepsleep.
    In order to save more power I tried to use an E-paper display and I was able to duplicate the data on the screen at fixed intervals BUT I was not able to save them on the SD card. Sinche the wiring for the E-paper display ( a 3c 2.13″ WeActStudio display) is four lines SPI (MOSI to 23, SCK to 18, CS to 5, D/C to .0, RST to 2 and BUSY to 15) I was forced for the SD card to use a different SPI configuration and, following your tutorial on SPI, I defined for SD card SCK 25, MISO 32, MOSI 26, CS 33) with the command
    SPIClass spi = SPIClass(VSPI);
    and
    in the setup
    spi.begin(SCK, MISO, MOSI, CS);
    I got no error when compiling and also the uploading went without any problems but I keep on getting the message
    Failed to open file for writing
    and
    Failed to open file for appending
    and obviously no data are saved on the SD card.
    I checked the wiring and the VSPI for SD card with one of your codes suggested in a tutorial and it worked but when I use also the SPI for display I get the problem.
    Could you help me ? Thanks in advance
    Here is my code
    #include <SPI.h> //for the SD card
    #include <Wire.h>

    #include “FS.h”
    #include <SD.h> // for the SD card

    #define SCK 25
    #define MISO 32
    #define MOSI 26
    #define CS 33

    SPIClass spi = SPIClass(VSPI);

    #include <RTClib.h> // for the RTC
    RTC_DS3231 rtc;

    //libraries for e-paper display

    #define ENABLE_GxEPD2_GFX 0

    #include <GxEPD2_BW.h>
    #include <GxEPD2_3C.h>
    #include <Fonts/FreeMonoBold9pt7b.h>

    // ESP32 SS=5,SCL(SCK)=18,SDA(MOSI)=23,BUSY=15,RST=2,DC=0

    // 2.13” EPD Module
    GxEPD2_3C<GxEPD2_213_Z98c, GxEPD2_213_Z98c::HEIGHT> display(GxEPD2_213_Z98c(/CS=5/ 5, /DC=/ 0, /RST=/ 2, /BUSY=/15)); // GDEY0213Z98 122×250, SSD1680

    #include <Adafruit_Sensor.h>
    #include <Adafruit_BME280.h>

    #define SEALEVELPRESSURE_HPA (1013.25)
    Adafruit_BME280 bme; // I2C

    #include <SHT3x.h>
    SHT3x Sensor;

    // variables to store data from sensors ( float type because they are value with a decimal part)

    float temp;
    float hum;
    float TEMP;
    float HUM;

    String timeStamp;

    // variables to define sleep time; the first multiplies the value to get seconds from microseconds; the second says the sleep time in seconds (1200 = 30 minutes)
    uint64_t uS_TO_S_FACTOR = 1000000;
    uint64_t TIME_TO_SLEEP = 180; //sleep for 10 minutes

    String dataMessage;

    // setting a counter for data readings; it will increase every time data from sensors are collected
    RTC_DATA_ATTR int sensor_data = 0;

    // initializing string data to save data collected from sensors

    String Data;

    #define sensor_data(temp,hum,TEMP,HUM);

    void gettimeStamp() {
    DateTime now = rtc.now();

    char timeStamp[9];
    sprintf(timeStamp, “%02i:%02i:%02i”, now.hour(), now.minute(), now.second());

    Serial.println(timeStamp);
    }

    void Read_TempHum()
    {
    Serial.print(“Temp_BME280 = “);
    Serial.print(temp);
    Serial.println(” C”);
    Serial.print(“Hum_BME280 = “);
    Serial.print(hum);
    Serial.println(” %”);
    Serial.print(“Temp_SHT3x = “);
    Serial.print(TEMP);
    Serial.println(” C”);
    Serial.print(“Hum_SHT3X = “);
    Serial.print(HUM);
    Serial.println(” %”);
    }

    void displayReadings() {
    DateTime now = rtc.now();

    char timeStamp[9];
    sprintf(timeStamp, “%02i:%02i:%02i”, now.hour(), now.minute(), now.second());
    display.init(115200,true,50,false);
    display.setRotation(1);
    display.setFont(&FreeMonoBold9pt7b);
    display.setTextColor(GxEPD_BLACK);
    display.setFullWindow();
    display.firstPage();
    do
    {
    display.fillScreen(GxEPD_WHITE);
    display.setCursor(0,10);
    display.print(“temp_BME= “);
    display.print(temp);
    display.println(” C”);
    display.setCursor(0,30);
    display.print(“temp_SHT= “);
    display.print(TEMP);
    display.println(” C”);
    display.setCursor(0,50);
    display.print(“hum_BME= “);
    display.print(hum);
    display.println(” %”);
    display.setCursor(0,70);
    display.print(“hum_SHT= “);
    display.print(HUM);
    display.println(” %”);
    display.setCursor(0,90);
    display.setTextColor(GxEPD_RED);
    display.print(“sleeping for 15 min”);
    display.setCursor(0,110);
    display.print(“# “);
    display.print(sensor_data);
    display.print(” “);
    display.print(timeStamp);
    }
    while(display.nextPage());
    delay(100);
    display.hibernate();
    }

    void setup() {
    //initializing Serial monitor
    Serial.begin(115200);
    while(!Serial);
    delay(100);

    // Initialize SD card

    spi.begin(SCK, MISO, MOSI, CS);

    if (!SD.begin(CS,spi,80000000)) {
    Serial.println(“Card Mount Failed”);
    return;
    }
    uint8_t cardType = SD.cardType();

    if(cardType == CARD_NONE){
    Serial.println(“No SD card attached”);
    return;
    }
    display.init(115200,true,50,false);

    delay(3000);

    bme.begin(0x76);
    temp = bme.readTemperature();
    hum= bme.readHumidity();

    //Initialize DS3231
    Serial.println(“Initialize DS3231”);

    // checking the BME280 connections and initializing the sensor

    if (!bme.begin(0x76)) {
    Serial.println(“Could not find a valid BME280 sensor, check wiring!”);
    while (1);
    }

    //initializing the SHT31 sensor

    Sensor.Begin();
    Sensor.UpdateData();
    TEMP = Sensor.GetTemperature();
    HUM = Sensor.GetRelHumidity();

    // setup for the RTC
    while(!Serial);
    delay(1000);
    if(! rtc.begin()) {
    Serial.println(“Couldn’t find RTC”);
    while (1);
    }
    else {
    // following line sets the RTC to the date & time this sketch was compiled
    rtc.adjust(DateTime(F(DATE), F(TIME)));
    }

    //try to open the data.txt file on the microSD card where the data collected from the sensors will be stored together with time and date
    // If the data.txt file doesn’t exist
    // Create a file on the SD card and write the data labels
    File file = SD.open(“/data.txt”);
    if(!file) {
    Serial.println(“File does not exist”);
    Serial.println(“Creating file…”);
    writeFile(SD, “/data.txt”, “Reading Number, Date, Hour, temp, hum, TEMP, HUM \r\n”);
    }
    else {
    Serial.println(“File exists”);
    }
    file.close();

    Read_TempHum();
    logSDCard();
    displayReadings();
    //ledHumid();
    delay(4000);
    display.hibernate();

    // increasing the counter for the next data readings

    sensor_data++;

    Serial.println("Sensor data logged successfully! Going to sleep");

    // ESP32 going to sleep for the amount of time you decided
    esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
    delay(4000);

    esp_deep_sleep_start();
    }

    void logSDCard() {
    DateTime now = rtc.now();
    char timeStamp[9];
    sprintf(timeStamp, “%02i:%02i:%02i”, now.hour(), now.minute(), now.second());

    dataMessage = String(sensor_data) + “,” + String(timeStamp) + “,” +
    String(temp) + “,” + String(hum)+ “,” + String(TEMP)+”,”+ String(HUM) +”\r\n”;
    Serial.print(“Save data: “);
    Serial.println(dataMessage);
    appendFile(SD, “/data.txt”, dataMessage.c_str());
    }

    // Write to the SD card (DON’T MODIFY THIS FUNCTION)
    void writeFile(fs::FS &fs, const char * path, const char * message) {
    Serial.printf(“Writing file: %s\n”, path);
    File file = fs.open(path, FILE_WRITE);
    if(!file) {
    Serial.println(“Failed to open file for writing”);
    return;
    }
    if(file.print(message)) {
    Serial.println(“File written”);
    } else {
    Serial.println(“Write failed”);
    }
    file.close();
    }
    // Append data to the SD card (DON’T MODIFY THIS FUNCTION)
    void appendFile(fs::FS &fs, const char * path, const char * message) {
    Serial.printf(“Appending to file: %s\n”, path);
    File file = fs.open(path, FILE_APPEND);
    if(!file) {
    Serial.println(“Failed to open file for appending”);
    return;
    }
    if(file.print(message)) {
    Serial.println(“Message appended”);
    } else {
    Serial.println(“Append failed”);
    }
    file.close();
    }

    void loop() {
    }

    Reply
  54. Hi Sara
    I’ve tried to contact also the guru of E-paper displays ZinggJm but I’m still with my problem unsolved.
    Could you help me please?

    Reply
  55. Hello and thank you for this article. I have a question about the opening and closing of the file on the SD card. If we have code in the loop to read sensor data once per second, and log this to an SD card, would we be opening and closing the file every second as well? How could this code be modified to include a sync function rather than file.close? Or am I missing something important? I am trying to make an ultra-low power consuming sensor-datalogger setup, and would like to try and reduce the amount of power used by my SD module by maybe keeping the file open during the whole wake cycle and only closing once it enters deep sleep. Have I understood this all correctly?

    Reply
  56. Hello and thank you for this nice tutorial. I would like to ask a question.
    I use SD card for data logging with ESP32 DevKit V1. I need to read the contents of a file on the SD card in reverse order, first the last written and backwards. Not just the last 10 or 30 records, but as far back as I need at any given time. Is there any way to do it? Thanks in advance.

    Reply

Leave a Reply to Fernando Nino Cancel reply

Download Our Free eBooks and Resources

Get instant access to our FREE eBooks, Resources, and Exclusive Electronics Projects by entering your email address below.