ESP8266 data logger: temperature and humidity measurements, SD card storage and remote access with REST API

Introduction

Welcome to the ESP8266 data logger project. In this article, we will explore in depth the creation of an advanced data logger driven by an ESP8266. Our mission is to build a device that can accurately record changes in ambient temperature and humidity at regular intervals and store them neatly on an SD card. The ESP8266, renowned for its flexibility and Wi-Fi connection capability, not only takes care of local logging but also offers a REST API interface. This functionality opens the door to intelligent monitoring and management of our data logger remotely.

A notable aspect of this project is the organization of folders and files on the SD card, structured according to the current year, month and day. Each CSV file contains detailed data, such as temperature, humidity, hour and minute, recorded every half hour. A distinctive feature is the possibility of easily consulting the measurements without having to turn off the device and extract the SD card, thanks to a REST API system. Additionally, REST APIs allow you to check and update the clock in real time, get current temperature and humidity data, or retrieve log files intuitively and quickly.

A key point of this project is flexibility and practicality, offering an intuitive interface for the user. Whether you are a curious hobbyist or an IoT industry expert, this ESP8266 data logger offers you a powerful and scalable solution for environmental monitoring. Let’s discover together how to put this versatile device into practice, paving the way for numerous applications in the vast world of the Internet of Things.

Main features of our ESP8266 data logger

  1. Accurate Data Recording: the data logger is able to precisely detect environmental changes in temperature and humidity at regular half-hour intervals.
  2. Organized Structure of Folders and Files: the SD card organizes information intuitively, dividing it into directories corresponding to the current year and month, with daily files containing detailed temperature and humidity data. So, to give an example, the measurements of a certain day (for example January 26, 2024) will be found in the file with path templog/24/01/26.
  3. Wi-Fi connectivity: thanks to the ESP8266, the project offers the possibility of managing data remotely via Wi-Fi connectivity. This allows you to monitor and retrieve information in real time without having to physically manipulate the SD card.
  4. Precise Measurements Every 30 Minutes: taking regular measurements every half hour provides a detailed view of environmental conditions over time and is an excellent compromise with the size of the generated file which will contain a maximum of 48 measurements, resulting in a file small enough to be easily recalled via a specific API.
  5. REST API interface: adding a REST API expands remote management possibilities. Allows you to synchronize the clock in real time, get instant temperature and humidity updates, or easily retrieve log files without additional effort.

As in the other cases, we will use the PlatformIO IDE for firmware development while to test the REST API we will use the Postman program.

The set of REST APIs available

The device communicates with the outside via a set of 5 REST APIs, 2 of GET type and 3 of POST type:

  • getDate (GET) returns a Json document containing the current date and time in the RTC module (year, month, day, hours, minutes, seconds). It is used to check the accuracy of the date and time;
  • getTH (GET) returns a Json document containing the current temperature and humidity. Useful for making a measurement on the fly without having to download the entire day’s file;
  • fileExists (POST) returns true or false depending on whether a certain file is present in the file system or not. The data to allow it to construct the correct path of the file are year, month, day sent via a special Json of the type:
                      {
                             "year": "24",
                             "month" : "01",
                             "day" : "27"
                       }
  • fileRead (POST) returns the contents of a given file. The data to allow it to construct the correct path of the file are year, month, day sent via a special Json of the type:
                      {
                             "year": "24",
                             "month" : "01",
                             "day" : "27"
                       }
  • setDate (POST) adjust the clock with the year, month, day, hours, minutes and seconds data provided with a Json of the type:
                      {
                             "year": "24",
                             "month" : "01",
                             "day" : "27",
                             "hour" : "15",
                             "minutes" : "12",
                             "seconds" : "10"
                       }

What components do we need for our data logger?

The list of components is not particularly long:

  • a breadboard to connect the NodeMCU ESP8266 to other components
  • someDuPont wires (male – male, male – female, female – female)
  • a DHT22 sensor
  • a 4.7 kΩ resistor
  • an RTC DS3231 module
  • a micro SD card reading/writing module with SPI interface
  • a micro SD card of no more than 32GB formatted in FAT32
  • and, of course, a NodeMCU ESP8266 !

