In this guide, we’ll build an ESP32 datalogger that also hosts a web server so that you can access and download the data remotely. The ESP32 will log data to a file hosted on a microSD card. You can access the web server with your computer or smartphone and download the file with the data remotely without the need to remove the microSD card from the ESP32.
Table of Contents:
Project Overview
Here’s a quick overview of the features of this project.
- The ESP32 will log data and the corresponding timestamp to a file on a microSD card.
- We’ll log data from a BME280 sensor, but you can use any other sensor or sensors.
- We’ll save the timestamp in epoch time. Then, when processing the data, you can convert it to your local time.
- The ESP32 will also host a web server that you can access on your computer or smartphone as long as they are on the same network.
- The web server allows you to visualize the data saved on the file, download the data file to your computer, or delete the file from the microSD card.
- The HTML file to build the ESP32 web server will also be hosted on the microSD card.
In this example, we’ll get the time from the internet (NTP server), so the ESP32 needs to be connected to a router. If the board doesn’t have access to the internet, you can set it as an access point, and get the time from an RTC module (for example DS1307 or DS3231).
Prerequisites
Before proceeding, make sure you check the follow the next prerequisites.
Arduino IDE
We’ll program the ESP32 using Arduino IDE. So make sure you have the ESP32 boards installed. You can use Arduino IDE 2 or the legacy version.
Libraries
You also need to install the following libraries.
- Adafruit BME280 Library (Arduino Library Manager)
- Adafruit Unified Sensor Driver (it will install automatically with the Adafruit BME280, otherwise, you need to install it manually)
- ESPAsyncWebServer (.zip folder)
- AsyncTCP (.zip folder)
You can install the first two libraries using the Arduino Library Manager. Go to Sketch > Include Library > Manage Libraries and search for the library name.
The ESPAsyncWebServer and AsynTCP libraries aren’t available to install through the Arduino Library Manager. You need to download the library .zip file and then, in your Arduino IDE, go to Sketch > Include Library > Add .zip Library and select the libraries you’ve just downloaded.
Formatting the MicroSD Card
Before proceeding with the tutorial, make sure you format your microSD card as FAT32. Follow the next instructions to format your microSD card or use a software tool like SD Card Formatter (compatible with Windows and Mac OS).
1. Insert the microSD card into your computer. Go to My Computer and right-click on the SD card. Select Format as shown in the figure below.
2. A new window pops up. Select FAT32, press Start to initialize the formatting process, and follow the onscreen instructions.
Parts Required
To follow this tutorial, you need the following parts:
- ESP32 development board (read: Best ESP32 development boards)
- BME280 sensor
- MicroSD Card Module
- MicroSD Card
- Jumper Wires
- Breadboard
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!
Circuit Diagram
For this example, wire the microSD card module and the BME280 sensor to the ESP32. Follow the next schematic diagram or the tables below to wire the circuit.
You can also take a look at the following tables:
BME280 | ESP32 |
VIN | 3V3 |
GND | GND |
SCL | GPIO 22 |
SDA | GPIO 21 |
microSD card module | ESP32 |
3V3 | 3.3V |
CS | GPIO 5 |
MOSI | GPIO 23 |
CLK | GPIO 18 |
MISO | GPIO 19 |
GND | GND |
Not familiar with the BME280 sensor? Read the following guide
Not familiar with using a microSD card with the ESP32? Check the following tutorials:
- ESP32: Guide for MicroSD Card Module using Arduino IDE
- ESP32 Web Server Hosting Files from MicroSD Card
- ESP32 Data Logging Temperature to MicroSD Card
HTML File
The following HTML file will build the web server page that we can interact with to manage the data on the ESP32.
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ESP32 Datalogger</title>
<style>
html {
font-family: Arial, Helvetica, sans-serif;
}
body {
background-color: #f4f4f4;
margin: 0;
padding: 0;
}
.container {
max-width: 800px;
margin: 50px auto;
text-align: center;
}
h1 {
color: #333;
}
.button {
display: inline-block;
padding: 10px 20px;
margin: 10px;
font-size: 16px;
border: none;
border-radius: 5px;
cursor: pointer;
transition-duration: 0.4s; }
.button-data {
background-color: #858585;
color: #fff;
}
.button-delete {
background-color: #780320;
color: #fff;
}
.button:hover {
background-color: #0056b3;
}
</style>
</head>
<body>
<div class="container">
<h1>ESP32 Datalogger - Manage Data</h1>
<a href="view-data"><button class="button button-data">View Data</button></a>
<a href="download"><button class="button button-data">Download Data</button></a>
<a href="delete"><button class="button button-delete">Delete Data</button></a>
</div>
</body>
</html>
The web page has three buttons:
- View Data: will show the data file contents — makes a request on the /view-data path;
- Download Data: downloads the data file to your device — makes a request on the /download path;
- Delete Data: deletes the data file from the microSD card — makes a request on the /delete path.
Copy the HTML File to the microSD card
- Create a file called index.html and copy the HTML text we’ve shown you previously.
- Copy that file to the microSD card.
- Insert the microSD card into the microSD card module that should be connected to the ESP32.
Datalogger and Web Server Code
The following code creates an ESP32 datalogger that will log BME280 sensor data and the corresponding timestamp to a file called data.txt on the microSD card. At the same time, it also hosts a web server and shows a web page (built from the HTML file you copied to the microSD card) that you can access to manage the data.
/*********
Rui Santos & Sara Santos - Random Nerd Tutorials
Complete project details at https://RandomNerdTutorials.com/esp32-datalogger-download-data-file/
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files.
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*********/
#include <Arduino.h>
#include <WiFi.h>
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include "FS.h"
#include "SD.h"
#include "SPI.h"
#include <Adafruit_BME280.h>
#include <Adafruit_Sensor.h>
#include "time.h"
#include <WiFiUdp.h>
// Replace with your network credentials
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
// NTP server to request epoch time
const char* ntpServer = "pool.ntp.org";
// Variable to save current epoch time
unsigned long epochTime;
// Variables to hold sensor readings
float temp;
float hum;
float pres;
String dataMessage;
// File name where readings will be saved
const char* dataPath = "/data.txt";
// Timer variables
unsigned long lastTime = 0;
unsigned long timerDelay = 30000;
// Create AsyncWebServer object on port 80
AsyncWebServer server(80);
// BME280 connect to ESP32 I2C (GPIO 21 = SDA, GPIO 22 = SCL)
Adafruit_BME280 bme;
// Init BME280
void initBME(){
if (!bme.begin(0x76)) {
Serial.println("Could not find a valid BME280 sensor, check wiring!");
while (1);
}
}
// Init microSD card
void initSDCard(){
if(!SD.begin()){
Serial.println("Card Mount Failed");
return;
}
uint8_t cardType = SD.cardType();
if(cardType == CARD_NONE){
Serial.println("No SD card attached");
return;
}
Serial.print("SD Card Type: ");
if(cardType == CARD_MMC){
Serial.println("MMC");
} else if(cardType == CARD_SD){
Serial.println("SDSC");
} else if(cardType == CARD_SDHC){
Serial.println("SDHC");
} else {
Serial.println("UNKNOWN");
}
uint64_t cardSize = SD.cardSize() / (1024 * 1024);
Serial.printf("SD Card Size: %lluMB\n", cardSize);
}
// Write to the SD card
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
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();
}
// Delete file
void deleteFile(fs::FS &fs, const char * path){
Serial.printf("Deleting file: %s\r\n", path);
if(fs.remove(path)){
Serial.println("- file deleted");
} else {
Serial.println("- delete failed");
}
}
// Function that gets current epoch time
unsigned long getTime() {
time_t now;
struct tm timeinfo;
if (!getLocalTime(&timeinfo)) {
//Serial.println("Failed to obtain time");
return(0);
}
time(&now);
return now;
}
// Function that initializes wi-fi
void initWiFi() {
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
Serial.print("Connecting to WiFi ..");
while (WiFi.status() != WL_CONNECTED) {
Serial.print('.');
delay(1000);
}
Serial.println(WiFi.localIP());
}
void setup() {
Serial.begin(115200);
initWiFi();
initBME();
initSDCard();
configTime(0, 0, ntpServer);
// 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 doesn't exist");
Serial.println("Creating file...");
writeFile(SD, "/data.txt", "Epoch Time, Temperature, Humidity, Pressure \r\n");
}
else {
Serial.println("File already exists");
}
file.close();
// Handle the root URL
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
request->send(SD, "/index.html", "text/html");
});
// Handle the download button
server.on("/download", HTTP_GET, [](AsyncWebServerRequest *request){
request->send(SD, "/data.txt", String(), true);
});
// Handle the View Data button
server.on("/view-data", HTTP_GET, [](AsyncWebServerRequest *request){
request->send(SD, "/data.txt", "text/plain", false);
});
// Handle the delete button
server.on("/delete", HTTP_GET, [](AsyncWebServerRequest *request){
deleteFile(SD, dataPath);
request->send(200, "text/plain", "data.txt was deleted.");
});
// Uncomment the following line if you need to serve more static files like CSS and javascript or favicon
//server.serveStatic("/", SD, "/");
server.begin();
}
void loop() {
if ((millis() - lastTime) > timerDelay) {
//Get epoch time
epochTime = getTime();
//Get sensor readings
temp = bme.readTemperature();
//temp = 1.8*bme.readTemperature() + 32;
hum = bme.readHumidity();
pres = bme.readPressure()/100.0F;
//Concatenate all info separated by commas
dataMessage = String(epochTime) + "," + String(temp) + "," + String(hum) + "," + String(pres)+ "\r\n";
Serial.print("Saving data: ");
Serial.println(dataMessage);
//Append the data to file
appendFile(SD, "/data.txt", dataMessage.c_str());
lastTime = millis();
}
}
Before uploading the code to the board, you need to insert your network credentials on the following variables.
// Replace with your network credentials
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
How the Code Works
Continue reading to learn how the code works or skip to the Demonstration section.
Including Libraries
Start by including the required libraries. We include the libraries to connect to Wi-Fi, create the web server, handle files, communicate with the microSD card, communicate with the BME280 sensor and get the time from an NTP server.
#include <Arduino.h>
#include <WiFi.h>
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include "FS.h"
#include "SD.h"
#include "SPI.h"
#include <Adafruit_BME280.h>
#include <Adafruit_Sensor.h>
#include "time.h"
#include <WiFiUdp.h>
Network Credentials
Insert your network credentials on the following variables so that the ESP32 can connect to your local network.
// Replace with your network credentials
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
Initialize Variables
Then, we initialize some variables that we’ll use throughout the code.
the ntpServer saves the URL of the NTP server we’ll use to get the time.
const char* ntpServer = "pool.ntp.org";
We’ll save the timestamp in epoch time on the epochTime variable.
// Variable to save current epoch time
unsigned long epochTime;
The following variables will hold BME280 sensor readings.
float temp;
float hum;
float pres;
The dataMessage variable will hold the concatenation of all readings separated by commas to be inserted in the data file.
String dataMessage;
The data will be saved on a file called data.txt on the root of the microSD card. The dataPath variable saves the name and path of that file.
const char* dataPath = "/data.txt";
We’ll get new data every 30 seconds (30000milliseconds). You can change the sampling period on the timerDelay variable.
// Timer variables
unsigned long lastTime = 0;
unsigned long timerDelay = 30000;
Create an AsyncWebServer instance on port 80.
// Create AsyncWebServer object on port 80
AsyncWebServer server(80);
And create an Adafruit_BME280 object called bme. It will use the ESP32 default I2C pins (GPIO 21 (SDA), and GPIO 22 (SCL))
// BME280 connect to ESP32 I2C (GPIO 21 = SDA, GPIO 22 = SCL)
Adafruit_BME280 bme;
Initialize the BME280 Sensor
The initBME() function will initialize the BME280 sensor. We’re setting the I2C address to 0x76, which is usually the address for these sensors. However, it might be different. You can check that using an I2C scanner.
// Init BME280
void initBME(){
if (!bme.begin(0x76)) {
Serial.println("Could not find a valid BME280 sensor, check wiring!");
while (1);
}
}
Initialize the MicroSD Card
The following function will initialize the communication with microSD card on the ESP32 default SPI pins. It will also print some information about the microSD card type and size.
// Init microSD card
void initSDCard(){
if(!SD.begin()){
Serial.println("Card Mount Failed");
return;
}
uint8_t cardType = SD.cardType();
if(cardType == CARD_NONE){
Serial.println("No SD card attached");
return;
}
Serial.print("SD Card Type: ");
if(cardType == CARD_MMC){
Serial.println("MMC");
} else if(cardType == CARD_SD){
Serial.println("SDSC");
} else if(cardType == CARD_SDHC){
Serial.println("SDHC");
} else {
Serial.println("UNKNOWN");
}
uint64_t cardSize = SD.cardSize() / (1024 * 1024);
Serial.printf("SD Card Size: %lluMB\n", cardSize);
}
Write Data to a File
The following function allows us to write data to a file. To use this function you must pass as arguments the filesystem type, the file path and the message to be written.
// Write to the SD card
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 a File
The writeFile() function overwrites any existing data on a file. To append data to a file, we have the appendFile() function. It works as the previous function, but will append data instead of overwritting.
// Append data to the SD card
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();
}
Delete a File
The deleteFile() function deletes a file from the specified filesystem and path.
// Delete file
void deleteFile(fs::FS &fs, const char * path){
Serial.printf("Deleting file: %s\r\n", path);
if(fs.remove(path)){
Serial.println("- file deleted");
} else {
Serial.println("- delete failed");
}
}
Get Time
The following function gets and returns the current epoch time.
// Function that gets current epoch time
unsigned long getTime() {
time_t now;
struct tm timeinfo;
if (!getLocalTime(&timeinfo)) {
//Serial.println("Failed to obtain time");
return(0);
}
time(&now);
return now;
}
Initialize Wi-Fi
The initWiFi() function will connect your ESP32 to your local network using the SSID and password you inserted at the beginning of the code.
void initWiFi() {
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
Serial.print("Connecting to WiFi ..");
while (WiFi.status() != WL_CONNECTED) {
Serial.print('.');
delay(1000);
}
Serial.println(WiFi.localIP());
}
setup()
In the setup(), initialize the Serial Monitor, connect the ESP32 to Wi-Fi, initialize the BME280 sensor and the microSD card and configure the time server.
Serial.begin(115200);
initWiFi();
initBME();
initSDCard();
configTime(0, 0, ntpServer);
Then, we create a new file on the microSD card called data.txt where we’ll save the data (if it doesn’t exist yet) and we’ll write the data headers to the file.
// 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 doesn't exist");
Serial.println("Creating file...");
writeFile(SD, "/data.txt", "Epoch Time, Temperature, Humidity, Pressure \r\n");
}
else {
Serial.println("File already exists");
}
file.close();
Handle Requests
Finally, we need to handle what happens when we click on the web page buttons. As we’ve seen previously:
- View Data: will show the data file contents — makes a request on the /view-data path;
- Download Data: downloads the data file to your device — makes a request on the /download path;
- Delete Data: deletes the data file from the microSD card — makes a request on the /delete path.
The following line will serve the index.html file saved on the microSD card to show up the web page.
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
request->send(SD, "/index.html", "text/html");
});
You may also like reading: ESP32 Web Server Hosting Files from MicroSD Card
When we click on the Download button, the ESP32 receives a request on the /download URL, when that happens, we handle the request as follows.
// Handle the download button
server.on("/download", HTTP_GET, [](AsyncWebServerRequest *request){
request->send(SD, "/data.txt", String(), true);
});
To download the file, we need to pass the following arguments to the send() function: filesystem, filepath, String(), and a boolean variable that indicates true = download). For more information you can check this use case on the library documentation here.
When the ESP32 receives a request on the /view-data path, we’ll respond with the contents of the data.txt file as follows:
// Handle the View Data button
server.on("/view-data", HTTP_GET, [](AsyncWebServerRequest *request){
request->send(SD, “/data.txt”, “text/plain”, false);
});
Finally, when the Delete button is clicked, we’ll call the deleteFile() function to detect the file from the microSD card.
server.on("/delete", HTTP_GET, [](AsyncWebServerRequest *request){
deleteFile(SD, dataPath);
request->send(200, "text/plain", "data.txt was deleted.");
});
At the end of the setup(), we need to initialize the server with server.begin().
server.begin();
loop()
In the loop(), we get the time and new data from the sensor every 30 seconds and append it to the data.txt file on the microSD card.
void loop() {
if ((millis() - lastTime) > timerDelay) {
//Get epoch time
epochTime = getTime();
//Get sensor readings
temp = bme.readTemperature();
//temp = 1.8*bme.readTemperature() + 32;
hum = bme.readHumidity();
pres = bme.readPressure()/100.0F;
//Concatenate all info separated by commas
dataMessage = String(epochTime) + "," + String(temp) + "," + String(hum) + "," + String(pres)+ "\r\n";
Serial.print("Saving data: ");
Serial.println(dataMessage);
//Append the data to file
appendFile(SD, "/data.txt", dataMessage.c_str());
lastTime = millis();
}
}
Demonstration
After inserting your network credentials in the code, you can upload it to your ESP32 board.
After uploading, open the Serial Monitor at a baud rate of 115200 and press the ESP32 onboard RST button. It will connect to Wi-Fi and print its IP address.
After that, it will create the file on the microSD card and it should start appending data to the file every 30 seconds.
Let the code run for a while until the ESP32 gathers some data. Then, you can manage the data on the microSD card that the ESP32 is connected to by accessing the web server. Open a browser on your local network and type the ESP32 IP address.
You should get the following page.
You can click on the View Data button to see the raw data on the web browser.
You can also download the file to your computer without the need to remove the microSD card from the adapter and insert it into your computer. You just need to click on the Download Data button.
Then, you can open the file on your computer and process the data as you wish.
Finally, you can also delete the file from the microSD card by clicking the Delete Data button.
And that’s basically how the project works. Feel free to adapt what you learned here to your own projects.
Wrapping Up
In this tutorial, you learned how to download a file stored on a microSD card to your computer using a web server on the ESP32. This is very useful because you don’t need physical access to the card to get the files on your computer.
We hope you found this tutorial useful. Here’s a list of related articles you may like:
- ESP32 Data Logging Temperature to MicroSD Card
- ESP32 Web Server Hosting Files from MicroSD Card
- ESP32: Guide for MicroSD Card Module using Arduino IDE
- ESP32 Web Server: Display Sensor Readings in Gauges
- ESP32/ESP8266: Firebase Data Logging Web App (Gauges, Charts, and Table)
If you want to learn more about the ESP32, check out our resources:
Great, was just working on something like that….which I can now happily abandon. No need to reinvent. Saved me much time
great, but can you make also a enlargement the data to highchart
on the same page
Here is an example with Highcharts.
https://drive.google.com/drive/folders/1pCMxZDTGQYR0_KZi7bPpzTpGjn2A6r3M?usp=sharing
Hi.
You can use the following tutorials as inspiration:
https://randomnerdtutorials.com/esp32-esp8266-plot-chart-web-server/
https://randomnerdtutorials.com/esp32-plot-readings-charts-multiple/
Regards,
Sara
Hi.
Peter can just use my example.
My example is fully implemented in your project.
It’s just a matter of uploading the sketch and the data folder.
https://drive.google.com/drive/folders/1pCMxZDTGQYR0_KZi7bPpzTpGjn2A6r3M?usp=sharing
my mistake I should have written.
It was just a matter of uploading the sketch
and copy the files to the root of the SD card
Hi JB
It is working ,thanks.
I rewrite the sketch and i use only the SD.h,
only delete is not yet working.
and the chart lines are for my to thick,
but that is now no problem.
thanks.
Hi.
I most look later this week,
the examples from Sara is that it print real time,
and thats not my idea.
When i start my computer in the evening i will that
highchart is writing the full day data from the sd-card to the website.
this is what i mean as example
http://everettsprojects.com/2012/12/31/arduino-super-graphing-data-logger/
thanks for you effort.
peter
P.S.
but than with the ESP32 and SD-card.
peter
That’s exactly what you can do with my example.
I have posted two versions, one with SD card and one with Littlefs file system
You can just take a look at the links in my other posts on this page.
I’m glad you got it working!!
Hi Peter.
you can change the line width like this.
plotOptions: {
line: { animation: false,
lineWidth: 1,
dataLabels: { enabled: true
}
},
},
Well done, it is working as you designed it.
One thing may be worth to mention. The SD card module I am using does not have the CLK pin. It is called SCK. So I have connected your green wire (coming from the ESP32 board as D18) to SCK. The other modification was to connect VCC of the SD card module to Vin of the ESP32 board (+5Volt). The voltage of 3.3 V was not enough (it is the SD card module as shown in https://www.youtube.com/watch?v=Ts9PgVHjSOs)
After these two corrections the datalogger works perfect!
Hi, Very useful post. SD cards hold huge amounts of data and downloading big files this way is quite slow. Is the speed limit in the ESP32 or is it in the software? Any tips on how to speed it up?
Bill
I love the practical applications of this project. It is incredibly useful. I tried something similar a few years back when I logged my car’s engine temperature over time. The data was later transferred via FTP to a MongoDB when the car was in my garage where I had Wi-Fi. I wish I could have meet this article before I started my project!
nice tutorial :–) Thank you !! (been wanting to do that for a while) … however, for some reason, when I click on View, it opens a window to save it somewhere (similar to what the Download button does). … any idea why that would happen? (the request is “request->send(SD, “/data.txt”, “text/txt”);” as per your code. (I even tried manually writing view-data at the end of the IP address … same thing happens).
… works on Internet Explorer. I use Mozilla Foxfire, so it may be a security issue with Foxfire.
Hi.
I tested it on Google Chrome and it works well.
I didn’t test on Firefox.
Regards,
Sara
request->send(SD, “/data.txt”, “text/txt”);
change code to this and it will work in firefox.
request->send(SD, “/data.txt”, “text/plain”, false);
Yes! … works fine now in Firefox. Thanks!!
I thank you for replying back.
Thanks for sharing.
Regards,
Sara
If you prefer the time in this format.
Sat 18/05/2024 19:40:11,23.99,44.31,1010.07
here is a link to Rui & Sara’s sketch slightly modified.
just be aware that the code has been changed to use LittleFs
instead of using sd card.
https://drive.google.com/drive/folders/1pCMxZDTGQYR0_KZi7bPpzTpGjn2A6r3M?usp=sharing
The instructions show a card reader with 3v3 and CLK pins. All of the readers in the parts list have VCC and SCK pins. The VCC is 5v. Where does the SCK go? Any changes in the sketch?
My experience is that you can connect SCK (Serial ClocK) to the same pin (D18) as the CLK signal in the sketch. See also my comment above (May 16, 2024 at 9:09 pm)
Hi.
SCK and CLK is the same.
Regards,
Sara
I have a half baked project doing similar that I got stuck with and lost interest ( Something else came along). I will now use this project and try to add my own sensors and when that works try and extend the range. Thankyou for this, great timing.
Great article Sara. One small question: If the data is being recorded at a high rate and the file to be downloaded has become very big – what happens when a file write occurs during a download? Perhaps I should be asking the SD library writers, but I have setup this situation with a 1 second sample time and a data file that takes several seconds to download (> 1183KB). After many downloads, file comparisons between consecutive downloads show no missing or corrupted data. Is this just a fluke?
Regards, Ron
I test it with BMP180. I got data and IP address.
I pasted IP address on Google Chrome but web page did not appear. Plz, solve my issue.
Hi.
You probably forgot to put the HTML page on the microSD card.
Regards,
Sara
A great project, but please note not all browsers respect the view data path.
Firefox just offers a download, but edge, iron and brave work fine (ok they are all chrome based)
Hi.
This project was tested using Google Chrome.
I haven’t tested it on Firefox. But, it seems that it doesn’t work as expected with that browser.
Regards,
Sara
Hi Sarah.
maybe you should update your tutorial
to this, obviously not everyone reads the comments.
Then view data also works in Firefox.
request->send(SD, “/data.txt”, “text/txt”);
change code to this and it will work in Firefox.
request->send(SD, “/data.txt”, “text/plain”, false);
Thanks.
I’ll do that.
Regards,
Sara
Hi Sara
Sorry for spelling your name wrong.
Thanks for all your tutorials.
Hi.
request->send(SD, “/data.txt”, “text/txt”);
change code to this and it will work in firefox.
request->send(SD, “/data.txt”, “text/plain”, false);
Hello Mr. JB, I ran your project. However, unlike your project, I added RTC to my system. And instead of connecting to a modem, I use esp 32 as a modem. My problem is that when I want to draw a graph from the internet browser, it draws the old data on the graph. When I clear my browser’s history, a new graph appears. I have to clear the browser history every time I want to see graphics. Is there a solution to this? Thank you very much in advance
Hi Sara.
How about making tutorials on the new Esp32 c3 super mini, and esp32 c6 mini boards. I myself use Esp32 c3 super mini. and I think they’re pretty cool.
Hello;
I’ve just try the project and receive the message “Card Mount Failed” in serial monitor.
I used a 128GB card, and change to 32Gb and all works fine then.
I used the BMP280 sensor too, with minor changes in programming.
Connecting to WiFi ……192.168.1.48
Card Mount Failed
File doesn’t exist
Creating file…
Writing file: /data.txt
Failed to open file for writing
Saving data: 0,26.99,1013.80,95.39
Appending to file: /data.txt
Failed to open file for appending
Saving data: 1718995539,27.17,1013.84,95.09
..192.168.1.48
SD Card Type: SDHC
SD Card Size: 30436MB
File already exists
Saving data: 1719000347,27.59,1014.36,90.80
Hi Sara,
a pretty nice and helpfull tutorial. But what is if someone wouldn’t use a SD-Card (with Reader) ? It is really easy to save a file to the computer who have the browser running and from there anyone cpuld save th file wherever – maybe over USB to a SD-Stick.
Can you give a sample-code snipet (or modify the given) to collect sensor-data and save this data over a separate download-button vis browser directly to the computer. I think there is extremly less code necessary to have one more save-option without SD-Card-Reader installed.
Thanks in advance,
Manfred