Random Nerd Tutorials
Shares

ESP32 Data Logging Temperature to MicroSD Card

Shares

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.

cloud-download

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 Module ESP32
3V3 3V3
CS GPIO 5
MOSI GPIO 23
CLK GPIO 18
MISO GPIO 19
GND GND

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 DallasTemperature folder 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 NTPClient folder 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.

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 dataMessage variable 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).

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 ESP32 with Arduino IDE

This our complete guide to program the ESP32 with Arduino IDE, including projects, tips, and tricks! The registrations are open, so SIGN UP NOW »

Leave a Comment:

Add Your Reply

⏰ Registrations are open ⏰
Sign up for "Learn ESP32 with Arduino IDE" Course