Let’s now look at these components in more detail.

The DS3231 module

The DS3231 RTC (Real-Time Clock DS3231) is an electronic component widely used to track time in embedded applications. Its I2C (Inter-Integrated Circuit) interface makes it easy to integrate with microcontrollers, such as the Arduino, and other digital devices (such as ESP8266 and ESP32). The one used in this article is produced by the company AZDelivery. Let’s see an accurate description of the DS3231:

Extreme precision

The DS3231 is known for its amazing accuracy in keeping track of time. It has a maximum error of just a few seconds per year, making it ideal for applications requiring accurate time stamps.

I2C interface

The DS3231 RTC communicates via the I2C (or I-squared-C) interface. I2C is a serial communications protocol that allows you to connect multiple devices on a single bus, making the DS3231 ideal for projects that require simple, efficient time management.

Full calendar

In addition to keeping track of time, the DS3231 also manages a full calendar, including days of the week, months and years, even accounting for leap years. This feature makes it useful in applications such as alarm clocks, digital calendars, and real-time clocks.

Built-in EEPROM memory

The DS3231 is equipped with a small EEPROM (Electrically Erasable Programmable Read-Only Memory) that can be used to store additional data. This memory is non-volatile, which means that data remains preserved even in the absence of electrical power.

Configurable alarm

You can set up two separate alarms on the DS3231, allowing the device to generate a stop signal or an alarm signal when certain time conditions are met. This feature is useful in applications such as alarm clocks or time controls.

Integrated temperature

The DS3231 also features a built-in temperature sensor. This sensor can be used to monitor ambient temperature and is especially useful when temperature accuracy is important for an application.

Low power and battery backup

To maintain time accuracy even in the event of a main power failure, the DS3231 can be powered by a backup battery. This battery ensures that the device continues to function and keep track of time even when the main power is cut.

Common applications

The DS3231 is widely used in a wide range of applications, including:

  1. Real Time Clocks (RTC): it is commonly used to add precise timestamping capabilities to devices such as digital watches.
  2. Digital alarm clocks: the DS3231 can be used to create precise alarms that do not need to be reset frequently.
  3. Control of timed devices: it is useful in applications that require scheduled activations or deactivations.
  4. Data logger: can be used to annotate data with timestamps in data logging projects.
  5. Home automation systems: It can be integrated into home automation systems to schedule time-based actions.

In summary, the DS3231 is a highly reliable and accurate component for time and date monitoring in electronic applications. Its I2C interface simplifies integration with a variety of devices, making it a popular choice for microcontroller-based projects.

The micro SD card module

The micro SD card module is an electronic component designed for use with Arduino boards and other compatible development platforms. This module allows you to read and write data to Micro SD and Micro SDHC (TransFlash) memory cards using SPI (Serial Peripheral Interface) communication. The one used in this article is produced by the company AZDelivery.

Here is a detailed description of this module:

SPI interface

The SD card reader module uses SPI interface, which is a 4-wire serial communication protocol commonly used in embedded projects. These four wires are:

  1. MISO (Master In Slave Out): this is the pin through which the module receives data from the master device, which is usually the Arduino or another microcontroller.
  2. MOSI (Master Out Slave In): this is the pin through which the module sends data to the master device.
  3. SCK (Serial Clock): this is the clock pin that synchronizes data transmission between the module and the master device.
  4. CS (Chip Select): this pin is used to select the SD card reading module and initialize read/write operations.

Support for Micro SD and Micro SDHC

This module is compatible with both Micro SD cards and Micro SDHC cards, allowing the use of cards with capacities up to 32GB. Micro SD cards are commonly available and offer ample storage capacity for data such as log files, images, audio, or any other information you want to record.

Easy to use

The SD Reader Module is easy to integrate into your Arduino projects. It comes with a pre-installed Arduino library, which makes reading and writing data to micro SD cards much easier. This library allows you to easily access files on the card and perform operations such as creating, reading, modifying and deleting files.

Status LED

The module is equipped with a status LED that indicates when the module is active and communicating with the master device. This LED can be useful for debugging and monitoring read/write operations.

Common applications

This micro SD card reader module is widely used in a number of projects, including:

  • Data logging: to record data from sensors or other sources onto a micro SD card for future analysis.
  • Reading multimedia files: to read audio or image files from micro SD cards for playback or viewing on devices.
  • IoT projects: in Internet of Things (IoT)-based projects to record environmental or sensor data on micro SD cards.
  • Video recording: in video recording systems based on Arduino or similar microcontrollers.

The SD card module is a useful and practical component for projects that require reading and writing data on Micro SD memory cards. Its compatibility with Arduino and other development platforms makes it a valuable addition for projects that require data storage and management. Due to its ease of use and support for large memory cards, it is a popular choice among electronics enthusiasts and developers.

The DHT22 sensor

Here is a detailed technical overview of the main features of the DHT22 sensor:

  1. Accuracy of Measurements: the DHT22, also known as AM2302, is a digital temperature and humidity sensor that offers remarkable precision in measurements. The temperature accuracy is ±0.5°C, while for humidity it is ±2%.
  2. Wide Measurement Range: the sensor is able to measure the temperature in a range from -40°C to 80°C, therefore covering a wide range of environmental conditions. As for humidity, the range is between 0% and 100%.
  3. Fast answer: thanks to its ability to respond quickly to environmental changes, the DHT22 is ideal for monitoring conditions in real time.
  4. Digital Signals: the sensor transmits data directly in digital form, simplifying interfacing with microcontrollers such as the ESP8266. This avoids the need for external analog-to-digital converters.
  5. Reliability and Durability: designed to offer long life, the DHT22 features good reliability over time, making it suitable for long-term monitoring applications.
  6. Easy to use: with its single-wire communication interface, the DHT22 simplifies integration into electronic designs. Communication occurs via a two-wire communication protocol (data and ground).
  7. Integrated Calibration: the sensor includes internal calibration, reducing the need for external corrections and ensuring greater measurement accuracy.
  8. Wide Applicability: due to its features and ease of integration, the DHT22 is used in a variety of applications, including personal weather stations, air conditioning systems, and environmental monitoring projects.

Project implementation

The electrical diagram

Before creating the actual circuit let’s take a look at the pinout of the board:

ESP8266 NodeMCU pinout
ESP8266 NodeMCU pinout

Let’s also see the pinouts of the other components:

The pinout of the RTC module
The pinout of the RTC module
The pinout of the micro SD card module
The pinout of the micro SD card module

The DHT22 sensor pinout:

DHT22 pinout
DHT22 pinout

Let’s now see the electrical diagram of the project, created as usual with Fritzing:

Fritzing circuit diagram of the ESP8266 data logger
Fritzing circuit diagram of the ESP8266 data logger

It is possible that some modules need some connectors and therefore it is necessary to do some soldering. If you are new to this topic I recommend you read the article Yet another tutorial on how to solder.

As you can see, the micro SD card module is powered by 5V from the Vin terminal while the RTC module, as well as the DHT22 sensor, is powered by 3.3V from the 3V3 terminal of the ESP8266.

The micro SD card module is connected to the SPI port of the ESP8266 which uses the pins:

  • D8 for CS terminal (Chip Select)
  • D7 for MOSI terminal (Master Out Slave In)
  • D6 for MISO terminal (Master In Slave OUT)
  • D5 for the SCK terminal (Serial Clock)

The RTC module is connected to the I2C port of the ESP8266 which uses the pins:

  • D1 for the SCL terminal
  • D2 for the SDA terminal

The DHT22 sensor is instead connected to GPIO D4.

The sketch

Let’s create the PlatformIO project

We have already seen the procedure for creating a PlatformIO project in the article How to create a project for NodeMCU ESP8266 with PlatformIO.

Of the libraries indicated, install the DHT sensor library for ESPx by Bernd Giesecke and the WiFiManager by tzapu. Then install the RTClib by Adafruit library as shown in the following photo:

Install the RTClib by Adafruit library
Install the RTClib by Adafruit library

Also install the ArduinoJson library by Benoit Blanchon:

ArduinoJson library by Benoit Blanchon
ArduinoJson library by Benoit Blanchon

and the Adafruit BusIO library by Adafruit:

Adafruit BusIO Library by Adafruit
Adafruit BusIO Library by Adafruit

Now edit the platformio.ini file to add these two lines:

monitor_speed = 115200
upload_speed = 921600

and these two other lines at the end:

Wire
SPI

so that it looks like this:

[env:nodemcuv2]
platform = espressif8266
board = nodemcuv2
framework = arduino
monitor_speed = 115200
upload_speed = 921600
lib_deps = 
	adafruit/RTClib@^2.1.3
	adafruit/Adafruit BusIO@^1.15.0
	beegee-tokyo/DHT sensor library for ESPx@^1.19
	bblanchon/ArduinoJson@^7.0.2
	tzapu/WiFiManager@^0.16.0
	Wire
	SPI

Obviously you can download the project from the following link:

Replace the main.cpp file of the project you created with the one present in the zip file.

Now let’s see how the sketch works.

Initially the necessary libraries are included:

#include <Arduino.h>
#include "DHTesp.h"
#include <Wire.h>
#include <RTClib.h> // Library for the DS3231 RTC
#include <SPI.h> // Include the SPI.h library
#include <SD.h>
#include <ESP8266WebServer.h>
#include <ArduinoJson.h>
#include <WiFiManager.h>

Then the myFile object of type File is instantiated which allows you to manage the files in the SD card, the GPIO D8 for the Chip Select terminal of the SD card is defined and the basic path (templog/) for all the files managed in the SD card is defined:

// set up variables using the SD utility library functions:
File myFile;
const int chipSelect = D8;
String pathbase = "templog/";

The file system will then be organized into folders and files that derive from the current year, month and day. For example, the path templog/24/01/26 indicates the day January 26, 2024 and this file will contain the measurements of that single day. The creation of folders and files is carried out automatically by the data logger. If a folder is not there, it is created if necessary (for example, if you move from January to February, the data logger will create folder 02 inside folder 24 and files 01, 02, 03…… inside folder 02 , representing the days of February). When the year changes, going from 2024 to 2025, the data logger will create folder 25 at the same level as folder 24 and so on. This way the files are tidy and easily traceable.

Immediately afterwards, the dht object that manages the sensor is instantiated and the GPIO connecting to the sensor is defined:

// Set the DHT22 sensor pin
DHTesp dht;
#define  DHT22_PIN D4 

The variables that establish the timing of the measurements are then defined. They are carried out every 30 minutes in order to have 48 measurements per day (i.e. 48 lines per file) in order to have a good compromise between the frequency of the measurements and the size of the generated file:

unsigned long measureDelay = 1800000;                //    NOT LESS THAN 2000!!!!!    BETTER 1800000  (30 MINUTES)
unsigned long lastTimeRan;

The rtc object that manages the clock is then instantiated and the global variable readFile is used to contain the file requested via a specific REST API and then returned as a response:

RTC_DS3231 rtc;
String readFile = "";

The webserver listening on port 80 is defined which will manage the API and the Json document and a support buffer are defined:

// Web server running on port 80
ESP8266WebServer server(80);
StaticJsonDocument<1024> jsonDocument;
char buffer[1024];

We then encounter the function:

void addJsonObject(char *name, float value) {
  JsonObject obj = jsonDocument.createNestedObject();
  obj["name"] = name;
  obj["value"] = value;
}

which adds elements to the Json document during its creation. Json document which will then be the response of an API.

The getDate function creates a Json containing the current date and time in order to check the accuracy of the RTC module. The Json document it creates is used as a response for the getDate API:

void getDate() {

  DateTime now = rtc.now(); // Read the date and time from the DS3231    

  jsonDocument.clear(); // Clear json buffer
  addJsonObject("year", now.year());
  addJsonObject("month", now.month());
  addJsonObject("day", now.day());
  addJsonObject("hour", now.hour());
  addJsonObject("minutes", now.minute());
  addJsonObject("seconds", now.second());
  serializeJson(jsonDocument, buffer);
  server.send(200, "application/json", buffer);
}

The fileIsPresent function checks whether or not a given file whose path is provided is present in the file system:

bool fileIsPresent(String path) {
  return SD.exists(path);
}

It is used for example by the fileExists API.

The getTH function creates a Json containing the current temperature and humidity values. The Json document it creates is used as a response for the getTH API:

void getTH() {
  float h = dht.getHumidity(); // reads humidity and puts the value in the h variable
  float t = dht.getTemperature();
  jsonDocument.clear(); // Clear json buffer
  addJsonObject("temperature", t);
  addJsonObject("humidity", h);
  serializeJson(jsonDocument, buffer);
  server.send(200, "application/json", buffer);
}

The setDate function takes as input a Json containing year, month, day, hours, minutes and seconds and adjusts the clock with this data. This is in case we want to adjust the clock manually. This function is called by the setDate API:

void setDate() {
  if (server.hasArg("plain") == false) {
  //handle error here
  }
  String body = server.arg("plain");
  deserializeJson(jsonDocument, body);

  // Get code for resistance
  String year_s = jsonDocument["year"];
  String month_s = jsonDocument["month"];
  String day_s = jsonDocument["day"];
  String hour_s = jsonDocument["hour"];
  String minutes_s = jsonDocument["minutes"];
  String seconds_s = jsonDocument["seconds"];
  rtc.adjust(DateTime(year_s.toInt(), month_s.toInt(), day_s.toInt(), hour_s.toInt(), minutes_s.toInt(), seconds_s.toInt()));

  // Respond to the client
  server.send(200, "application/json", "{}");
}

The fileExists function checks the existence of a given file starting from the path created with the year, month and day. It uses the fileIsPresent function encountered previously and is called by the fileExists API:

void fileExists() {
  if (server.hasArg("plain") == false) {
  //handle error here
  }
  String body = server.arg("plain");
  deserializeJson(jsonDocument, body);

  // Get code for resistance
  String year = jsonDocument["year"];
  String month = jsonDocument["month"];
  String day = jsonDocument["day"];

  String path = "templog/" + year + "/" + month + "/" + day;
  String res = "";
  if(fileIsPresent(path)) {
    res = "true";
  } else {
    res = "false";
  }

  // Respond to the client
  String response = "{\"isPresent\" : " + res + "}";
  server.send(200, "application/json", response);
}

The readfile function reads the file present at the given path and stores it in the readFile variable. It is called by the fileRead API:

void readfile(String path) {
  readFile = "";
  char patharray[path.length() + 1];
  path.toCharArray(patharray, path.length() + 1);
  SD.begin(chipSelect);
  myFile = SD.open(patharray);
  if (myFile) {
    // read from the file until there's nothing else in it:
    for (unsigned long i = 0; i <=  myFile.size() - 1; i++) {
      myFile.seek(i);
      readFile = readFile + (char)myFile.peek();
    }
    // close the file:  
    myFile.close();  
  }  
}

The fileRead function is the actual API that returns the contents of the file read by the readfile function:

void fileRead() {
  if (server.hasArg("plain") == false) {
  //handle error here
  }
  String body = server.arg("plain");
  deserializeJson(jsonDocument, body);

  // Get code for resistance
  String year = jsonDocument["year"];
  String month = jsonDocument["month"];
  String day = jsonDocument["day"];

  String path = "templog/" + year + "/" + month + "/" + day;
  String res = "";
  if(fileIsPresent(path)) {
    readfile(path);
    String response = "{\"file\" : \"";
    readFile.trim();
    response +=   readFile;
    response += "\"}";
    server.send(200, "application/json", response); 
  } else {
    server.send(404, "application/json", "{}");
  }

}

The measure_sd function reads the current temperature and humidity values ​​and composes part of the string to be saved to the file (it does not take care of the hours and minutes):

String measure_sd() {
  char temperature_c[6];
  char humidity_c[6];
  float h = dht.getHumidity(); // reads humidity and puts the value in the h variable
  float t = dht.getTemperature(); // reads temperature and puts the value in the t variable
  dtostrf(t, 0, 1, temperature_c);  // Here we need to convert the float to a string
  dtostrf(h, 0, 1, humidity_c);  // Here we need to convert the float to a string
  return (String)temperature_c + "," + (String)humidity_c;
}

The sanitize function ensures that the values ​​of months, days, hours, minutes and seconds always have two digits, prepending a zero in the case of single-digit numbers. So “1” becomes “01” and so on:

String sanitize(String hms) {
  if(hms.length() < 2) {
    hms = "0" + hms;
  }
  return hms;
}

The updatefile function creates, if not present, the file with the correct path obtained from the current date and writes the temperature and humidity values ​​by taking the string created by the measure_sd function and concatenating it with the current hour and minutes. If the file is already present, it simply writes the new data (append) to it until it is complete:

void updatefile() {
  DateTime now = rtc.now();
  String path_folder = pathbase + sanitize(((String)now.year()).substring(2,5)) + "/" + sanitize((String)now.month()) + "/";
  String path_file = path_folder + sanitize((String)now.day()); 
  String line = measure_sd() + "," + sanitize((String)now.hour()) + ":" + sanitize((String)now.minute());
  SD.begin(chipSelect);
  char path_folder_array[path_folder.length() + 1];
  path_folder.toCharArray(path_folder_array, path_folder.length() + 1);
  char path_file_array[path_file.length() + 1];
  path_file.toCharArray(path_file_array, path_file.length() + 1);
  
  if(!SD.exists(path_folder_array)) {SD.mkdir(path_folder_array);}  

  myFile = SD.open(path_file_array, FILE_WRITE);

  // if the file opened okay, write to it:
  if (myFile) {
    myFile.println(line);
    // close the file:
    myFile.close();
  } 
}

The setupApi function associates the 5 APIs /getDate, /getTH, /fileExists, /fileRead and /setDate with the respective functions getDate, getTH, fileExists, fileRead, setDate:

void setupApi() {
  server.on("/getDate", getDate);
  server.on("/getTH", getTH);
  server.on("/fileExists", HTTP_POST, fileExists);
  server.on("/fileRead", HTTP_POST, fileRead);
  server.on("/setDate", HTTP_POST, setDate);
 
  // start server
  server.begin();
}

The setup function begins with the initialization of the serial port, the connection of the DHT22 to the GPIO D4 and the initialization of the Wire and rtc modules:

  Serial.begin(115200);
  delay(2000);  
  dht.setup(DHT22_PIN, DHTesp::DHT22); // Connect DHT sensor to GPIO D4 

  Wire.begin();
  rtc.begin();

Then continue with the initialization of the SD card:

  // Initialize SPI communication with the SD module
  if (!SD.begin(chipSelect)) {
    Serial.println("Error initializing the SD card.");
    return;
  } 

  Serial.println("SD card initialized successfully.");

and adjusting the clock by sending it the computer time:

  if (rtc.lostPower()) {
    Serial.println("RTC not initialized. I set the time...");
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  }

Then follows the whole part of managing the WiFi connection:

WiFi.mode(WIFI_STA); // explicitly set mode, esp defaults to STA+AP
// it is a good practice to make sure your code sets wifi mode how you want it.

//WiFiManager, Local intialization. Once its business is done, there is no need to keep it around
WiFiManager wm;

// reset settings - wipe stored credentials for testing
// these are stored by the esp library
// wm.resetSettings();

// Automatically connect using saved credentials,
// if connection fails, it starts an access point with the specified name ( "AutoConnectAP"),
// if empty will auto generate SSID, if password is blank it will be anonymous AP (wm.autoConnect())
// then goes into a blocking loop awaiting configuration and will return success result

bool res;
// res = wm.autoConnect(); // auto generated AP name from chipid
// res = wm.autoConnect("AutoConnectAP"); // anonymous ap
res = wm.autoConnect("AutoConnectAP","password"); // password protected ap

if(!res) {
    Serial.println("Failed to connect");
    ESP.restart();
} 
else {
    //if you get here you have connected to the WiFi    
    Serial.println("Connected...yeey :)");
}

and the call to the setupApi() function which serves to route the various REST requests to the appropriate functions (as already seen above).

The very simple loop function cyclically calls the server function that handles requests from the client (our Postman program) and updates the file on the SD card every measureDelay ms:

void loop() {
  // put your main code here, to run repeatedly:
  server.handleClient();
  if (millis() > lastTimeRan + measureDelay)  {
    updatefile();
    lastTimeRan = millis();
  }  
}

How to connect the board to the Internet

After uploading the sketch to the card, open the Serial Monitor to see the messages coming from the device. First the board goes into Access Point mode and will provide us with an IP address that we will use shortly. This operation is used to connect the board to the Internet without having to enter the WiFi network parameters (SSID and password) in the code.

The board provides us with its IP address
The board provides us with its IP address

In this case the IP address is 192.168.4.1.

At this point the ESP8266 is in Access Point mode (with AutoConnectAP SSID) and we need to connect our computer to the AutoConnectAP network. If we go to the networks menu of our computer, we should also see the AutoConnectAP network in the list of wireless networks.

List of available WiFi networks
List of available WiFi networks

Connect your computer to the AutoConnectAP network. Then go to your browser and enter the IP previously provided by the ESP8266 (which in this example is 192.168.4.1)

You will see a screen like this:

The browser screen for choosing the network
The browser screen for choosing the network

Click the ConfigureWiFi button. It will show you the available networks:

List of available networks
List of available networks

Choose your network’s SSID:

Choose your network
Choose your network

Enter your network password and click the save button:

Enter your password
Enter your password

The board's response
The board’s response

The ESP8266 module keeps the access parameters stored even if you turn it off, it will remember them when restarting and will automatically reconnect without having to repeat this procedure. Only if you reset it by uncommenting this line

// wm.resetSettings();

will lose the connection parameters.

Please note: the device can only memorize one network. If you later connect it to another network, it will forget the settings of the previous network.

Let’s test the project with REST APIs

Once the ESP8266 has been connected to the WiFi network it will provide us with its IP address via the PlatformIO Serial Monitor, as visible in the following figure:

We obtain the IP of the board
We obtain the IP of the board

In this case the IP assigned by the router to the board is 192.168.1.9. This IP will be used to compose the REST API.

To interact with the board we need special software called Postman. After installing the program, we are ready to use it.

This is what its home screen looks like:

Postman home screen
Postman home screen

In the main window there is a bar where you will need to enter the API.

To the left of this bar there is a drop-down menu that allows you to choose the type of API (for example GET, POST, PUT…).

NOTE: in subsequent experiments the IP 192.168.1.121 was assigned so the following images will refer to this IP. You, of course, will have to enter the IP address that was assigned to your ESP8266.

In general the structure of the API is of this form:

http://IP_ESP8266/APIname

Let’s try the GET API. In the drop-down menu on the left we choose the GET item. Let’s try the getDate API by placing the line

192.168.1.121/getDate

in the box to the right of the GET menu and press the Send button. Hopefully we’ll get a response like this:

getDate API
getDate API

Now let’s try getTH. Let’s put the line:

192.168.1.121/getTH

in the box to the right of the GET menu and press the Send button. Hopefully we’ll get a response like this:

getTH API
getTH API

Let’s now move on to the POST type API. In the drop-down menu on the left we choose the POST type.

They involve providing a Json document as input data to the API. To provide this Json, you will need to select the Body item below the URL bar. Then select the raw item (under Body) and then, on the drop-down menu on the right, select the JSON item instead of Text.

Let’s see it with the first POST API, fileExists. Let’s put the line

192.168.1.121/fileExists

we insert the Json file as explained above and press the Send button.

The answer should be something like this:

fileExists API
fileExists API

To adjust the clock we use the setDate always inserting the Json as explained above. Using the line

192.168.1.121/setDate

we should therefore have a situation similar to this:

API setDate
API setDate

By pressing the Send button the clock will be set with the incoming Json data.

Finally we read a given file with the command

192.168.1.121/fileRead

always inserting the Json containing the year, month and day to identify it in the file system.

The situation will be like this:

fileRead API
fileRead API

In this specific case I get a response like this:

{"file" : "18.7,62.2,00:03
18.4,61.8,00:33
18.1,61.2,01:03
17.9,60.7,01:33
17.6,62.2,02:03
17.4,61.9,02:33
17.3,60.3,03:03
17.2,61.1,03:33
17.1,61.2,04:03
16.9,61.2,04:33
16.9,60.9,05:03
16.7,60.5,05:33
16.7,60.5,06:03
16.5,60.5,06:33
16.4,60.2,07:03
16.3,60.3,07:33
16.3,60.5,08:03
16.2,61.7,08:33
16.2,61.7,09:03
15.9,62.1,09:33
16.0,63.4,10:03
16.1,64.2,10:33
16.0,64.7,11:03
16.1,65.8,11:33
16.1,65.7,12:03
16.6,65.7,12:33
16.4,66.4,13:03
16.5,70.6,13:33
16.6,70.9,14:03
16.6,72.6,14:33
16.7,71.6,15:03
16.7,71.6,15:33
16.6,71.5,16:03
16.6,71.1,16:33
16.6,71.0,17:03
16.6,70.1,17:33
16.5,71.2,18:03"}

By cleaning the file by eliminating the initial part {“file” : “ and the final part “} we obtain a CSV file containing the day’s data:

18.7,62.2,00:03
18.4,61.8,00:33
18.1,61.2,01:03
17.9,60.7,01:33
17.6,62.2,02:03
17.4,61.9,02:33
17.3,60.3,03:03
17.2,61.1,03:33
17.1,61.2,04:03
16.9,61.2,04:33
16.9,60.9,05:03
16.7,60.5,05:33
16.7,60.5,06:03
16.5,60.5,06:33
16.4,60.2,07:03
16.3,60.3,07:33
16.3,60.5,08:03
16.2,61.7,08:33
16.2,61.7,09:03
15.9,62.1,09:33
16.0,63.4,10:03
16.1,64.2,10:33
16.0,64.7,11:03
16.1,65.8,11:33
16.1,65.7,12:03
16.6,65.7,12:33
16.4,66.4,13:03
16.5,70.6,13:33
16.6,70.9,14:03
16.6,72.6,14:33
16.7,71.6,15:03
16.7,71.6,15:33
16.6,71.5,16:03
16.6,71.1,16:33
16.6,71.0,17:03
16.6,70.1,17:33
16.5,71.2,18:03

As already mentioned, the file is in CSV format. This is because a Comma-Separated Values ​​(CSV) file is a type of text file used to represent tabular data, such as tables or spreadsheets, in which columns of data are separated by commas or other delimiters. Here is a description of a CSV file:

  1. Pure text: a CSV file is a pure text file that contains data in tabular format. It can be opened and read with any text editor.
  2. Rows and columns: the data is organized into rows and columns. Each row represents a record or instance of data, while the columns represent fields or variables in the data.
  3. Delimiters: the data in the columns is separated by delimiters, usually commas (,), semicolons (;), or tabs (\t). The delimiter you choose determines the type of CSV file (CSV with comma, CSV with semicolon, CSV with tab, etc.).
  4. Headers: often, the first line of a CSV file contains the column headers, i.e. the field names. These headings are useful for understanding the meaning of the data in the columns.
  5. Data: subsequent lines contain the actual data. Each row represents a record and each field (column) contains a specific value.
  6. Quotes: in some cases, values ​​in a column may be enclosed in double quotes (“) to properly handle values ​​that contain the delimiter itself or special characters.

The CSV file can easily be opened as a spreadsheet with programs such as Excel or LibreOffice Calc in order to make calculations, statistics or graphs on the collected data.

Newsletter

If you want to be informed about the release of new articles, subscribe to the newsletter. Before subscribing to the newsletter read the page Privacy Policy (UE)

If you want to unsubscribe from the newsletter, click on the link that you will find in the newsletter email.

Enter your name
Enter your email
Scroll to Top