{"id":105001,"date":"2021-07-28T14:02:58","date_gmt":"2021-07-28T14:02:58","guid":{"rendered":"https:\/\/randomnerdtutorials.com\/?p=105001"},"modified":"2021-07-28T14:08:39","modified_gmt":"2021-07-28T14:08:39","slug":"altimeter-datalogger-esp32-bmp388","status":"publish","type":"post","link":"https:\/\/randomnerdtutorials.com\/altimeter-datalogger-esp32-bmp388\/","title":{"rendered":"Altimeter Datalogger: ESP32 with BMP388, MicroSD Card Storage and OLED Display"},"content":{"rendered":"\n<p>In this project, we&#8217;ll build an altimeter datalogger with the ESP32 and the BMP388 sensor. The BMP388 is a precise pressure sensor that allows us to estimate altitude with great accuracy. In this project, the pressure and altitude are logged to a file on a microSD. We&#8217;ve also added an OLED display to this project so that you can check the current altitude by pressing a pushbutton.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" fetchpriority=\"high\" decoding=\"async\" width=\"1200\" height=\"675\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/07\/Altimeter-Datalogger-ESP32-BMP388-microSD-Card-Storage-OLED-Display.jpg?resize=1200%2C675&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Altimeter Datalogger ESP32 with BMP388 MicroSD Card Storage and OLED Display\" class=\"wp-image-105090\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/07\/Altimeter-Datalogger-ESP32-BMP388-microSD-Card-Storage-OLED-Display.jpg?w=1280&amp;quality=100&amp;strip=all&amp;ssl=1 1280w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/07\/Altimeter-Datalogger-ESP32-BMP388-microSD-Card-Storage-OLED-Display.jpg?resize=300%2C169&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/07\/Altimeter-Datalogger-ESP32-BMP388-microSD-Card-Storage-OLED-Display.jpg?resize=1024%2C576&amp;quality=100&amp;strip=all&amp;ssl=1 1024w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/07\/Altimeter-Datalogger-ESP32-BMP388-microSD-Card-Storage-OLED-Display.jpg?resize=768%2C432&amp;quality=100&amp;strip=all&amp;ssl=1 768w\" sizes=\"(max-width: 1200px) 100vw, 1200px\" \/><\/figure><\/div>\n\n\n\n<p class=\"rntbox rntclblue\">For a getting started guide for the BMP388, check the following tutorial: <a href=\"https:\/\/randomnerdtutorials.com\/esp32-bmp388-arduino\/\">ESP32 with BMP388 Barometric\/Altimeter Sensor (Arduino IDE)<\/a><\/p>\n\n\n\n<p><strong>Table of Contents:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"#project-overview\">Project Overview<\/a><\/li><li><a href=\"#parts-required\">Parts Required<\/a><\/li><li><a href=\"#prerequisites\">Prerequisites<\/a><\/li><li><a href=\"#circuit\">Schematic Diagram (circuit)<\/a><\/li><li><a href=\"#circuit\">Code and How it Works<\/a><\/li><li><a href=\"#demonstration\">Demonstration<\/a><\/li><li><a href=\"#wrap-up\">Wrapping Up<\/a><\/li><li><a href=\"#why-we-created-this-project\">Why we created this project<\/a><\/li><\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"project-overview\">Project Overview<\/h2>\n\n\n\n<p>Before going straight to the project, let&#8217;s look at the main features of this project.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" decoding=\"async\" width=\"790\" height=\"455\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/07\/ESP32-BMP388-Datalogger-Project-Overview.png?resize=790%2C455&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 BMP388 Datalogger Project Overview\" class=\"wp-image-105042\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/07\/ESP32-BMP388-Datalogger-Project-Overview.png?w=790&amp;quality=100&amp;strip=all&amp;ssl=1 790w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/07\/ESP32-BMP388-Datalogger-Project-Overview.png?resize=300%2C173&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/07\/ESP32-BMP388-Datalogger-Project-Overview.png?resize=768%2C442&amp;quality=100&amp;strip=all&amp;ssl=1 768w\" sizes=\"(max-width: 790px) 100vw, 790px\" \/><\/figure><\/div>\n\n\n\n<ul class=\"wp-block-list\"><li>The ESP32 sets an access point (<strong>1<\/strong>) that you can connect to using your smarpthone. Once connected, you can access a web page with an input field, where you can enter the current sea level pressure at your location. You must enter this value when the project starts running. The altitude is calculated comparaing the sensor&#8217;s pressure with the current sea level pressure, that&#8217;s why this step is important for accurate results. You can check the current <a href=\"https:\/\/meteologix.com\/pt\/observations\/pressure-qnh.html\" target=\"_blank\" rel=\"noreferrer noopener\" title=\"https:\/\/meteologix.com\/xx\/observations\/portugal\/pressure-qnh\/20210512-1000z.html\">sea level pressure<\/a>.<\/li><\/ul>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" decoding=\"async\" width=\"750\" height=\"309\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/07\/ESP32-Access-Point-Insert-Sea-Level-Pressure.png?resize=750%2C309&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"HTML Form ESP32 Insert Sea Level Pressure\" class=\"wp-image-105024\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/07\/ESP32-Access-Point-Insert-Sea-Level-Pressure.png?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/07\/ESP32-Access-Point-Insert-Sea-Level-Pressure.png?resize=300%2C124&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/figure><\/div>\n\n\n\n<ul class=\"wp-block-list\"><li>The ESP32 is connected to a BMP388 pressure sensor, a microSD card module, an OLED display and a pushbutton.<\/li><\/ul>\n\n\n\n<ul class=\"wp-block-list\"><li>Every minute (or other period of time you define in the code), the ESP32 records new sensor readings to a file on the microSD card (<strong>2<\/strong>). It records current seal level pressure, current pressure at the sensor&#8217;s location, temperature and altitude estimation.<\/li><\/ul>\n\n\n\n<ul class=\"wp-block-list\"><li>When you press the pushbutton, the OLED display turns on and shows the current altitude and temperature (<strong>3<\/strong>). After 5 seconds, it turns off (to save power).<\/li><\/ul>\n\n\n\n<p>To better understand how this project works, it might be helpful to take a look at the following tutorials:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"https:\/\/randomnerdtutorials.com\/esp32-bmp388-arduino\/\">ESP32 with BMP388 Barometric\/Altimeter Sensor (Arduino IDE)<\/a><\/li><li><a href=\"https:\/\/randomnerdtutorials.com\/esp32-microsd-card-arduino\/\">ESP32: Guide for MicroSD Card Module using Arduino IDE<\/a><\/li><li><a href=\"https:\/\/randomnerdtutorials.com\/esp32-ssd1306-oled-display-arduino-ide\/\">ESP32 OLED Display with Arduino IDE<\/a><\/li><li><a href=\"https:\/\/randomnerdtutorials.com\/esp32-esp8266-input-data-html-form\/\">Input Data on HTML Form ESP32\/ESP8266 Web Server using Arduino IDE<\/a><\/li><li><a href=\"https:\/\/randomnerdtutorials.com\/esp32-access-point-ap-web-server\/\">How to Set an ESP32 Access Point (AP) for Web Server<\/a><\/li><\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"parts-required\">Parts Required<\/h2>\n\n\n\n<p>To build this project, you need the following parts:<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"750\" height=\"422\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/07\/ESP32-BMP388-Sensor-Altitude-Pressure-Temperature-Arduino-Oled-SSD1306-MicroSD-Card-Demonstration.jpg?resize=750%2C422&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 BMP388 Sensor Altitude Pressure Temperature Arduino Oled SSD1306 MicroSD Card Demonstration\" class=\"wp-image-105147\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/07\/ESP32-BMP388-Sensor-Altitude-Pressure-Temperature-Arduino-Oled-SSD1306-MicroSD-Card-Demonstration.jpg?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/07\/ESP32-BMP388-Sensor-Altitude-Pressure-Temperature-Arduino-Oled-SSD1306-MicroSD-Card-Demonstration.jpg?resize=300%2C169&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/figure><\/div>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"https:\/\/makeradvisor.com\/tools\/esp32-dev-board-wi-fi-bluetooth\/\" target=\"_blank\" rel=\"noreferrer noopener\">DOIT ESP32 DEVKIT V1 Board<\/a>&nbsp;\u2013 read&nbsp;<a href=\"https:\/\/makeradvisor.com\/esp32-development-boards-review-comparison\/\" target=\"_blank\" rel=\"noreferrer noopener\">Best ESP32 Development Boards<\/a><\/li><li><a href=\"https:\/\/makeradvisor.com\/tools\/bmp388-sensor-module\/\" target=\"_blank\" rel=\"noreferrer noopener\">BMP388 sensor module<\/a> (<a href=\"https:\/\/randomnerdtutorials.com\/esp32-bmp388-arduino\/\">Guide for BMP388<\/a>)<\/li><li><a href=\"https:\/\/makeradvisor.com\/tools\/sd-card-module\/\" target=\"_blank\" rel=\"noreferrer noopener\">MicroSD card module<\/a> + microSD card<\/li><li><a href=\"https:\/\/makeradvisor.com\/tools\/pushbuttons-kit\/\" target=\"_blank\" rel=\"noreferrer noopener\">Pushbutton<\/a><\/li><li><a rel=\"noreferrer noopener\" href=\"https:\/\/makeradvisor.com\/tools\/resistors-kits\/\" target=\"_blank\">10k Ohm resistor<\/a><\/li><li><a rel=\"noreferrer noopener\" href=\"https:\/\/makeradvisor.com\/tools\/mb-102-solderless-breadboard-830-points\/\" target=\"_blank\">Breadboard<\/a><\/li><li><a rel=\"noreferrer noopener\" href=\"https:\/\/makeradvisor.com\/tools\/jumper-wires-kit-120-pieces\/\" target=\"_blank\">Jumper wires<\/a><\/li><\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"prerequisites\">Prerequisites<\/h2>\n\n\n\n<p>Before continuing, make sure you check the following prerequisites.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">1. Install ESP32 Board in Arduino IDE<\/h3>\n\n\n\n<p>We&#8217;ll program the ESP32 using Arduino IDE. So, you must have the ESP32 add-on installed. Follow the next tutorial if you haven&#8217;t already:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"https:\/\/randomnerdtutorials.com\/installing-the-esp32-board-in-arduino-ide-windows-instructions\/\">Installing ESP32 Board in Arduino IDE (Windows, Mac OS X, Linux)<\/a><\/li><\/ul>\n\n\n\n<p>If you want to use VS Code with the PlatformIO extension, follow the next tutorial instead to learn how to program the ESP32:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"https:\/\/randomnerdtutorials.com\/vs-code-platformio-ide-esp32-esp8266-arduino\/\">Getting Started with VS Code and PlatformIO IDE for ESP32 and ESP8266 (Windows, Mac OS X, Linux Ubuntu)<\/a><\/li><\/ul>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"block-cb8ad99c-51d7-4be8-8b73-0e6ed7590672\">2. Installing Libraries<\/h3>\n\n\n\n<p id=\"block-c77756ee-9fdf-4060-aadd-c71e205dc9ac\">To build this project, you need to install the following libraries:<\/p>\n\n\n\n<ul class=\"wp-block-list\" id=\"block-a7af30fd-b1cd-47a2-9dc0-3cf5fb8d5886\"><li><a href=\"https:\/\/github.com\/adafruit\/Adafruit_BMP3XX\" target=\"_blank\" rel=\"noreferrer noopener\">Adafruit BMP3XX library<\/a> (Arduino Library Manager)<\/li><li><a rel=\"noreferrer noopener\" href=\"https:\/\/github.com\/adafruit\/Adafruit_Sensor\" target=\"_blank\">Adafruit_Sensor library<\/a> (Arduino Library Manager)<\/li><li><a rel=\"noreferrer noopener\" href=\"https:\/\/github.com\/adafruit\/Adafruit_SSD1306\" target=\"_blank\">Adafruit_SSD1306 library<\/a> (Arduino Library Manager)<\/li><li><a rel=\"noreferrer noopener\" href=\"https:\/\/github.com\/adafruit\/Adafruit-GFX-Library\" target=\"_blank\">Adafruit_GFX library<\/a> (Arduino Library Manager)<\/li><li><a style=\"font-size: inherit;\" href=\"https:\/\/github.com\/me-no-dev\/ESPAsyncWebServer\" target=\"_blank\" rel=\"noreferrer noopener\">ESPAsyncWebServer<\/a><span style=\"font-size: inherit;\">&nbsp;(.zip folder);<\/span><\/li><li><a href=\"https:\/\/github.com\/me-no-dev\/AsyncTCP\" target=\"_blank\" rel=\"noreferrer noopener\">AsyncTCP<\/a>&nbsp;(.zip folder).<\/li><\/ul>\n\n\n\n<p id=\"block-ff352e7d-a8f9-4463-b910-bba6133ddd9a\">You can install the first four libraries using the Arduino Library Manager. Go to&nbsp;<strong>Sketch&nbsp;<\/strong>&gt;&nbsp;<strong>Include Library<\/strong>&nbsp;&gt;&nbsp;<strong>Manage Libraries<\/strong>&nbsp;and search for the library name.<\/p>\n\n\n\n<p id=\"block-dec05128-9131-4046-af2e-eb8b927deddd\">The ESPAsyncWebServer and AsynTCP libraries aren\u2019t available to install through the Arduino Library Manager, so you need to copy the library files to the Arduino Installation Libraries folder. Alternatively, in your Arduino IDE, you can go to&nbsp;<strong>Sketch&nbsp;<\/strong>&gt;&nbsp;<strong>Include Library<\/strong>&nbsp;&gt;&nbsp;<strong>Add .zip Library<\/strong>&nbsp;and select the libraries you\u2019ve just downloaded.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"block-a46f6bd9-377f-4e05-8393-1f1da294e7f3\">Installing Libraries (VS Code + PlatformIO)<\/h3>\n\n\n\n<p>If you\u2019re programming the ESP32 using PlatformIO, you should add the following lines to the <span class=\"rnthl rntliteral\">platformio.ini<\/span> file to include the libraries (also change the Serial Monitor speed to 115200):<\/p>\n\n\n\n<pre id=\"block-f0ab925d-77b2-4f1d-8f56-9361c8deafd6\" class=\"wp-block-code\"><code>monitor_speed = 115200\nlib_deps = ESP Async WebServer\n\tadafruit\/Adafruit SSD1306@^2.4.6\n\tadafruit\/Adafruit GFX Library@^1.10.10\n\tadafruit\/Adafruit BMP3XX Library@^2.1.0<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">3. Formatting the MicroSD Card<\/h3>\n\n\n\n<p>Before proceeding with the tutorial, make sure you <strong>format your microSD card as FAT32<\/strong>. Follow the next instructions to format your microSD card or use a software tool like <a href=\"https:\/\/www.sdcard.org\/downloads\/formatter\/\" target=\"_blank\" rel=\"noreferrer noopener\">SD Card Formater<\/a> (compatible with Windows and Mac OS).<\/p>\n\n\n\n<p><strong>1.<\/strong>&nbsp;Insert the microSD card into your computer. Go to&nbsp;<strong>My Computer<\/strong>&nbsp;and right-click on the SD card. Select&nbsp;<strong>Format&nbsp;<\/strong>as shown in the figure below.<\/p>\n\n\n\n<div class=\"wp-block-image is-style-default\"><figure class=\"aligncenter\"><img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/rntlab.com\/wp-content\/uploads\/2018\/05\/format-SD-card-1.png?w=1200&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"MicroSD Card Module format sd card\" class=\"wp-image-11805\"\/><\/figure><\/div>\n\n\n\n<p><strong>2.&nbsp;<\/strong>A new window pops up. Select&nbsp;<strong>FAT32<\/strong>, press&nbsp;<strong>Start<\/strong>&nbsp;to initialize the formatting process, and follow the onscreen instructions.<\/p>\n\n\n\n<div class=\"wp-block-image is-style-default\"><figure class=\"aligncenter\"><img data-recalc-dims=\"1\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/rntlab.com\/wp-content\/uploads\/2018\/05\/format-SD-card-2.png?w=1200&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"MicroSD Card Module format sd card\" class=\"wp-image-11806\"\/><\/figure><\/div>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"circuit\">Schematic Diagram<\/h2>\n\n\n\n<p>Connect all the components as shown in the following schematic diagram.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"750\" height=\"642\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/07\/ESP32-BMP388-Datalogger-OLED-Pushbutton.png?resize=750%2C642&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 BMP388 Datalogger OLED Pushbutton Wiring Circuit Diagram\" class=\"wp-image-105040\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/07\/ESP32-BMP388-Datalogger-OLED-Pushbutton.png?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/07\/ESP32-BMP388-Datalogger-OLED-Pushbutton.png?resize=300%2C257&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/figure><\/div>\n\n\n\n<p>You can also check the wiring in the following table:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><tbody><tr><td><strong>Component<\/strong><\/td><td><strong>ESP32 Pin Assignment<\/strong><\/td><\/tr><tr><td>BMP388<\/td><td>GPIO 21 (SDA), GPIO 22 (SCL)<\/td><\/tr><tr><td>OLED Display<\/td><td>GPIO 21 (SDA), GPIO 22 (SCL)<\/td><\/tr><tr><td>MicroSD card Module<\/td><td>GPIO 5 (CS), GPIO 23 (MOSI), GPIO 18 (CLK), GPIO 19 (MISO)<\/td><\/tr><tr><td>Pushbutton<\/td><td>GPIO 4<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"code\">Code<\/h2>\n\n\n\n<p>Copy the following code to your ESP32 board, and the project will work straight away.<\/p>\n\n\n<pre style=\"max-height: 40em; margin-bottom: 20px;\"><code class=\"language-c\">\/*\n  Rui Santos &amp; Sara Santos - Random Nerd Tutorials\n  Complete project details at https:\/\/RandomNerdTutorials.com\/altimeter-datalogger-esp32-bmp388\/\n  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files.\n  The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n*\/\n\n#include &lt;Arduino.h&gt;\n#include &lt;Wire.h&gt;\n#include &lt;Adafruit_GFX.h&gt;\n#include &lt;Adafruit_SSD1306.h&gt;\n#include &lt;Adafruit_Sensor.h&gt;\n#include &quot;Adafruit_BMP3XX.h&quot;\n#include &lt;WiFi.h&gt;\n#include &lt;AsyncTCP.h&gt;\n#include &lt;ESPAsyncWebServer.h&gt;\n\n\/\/Libraries for microSD card\n#include &quot;FS.h&quot;\n#include &quot;SD.h&quot;\n#include &quot;SPI.h&quot;\n\nAsyncWebServer server(80);\n\n\/\/ Replace with your network credentials\nconst char* ssid     = &quot;ESP32&quot;;\nconst char* password = NULL;\n\n\/\/OLED Display\n#define SCREEN_WIDTH 128 \/\/ OLED display width, in pixels\n#define SCREEN_HEIGHT 64 \/\/ OLED display height, in pixels\n\nAdafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &amp;Wire, -1);\n\n\/\/ Variables for BMP388\nfloat seaLevelPressure = 1013.25;\nAdafruit_BMP3XX bmp;\nfloat alt;\nfloat temp;\nfloat pres;\nString dataMessage;\n\n\/\/Pushbutton\nconst int buttonPin = 4; \nint buttonState;              \nint lastButtonState = LOW;    \nunsigned long lastDebounceTime = 0;\nunsigned long debounceDelay = 50;    \/\/ the debounce time; increase if the output flickers   \n\n\/\/Timers for datalogging\nunsigned long lastTimer = 0;\nunsigned long timerDelay = 18000;\n\nconst char* PARAM_INPUT_1 = &quot;seaLevelPressure&quot;;\n\n\/\/ HTML web page to handle 1 input field\nconst char index_html[] PROGMEM = R&quot;rawliteral(\n&lt;!DOCTYPE HTML&gt;&lt;html&gt;&lt;head&gt;\n  &lt;title&gt;Sea Level Pressure&lt;\/title&gt;\n  &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1&quot;&gt;\n  &lt;\/head&gt;&lt;body&gt;\n  &lt;form action=&quot;\/get&quot;&gt;\n    Sea Level Pressure: &lt;input type=&quot;float&quot; name=&quot;seaLevelPressure&quot;&gt;\n    &lt;input type=&quot;submit&quot; value=&quot;Submit&quot;&gt;\n  &lt;\/form&gt;\n&lt;\/body&gt;&lt;\/html&gt;)rawliteral&quot;;\n\nvoid initBMP(){\n  if (!bmp.begin_I2C()) {   \/\/ hardware I2C mode, can pass in address &amp; alt Wire\n  \/\/if (! bmp.begin_SPI(BMP_CS)) {  \/\/ hardware SPI mode  \n  \/\/if (! bmp.begin_SPI(BMP_CS, BMP_SCK, BMP_MISO, BMP_MOSI)) {  \/\/ software SPI mode\n    Serial.println(&quot;Could not find a valid BMP3 sensor, check wiring!&quot;);\n    while (1);\n  }\n\n  \/\/ Set up oversampling and filter initialization\n  bmp.setTemperatureOversampling(BMP3_OVERSAMPLING_8X);\n  bmp.setPressureOversampling(BMP3_OVERSAMPLING_4X);\n  bmp.setIIRFilterCoeff(BMP3_IIR_FILTER_COEFF_3);\n  bmp.setOutputDataRate(BMP3_ODR_50_HZ);\n}\n\nvoid getReadings(){\n  if (! bmp.performReading()) {\n    Serial.println(&quot;Failed to perform reading :(&quot;);\n    return;\n  }\n  temp = bmp.temperature;\n  pres = bmp.pressure \/ 100.0;\n  alt = bmp.readAltitude(seaLevelPressure);\n}\n\nvoid initDisplay(){\n  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {\n    Serial.println(F(&quot;SSD1306 allocation failed&quot;));\n    for(;;);\n  }\n  delay(500);\n  display.clearDisplay();\n  display.setTextColor(WHITE); \n}\n\nvoid displayReadings(){\n  display.clearDisplay();\n  \/\/ display temperature\n  display.setTextSize(1);\n  display.setCursor(0,0);\n  display.print(&quot;Temperature: &quot;);\n  display.setTextSize(2);\n  display.setCursor(0,10);\n  display.print(String(temp));\n  display.print(&quot; &quot;);\n  display.setTextSize(1);\n  display.cp437(true);\n  display.write(167);\n  display.setTextSize(2);\n  display.print(&quot;C&quot;);\n  \/\/ display altitude\n  display.setTextSize(1);\n  display.setCursor(0, 35);\n  display.print(&quot;Altitude: &quot;);\n  display.setTextSize(2);\n  display.setCursor(0, 45);\n  display.print(String(alt));\n  display.print(&quot; m&quot;); \n  display.display();\n}\n\n\/\/ Initialize SD card\nvoid initSDCard(){\n   if (!SD.begin()) {\n    Serial.println(&quot;Card Mount Failed&quot;);\n    return;\n  }\n}\n\n\/\/ Write to the SD card\nvoid writeFile(fs::FS &amp;fs, const char * path, const char * message) {\n  Serial.printf(&quot;Writing file: %s\\n&quot;, path);\n\n  File file = fs.open(path, FILE_WRITE);\n  if(!file) {\n    Serial.println(&quot;Failed to open file for writing&quot;);\n    return;\n  }\n  if(file.print(message)) {\n    Serial.println(&quot;File written&quot;);\n  } else {\n    Serial.println(&quot;Write failed&quot;);\n  }\n  file.close();\n}\n\n\/\/ Append data to the SD card\nvoid appendFile(fs::FS &amp;fs, const char * path, const char * message) {\n  Serial.printf(&quot;Appending to file: %s\\n&quot;, path);\n\n  File file = fs.open(path, FILE_APPEND);\n  if(!file) {\n    Serial.println(&quot;Failed to open file for appending&quot;);\n    return;\n  }\n  if(file.print(message)) {\n    Serial.println(&quot;Message appended&quot;);\n  } else {\n    Serial.println(&quot;Append failed&quot;);\n  }\n  file.close();\n}\n\n\/\/ Initialize WiFi\nvoid initWiFi() {\n  WiFi.softAP(ssid, password);\n  IPAddress IP = WiFi.softAPIP();\n  Serial.print(&quot;AP IP address: &quot;);\n  Serial.println(IP);\n}\n\nvoid setup() {\n  Serial.begin(115200);\n  initBMP();\n  initDisplay();\n  initSDCard();\n  initWiFi();\n  pinMode(buttonPin, INPUT);\n\n  File file = SD.open(&quot;\/data.txt&quot;);\n  if(!file) {\n    Serial.println(&quot;File doesn't exist&quot;);\n    Serial.println(&quot;Creating file...&quot;);\n    writeFile(SD, &quot;\/data.txt&quot;, &quot;Pressure, Altitude, Temperature \\r\\n&quot;);\n  }\n  else {\n    Serial.println(&quot;File already exists&quot;);  \n  }\n  file.close();\n\n  \/\/ Send web page with input fields to client\n  server.on(&quot;\/&quot;, HTTP_GET, [](AsyncWebServerRequest *request){\n    request-&gt;send(200, &quot;text\/html&quot;, index_html);\n  });\n\n  \/\/ Send a GET request to &lt;ESP_IP&gt;\/get?input1=&lt;inputMessage&gt;\n  server.on(&quot;\/get&quot;, HTTP_GET, [] (AsyncWebServerRequest *request) {\n    String inputMessage;\n    \/\/ GET input1 value on &lt;ESP_IP&gt;\/get?input1=&lt;inputMessage&gt;\n    if (request-&gt;hasParam(PARAM_INPUT_1)) {\n      inputMessage = request-&gt;getParam(PARAM_INPUT_1)-&gt;value();\n      seaLevelPressure = inputMessage.toFloat();\n    }\n    else {\n      inputMessage = &quot;No message sent&quot;;\n    }\n    Serial.println(inputMessage);\n    request-&gt;send(200, &quot;text\/html&quot;, &quot;HTTP GET request sent to your ESP on input field with value: &quot; + inputMessage +\n                                     &quot;&lt;br&gt;&lt;a href=\\&quot;\/\\&quot;&gt;Return to Home Page&lt;\/a&gt;&quot;);\n  });\n  server.begin();\n\n}\nvoid loop() {\n  int reading = digitalRead(buttonPin);\n  display.clearDisplay();\n\n  \/\/ Light up when the pushbutton is pressed\n  if (reading != lastButtonState) {\n    lastDebounceTime = millis();\n  }\n  if ((millis() - lastDebounceTime) &gt; debounceDelay) {\n    if (reading != buttonState) {\n      buttonState = reading;\n      if (buttonState == HIGH) {\n        getReadings();\n        displayReadings();\n        delay(5000);\n        display.clearDisplay();\n        display.display();\n        lastDebounceTime = millis();\n      }\n    }\n  }\n  lastButtonState = reading;\n\n  \/\/ Log data every timerDelay seconds\n  if ((millis() - lastTimer) &gt; timerDelay) {\n    \/\/Concatenate all info separated by commas\n    getReadings();\n    dataMessage = String(pres) + &quot;,&quot; + String(alt) + &quot;,&quot; + String(temp)+ &quot;,&quot; + String(seaLevelPressure) + &quot;\\r\\n&quot;;\n    Serial.print(dataMessage);\n    \/\/Append the data to file\n    appendFile(SD, &quot;\/data.txt&quot;, dataMessage.c_str());\n    lastTimer = millis();\n  }\n}\n<\/code><\/pre>\n\t<p style=\"text-align:center\"><a class=\"rntwhite\" href=\"https:\/\/github.com\/RuiSantosdotme\/Random-Nerd-Tutorials\/raw\/master\/Projects\/ESP32\/BMP388\/ESP32_BMP388_Datalogger.ino\" target=\"_blank\">View raw code<\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">How the Code Works<\/h2>\n\n\n\n<p>Continue reading to learn how the code works, or skip to the <a href=\"#demonstration\">demonstration section<\/a>.<\/p>\n\n\n\n<p>Start by including all the necessary libraries:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>#include &lt;Arduino.h&gt;\n#include &lt;Wire.h&gt;\n#include &lt;Adafruit_GFX.h&gt;\n#include &lt;Adafruit_SSD1306.h&gt;\n#include &lt;Adafruit_Sensor.h&gt;\n#include \"Adafruit_BMP3XX.h\"\n#include &lt;WiFi.h&gt;\n#include &lt;AsyncTCP.h&gt;\n#include &lt;ESPAsyncWebServer.h&gt;\n\/\/Libraries for microSD card\n#include \"FS.h\"\n#include \"SD.h\"\n#include \"SPI.h\"<\/code><\/pre>\n\n\n\n<p>The following lines set the name and password for the access point. In this case, we set the password to <span class=\"rnthl rntliteral\">NULL<\/span>\u2014this creates an open access point. You can add a password for the access point if you want.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/ Replace with your network credentials\nconst char* ssid     = \"ESP32\";\nconst char* password = NULL;<\/code><\/pre>\n\n\n\n<p>Set the OLED display size and instantiate an instance on the default I2C pins.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/ OLED Display\n#define SCREEN_WIDTH 128 \/\/ OLED display width, in pixels\n#define SCREEN_HEIGHT 64 \/\/ OLED display height, in pixels\n\nAdafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &amp;Wire, -1);<\/code><\/pre>\n\n\n\n<p>We set the default sea level pressure as 1013.25 hPa. However, you should connect to the access point to change this value for more accurate results.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>float seaLevelPressure = 1013.25;<\/code><\/pre>\n\n\n\n<p>Create an instance for the BMP388 sensor called <span class=\"rnthl rntliteral\">bmp<\/span>\u2014this automatically uses the default I2C pins.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>Adafruit_BMP3XX bmp;<\/code><\/pre>\n\n\n\n<p>The following variables will be used to save the sensor data.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>float alt;\nfloat temp;\nfloat pres;\nString dataMessage;<\/code><\/pre>\n\n\n\n<p>The pushbutton is connected to GPIO 4.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>const int buttonPin = 4; <\/code><\/pre>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">buttonState<\/span> and <span class=\"rnthl rntliteral\">lastButtonState<\/span> variables save the current button state and the last button state.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>int buttonState;              \nint lastButtonState = LOW; <\/code><\/pre>\n\n\n\n<p>The next variables are used to debounce the pushbutton.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>unsigned long lastDebounceTime = 0;\nunsigned long debounceDelay = 50;    \/\/ the debounce time; increase if the output flickers <\/code><\/pre>\n\n\n\n<p>The BMP388 readings are saved every minute. You can change that in the <span class=\"rnthl rntliteral\">timerDelay<\/span> variable (in milliseconds).<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/Timers for datalogging\nunsigned long lastTimer = 0;\nunsigned long timerDelay = 60000;<\/code><\/pre>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">PARAM_INPUT_1<\/span> variable will be used to search for the input value on the HTML form. To learn more about HTML forms with the ESP32, <a href=\"https:\/\/randomnerdtutorials.com\/esp32-esp8266-input-data-html-form\/\">we recommend this tutorial<\/a>.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>const char* PARAM_INPUT_1 = \"seaLevelPressure\";<\/code><\/pre>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">index_html<\/span> variable saves a simple HTML page that displays an input field to enter the current sea level pressure.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/ HTML web page to handle 1 input field\nconst char index_html&#091;] PROGMEM = R\"rawliteral(\n&lt;!DOCTYPE HTML&gt;&lt;html&gt;&lt;head&gt;\n  &lt;title&gt;Sea Level Pressure&lt;\/title&gt;\n  &lt;meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"&gt;\n  &lt;\/head&gt;&lt;body&gt;\n  &lt;form action=\"\/get\"&gt;\n    Sea Level Pressure: &lt;input type=\"float\" name=\"seaLevelPressure\"&gt;\n    &lt;input type=\"submit\" value=\"Submit\"&gt;\n  &lt;\/form&gt;\n&lt;\/body&gt;&lt;\/html&gt;)rawliteral\";<\/code><\/pre>\n\n\n\n<p>When you submit a new pressure value, the ESP32 receives a request on the following URL (for example, pressure = 1022):<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/get?seaLevelPressure=1022<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Initialize BMP388<\/h3>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">initBMP()<\/span> function initializes the BMP388 sensor. Read the <a href=\"https:\/\/randomnerdtutorials.com\/esp32-bmp388-arduino\/\">ESP32 with the BMP388 tutorial<\/a> to learn more.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>void initBMP(){\n  if (!bmp.begin_I2C()) {   \/\/ hardware I2C mode, can pass in address &amp; alt Wire\n  \/\/if (! bmp.begin_SPI(BMP_CS)) {  \/\/ hardware SPI mode  \n  \/\/if (! bmp.begin_SPI(BMP_CS, BMP_SCK, BMP_MISO, BMP_MOSI)) {  \/\/ software SPI mode\n    Serial.println(\"Could not find a valid BMP3 sensor, check wiring!\");\n    while (1);\n  }\n\n  \/\/ Set up oversampling and filter initialization\n  bmp.setTemperatureOversampling(BMP3_OVERSAMPLING_8X);\n  bmp.setPressureOversampling(BMP3_OVERSAMPLING_4X);\n  bmp.setIIRFilterCoeff(BMP3_IIR_FILTER_COEFF_3);\n  bmp.setOutputDataRate(BMP3_ODR_50_HZ);\n}<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Get BMP388 Readings<\/h3>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">getReadings()<\/span> function gets new readings: temperature, pressure, and altitude and saves them on the <span class=\"rnthl rntliteral\">temp<\/span>, <span class=\"rnthl rntliteral\">pres<\/span>, and <span class=\"rnthl rntliteral\">alt<\/span> variables.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>void getReadings(){\n  if (! bmp.performReading()) {\n    Serial.println(\"Failed to perform reading :(\");\n    return;\n  }\n  temp = bmp.temperature;\n  pres = bmp.pressure \/ 100.0;\n  alt = bmp.readAltitude(seaLevelPressure);\n}<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Initialize OLED Display<\/h3>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">initDisplay()<\/span> function initializes the OLED display.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>void initDisplay(){\n  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {\n    Serial.println(F(\"SSD1306 allocation failed\"));\n    for(;;);\n  }\n  delay(500);\n  display.clearDisplay();\n  display.setTextColor(WHITE); \n}<\/code><\/pre>\n\n\n\n<p>To learn more about the OLED display with the ESP32, read <a href=\"https:\/\/randomnerdtutorials.com\/esp32-ssd1306-oled-display-arduino-ide\/\">ESP32 OLED Display with Arduino IDE<\/a>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Display BMP388 Readings<\/h3>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">displayReadings()<\/span> function displays the temperature and altitude on the display.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>void displayReadings(){\n  display.clearDisplay();\n  \/\/ display temperature\n  display.setTextSize(1);\n  display.setCursor(0,0);\n  display.print(\"Temperature: \");\n  display.setTextSize(2);\n  display.setCursor(0,10);\n  display.print(String(temp));\n  display.print(\" \");\n  display.setTextSize(1);\n  display.cp437(true);\n  display.write(167);\n  display.setTextSize(2);\n  display.print(\"C\");\n  \/\/ display altitude\n  display.setTextSize(1);\n  display.setCursor(0, 35);\n  display.print(\"Altitude: \");\n  display.setTextSize(2);\n  display.setCursor(0, 45);\n  display.print(String(alt));\n  display.print(\" m\"); \n  display.display();\n}<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Initialize microSD card<\/h3>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">initSDCard()<\/span> function initializes the microSD card on the default SPI pins.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/ Initialize SD card\nvoid initSDCard(){\n   if (!SD.begin()) {\n    Serial.println(\"Card Mount Failed\");\n    return;\n  }\n}<\/code><\/pre>\n\n\n\n<p>If you want to use other pins, read <a href=\"https:\/\/randomnerdtutorials.com\/esp32-microsd-card-arduino\/#sdcardcustompins\">this article to learn how to set custom SPI pins<\/a>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Write to the microSD card<\/h3>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">writeFile()<\/span> and <span class=\"rnthl rntliteral\">appendFile()<\/span> functions write and append a message to a file on the microSD card.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/ Write to the SD card\nvoid writeFile(fs::FS &amp;fs, const char * path, const char * message) {\n  Serial.printf(\"Writing file: %s\\n\", path);\n\n  File file = fs.open(path, FILE_WRITE);\n  if(!file) {\n    Serial.println(\"Failed to open file for writing\");\n    return;\n  }\n  if(file.print(message)) {\n    Serial.println(\"File written\");\n  } else {\n    Serial.println(\"Write failed\");\n  }\n  file.close();\n}\n\n\/\/ Append data to the SD card\nvoid appendFile(fs::FS &amp;fs, const char * path, const char * message) {\n  Serial.printf(\"Appending to file: %s\\n\", path);\n\n  File file = fs.open(path, FILE_APPEND);\n  if(!file) {\n    Serial.println(\"Failed to open file for appending\");\n    return;\n  }\n  if(file.print(message)) {\n    Serial.println(\"Message appended\");\n  } else {\n    Serial.println(\"Append failed\");\n  }\n  file.close();\n}<\/code><\/pre>\n\n\n\n<p>To learn more about microSD card functions, read <a href=\"https:\/\/randomnerdtutorials.com\/esp32-microsd-card-arduino\/\">ESP32: Guide for MicroSD Card Module using Arduino IDE<\/a>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Set Access Point<\/h3>\n\n\n\n<p>Initialize Wi-Fi by setting the ESP32 as an access point.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/ Initialize WiFi\nvoid initWiFi() {\n  WiFi.softAP(ssid, password);\n  IPAddress IP = WiFi.softAPIP();\n  Serial.print(\"AP IP address: \");\n  Serial.println(IP);\n}<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">setup()<\/h3>\n\n\n\n<p>In the <span class=\"rnthl rntliteral\">setup()<\/span>, initialize the Serial Monitor, the BMP388 sensor, the OLED display, the microSD card, start the access point and define the pushbutton as an <span class=\"rnthl rntliteral\">INPUT<\/span>.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>Serial.begin(115200);\ninitBMP();\ninitDisplay();\ninitSDCard();\ninitWiFi();\npinMode(buttonPin, INPUT);<\/code><\/pre>\n\n\n\n<p>Create a new file on the microSD card called <span class=\"rnthl rntliteral\">data.txt<\/span> if it doesn&#8217;t exist already.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>File file = SD.open(\"\/data.txt\");\nif(!file) {\n  Serial.println(\"File doesn't exist\");\n  Serial.println(\"Creating file...\");\n  writeFile(SD, \"\/data.txt\", \"Pressure, Altitude, Temperature \\r\\n\");\n}\nelse {\n  Serial.println(\"File already exists\");  \n}\nfile.close();<\/code><\/pre>\n\n\n\n<p>When you access the Access Point on the root (<span class=\"rnthl rntliteral\">\/<\/span>) URL, the server (ESP32) sends the HTML page (<span class=\"rnthl rntliteral\">index_html<\/span> variable) with the form.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/ Send web page with input fields to client\nserver.on(\"\/\", HTTP_GET, &#091;](AsyncWebServerRequest *request){\n  request-&gt;send_P(200, \"text\/html\", index_html);\n});<\/code><\/pre>\n\n\n\n<p>The following part gets the input field you&#8217;ve inserted in the form and saves it in the <span class=\"rnthl rntliteral\">seaLevelPressure<\/span> variable.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/ Send web page with input fields to client\nserver.on(\"\/\", HTTP_GET, &#091;](AsyncWebServerRequest *request){\n  request-&gt;send_P(200, \"text\/html\", index_html);\n});\n\n\/\/ Send a GET request to &lt;ESP_IP&gt;\/get?input1=&lt;inputMessage&gt;\nserver.on(\"\/get\", HTTP_GET, &#091;] (AsyncWebServerRequest *request) {\n  String inputMessage;\n  \/\/ GET input1 value on &lt;ESP_IP&gt;\/get?input1=&lt;inputMessage&gt;\n  if (request-&gt;hasParam(PARAM_INPUT_1)) {\n    inputMessage = request-&gt;getParam(PARAM_INPUT_1)-&gt;value();\n    seaLevelPressure = inputMessage.toFloat();\n  }\n  else {\n    inputMessage = \"No message sent\";\n  }\n  Serial.println(inputMessage);\n  request-&gt;send(200, \"text\/html\", \"HTTP GET request sent to your ESP on input field with value: \" + inputMessage +\n                                     \"&lt;br&gt;&lt;a href=\\\"\/\\\"&gt;Return to Home Page&lt;\/a&gt;\");\n});<\/code><\/pre>\n\n\n\n<p>To learn more about how this works, read: <a href=\"https:\/\/randomnerdtutorials.com\/esp32-esp8266-input-data-html-form\/\">Input Data on HTML Form ESP32\/ESP8266 Web Server using Arduino IDE<\/a>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">loop()<\/h3>\n\n\n\n<p>In the <span class=\"rnthl rntliteral\">loop()<\/span> is where we check the state of the pushbutton. If it was pressed, we light up the OLED display with the current temperature and altitude readings.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>int reading = digitalRead(buttonPin);\ndisplay.clearDisplay();\n\n\/\/ Light up when the pushbutton is pressed\nif (reading != lastButtonState) {\n  lastDebounceTime = millis();\n}\nif ((millis() - lastDebounceTime) &gt; debounceDelay) {\n  if (reading != buttonState) {\n    buttonState = reading;\n    if (buttonState == HIGH) {\n      getReadings();\n      displayReadings();\n      delay(5000);\n      display.clearDisplay();\n      display.display();\n      lastDebounceTime = millis();\n    }\n  }\n}\nlastButtonState = reading;<\/code><\/pre>\n\n\n\n<p>We also save new readings every 60 seconds (<span class=\"rnthl rntliteral\">timerDelay<\/span>) variable.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>if ((millis() - lastTimer) &gt; timerDelay) {\n  \/\/Concatenate all info separated by commas\n  getReadings();\n  dataMessage = String(pres) + \",\" + String(alt) + \",\" + String(temp)+ \",\" + String(seaLevelPressure) + \"\\r\\n\";\n  Serial.print(dataMessage);\n  \/\/Append the data to file\n  appendFile(SD, \"\/data.txt\", dataMessage.c_str());\n  lastTimer = millis();\n}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"demonstration\">Demonstration<\/h2>\n\n\n\n<p>Upload the code to your board. Don&#8217;t forget to select the right board (ESP32) and COM port.<\/p>\n\n\n\n<p>After uploading, you should get the following messages on the Serial Monitor*.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"750\" height=\"560\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/07\/BMP388-ESP32-Altitmeter-Datalogger-Serial-Monitor.png?resize=750%2C560&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 BMP388 Altimeter Datalogger Serial Monitor Demonstration\" class=\"wp-image-105097\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/07\/BMP388-ESP32-Altitmeter-Datalogger-Serial-Monitor.png?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/07\/BMP388-ESP32-Altitmeter-Datalogger-Serial-Monitor.png?resize=300%2C224&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/figure><\/div>\n\n\n\n<p>*In my case, it shows &#8220;File already exists&#8221;. But, when you&#8217;re running it for the first time, it should show &#8220;File doesn&#8217;t exist&#8221;, &#8220;Creating file &#8230;&#8221;.<\/p>\n\n\n\n<p>After a few seconds, it will display the first readings.<\/p>\n\n\n\n<p>After that, if you want to get more accurate altitude readings, on your computer or smartphone, connect to the ESP32 access point. Open a browser and go to the 192.168.4.1 IP address and insert the current sea level pressure at your location.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" decoding=\"async\" width=\"750\" height=\"309\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/07\/ESP32-Access-Point-Insert-Sea-Level-Pressure.png?resize=750%2C309&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"HTML Form ESP32 Insert Sea Level Pressure\" class=\"wp-image-105024\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/07\/ESP32-Access-Point-Insert-Sea-Level-Pressure.png?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/07\/ESP32-Access-Point-Insert-Sea-Level-Pressure.png?resize=300%2C124&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/figure><\/div>\n\n\n\n<p>After you&#8217;ve clicked the submit button, you&#8217;ll see the inserted value on the Serial Monitor.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"780\" height=\"582\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/07\/Ser-sea-level-pressure-ESP32-BMP388-Altimeter-Datalogger.png?resize=780%2C582&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 BMP388 Altimeter Datalogger Serial Monitor Demonstration New value for sea level pressure\" class=\"wp-image-105098\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/07\/Ser-sea-level-pressure-ESP32-BMP388-Altimeter-Datalogger.png?w=780&amp;quality=100&amp;strip=all&amp;ssl=1 780w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/07\/Ser-sea-level-pressure-ESP32-BMP388-Altimeter-Datalogger.png?resize=300%2C224&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/07\/Ser-sea-level-pressure-ESP32-BMP388-Altimeter-Datalogger.png?resize=768%2C573&amp;quality=100&amp;strip=all&amp;ssl=1 768w\" sizes=\"(max-width: 780px) 100vw, 780px\" \/><\/figure><\/div>\n\n\n\n<p>If you click on the pushbutton, you can check the current temperature and altitude on the OLED display.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"750\" height=\"422\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/07\/ESP32-BMP388-Sensor-Altitude-Pressure-Temperature-Arduino-Oled-SSD1306-MicroSD-Card-Parts-Required.jpg?resize=750%2C422&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 BMP388 Sensor Altitude Pressure Temperature Arduino Oled SSD1306 MicroSD Card Parts Required\" class=\"wp-image-105148\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/07\/ESP32-BMP388-Sensor-Altitude-Pressure-Temperature-Arduino-Oled-SSD1306-MicroSD-Card-Parts-Required.jpg?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/07\/ESP32-BMP388-Sensor-Altitude-Pressure-Temperature-Arduino-Oled-SSD1306-MicroSD-Card-Parts-Required.jpg?resize=300%2C169&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/figure><\/div>\n\n\n\n<p>If you want to check all the readings, you just need to connect the microSD card to your computer, and you can access the <span class=\"rnthl rntliteral\">data.txt<\/span> file with all the records. To analyze your data, you can use Google Sheets, Excel, or other software.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"wrap-up\">Wrapping Up<\/h2>\n\n\n\n<p>This project showed you how to log data to a microSD card using the ESP32 and how to get altitude using the BMP388 pressure sensor. You also learned how to create an access point where you can enter data that the ESP32 will use\u2014like the sea level pressure.<\/p>\n\n\n\n<p>We have a similar project using a temperature sensor (it connects to an NTP server to timestamp the readings, so the ESP32 needs to have access to the internet):<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"https:\/\/randomnerdtutorials.com\/esp32-data-logging-temperature-to-microsd-card\/\">ESP32 Data Logging Temperature to MicroSD Card<\/a><\/li><\/ul>\n\n\n\n<p>Learn more about the ESP32 with our resources:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><strong><a href=\"https:\/\/randomnerdtutorials.com\/learn-esp32-with-arduino-ide\/\">Learn ESP32 with Arduino IDE (eBook + video course)<\/a><\/strong><\/li><li><a href=\"https:\/\/randomnerdtutorials.com\/build-web-servers-esp32-esp8266-ebook\/\">Build Web Servers with ESP32 and ESP8266 eBook (2nd Edition)<\/a><\/li><li><a href=\"https:\/\/randomnerdtutorials.com\/projects-esp32\/\">More ESP32 Projects and Tutorials \u2026<\/a><\/li><\/ul>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"why-we-created-this-project\">Why we created this project?<\/h3>\n\n\n\n<p>Some curiosities about this project for those of you that like to know a little more about us. A few weeks ago, we visited Pico Island, a Portuguese island in the Azores archipelago. The landscape features a volcano, Ponta do Pico, the highest mountain in Portugal, and the Mid-Atlantic Ridge&#8217;s highest elevation with 2351 meters. <\/p>\n\n\n\n<p>One of the highlights of visiting Pico Island is climbing\/hiking the mountain to the highest point. We decided that this trip would be a good opportunity to test the BMP388 sensor at varying altitudes\u2014so, we created this datalogging project.<\/p>\n\n\n\n<div class=\"wp-block-columns is-layout-flex wp-container-core-columns-is-layout-9d6595d7 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\" style=\"flex-basis:100%\">\n<div class=\"wp-block-jetpack-tiled-gallery aligncenter is-style-rectangular\"><div class=\"tiled-gallery__gallery\"><div class=\"tiled-gallery__row\"><div class=\"tiled-gallery__col\" style=\"flex-basis:26.48397%\"><figure class=\"tiled-gallery__item\"><img decoding=\"async\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/07\/Climbing-Pico-Azores-Rui-Santos.jpg?strip=info&#038;w=562&#038;ssl=1 562w\" alt=\"\" data-height=\"750\" data-id=\"105045\" data-link=\"https:\/\/randomnerdtutorials.com\/?attachment_id=105045#main\" data-url=\"https:\/\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/07\/Climbing-Pico-Azores-Rui-Santos.jpg\" data-width=\"562\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/07\/Climbing-Pico-Azores-Rui-Santos.jpg?ssl=1\" data-amp-layout=\"responsive\"\/><\/figure><\/div><div class=\"tiled-gallery__col\" style=\"flex-basis:26.48397%\"><figure class=\"tiled-gallery__item\"><img decoding=\"async\" srcset=\"https:\/\/i2.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/07\/Climbing-Pico-Mark-30-Sara-Santos-Azores.jpg?strip=info&#038;w=562&#038;ssl=1 562w\" alt=\"\" data-height=\"750\" data-id=\"105046\" data-link=\"https:\/\/randomnerdtutorials.com\/?attachment_id=105046#main\" data-url=\"https:\/\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/07\/Climbing-Pico-Mark-30-Sara-Santos-Azores.jpg\" data-width=\"562\" src=\"https:\/\/i2.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/07\/Climbing-Pico-Mark-30-Sara-Santos-Azores.jpg?ssl=1\" data-amp-layout=\"responsive\"\/><\/figure><\/div><div class=\"tiled-gallery__col\" style=\"flex-basis:47.03207%\"><figure class=\"tiled-gallery__item\"><img decoding=\"async\" srcset=\"https:\/\/i2.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/07\/Mount-Pico-Azores-Rui-Sara-Santos.jpg?strip=info&#038;w=600&#038;ssl=1 600w, https:\/\/i2.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/07\/Mount-Pico-Azores-Rui-Sara-Santos.jpg?strip=info&#038;w=900&#038;ssl=1 900w, https:\/\/i2.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/07\/Mount-Pico-Azores-Rui-Sara-Santos.jpg?strip=info&#038;w=1000&#038;ssl=1 1000w\" alt=\"\" data-height=\"750\" data-id=\"105047\" data-link=\"https:\/\/randomnerdtutorials.com\/?attachment_id=105047#main\" data-url=\"https:\/\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/07\/Mount-Pico-Azores-Rui-Sara-Santos.jpg\" data-width=\"1000\" src=\"https:\/\/i2.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/07\/Mount-Pico-Azores-Rui-Sara-Santos.jpg?ssl=1\" data-amp-layout=\"responsive\"\/><\/figure><\/div><\/div><\/div><\/div>\n<\/div>\n<\/div>\n\n\n\n<p>At the top, the sensor was marking approximately 2260 meters, which is approximately 90 meters from the real value (2351 meters). I don&#8217;t think that a difference of 90 meters is relevant at such an altitude. What do you think? The temperature was marking 13\u00baC (55\u00baF), which was the same temperature predicted in the forecast.<\/p>\n\n\n\n<p>We tried to take pictures of the OLED display showing the results using our smartphone. Unfortunately, due to the frame rate of the OLED display, the numbers are not visible.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><a href=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/07\/BMP388-Datalogger-ESP32-Testing.jpg?quality=100&#038;strip=all&#038;ssl=1\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"750\" height=\"528\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/07\/BMP388-Datalogger-ESP32-Testing.jpg?resize=750%2C528&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"BMP388 Datalogger ESP32\" class=\"wp-image-105029\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/07\/BMP388-Datalogger-ESP32-Testing.jpg?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/07\/BMP388-Datalogger-ESP32-Testing.jpg?resize=300%2C211&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/a><\/figure><\/div>\n\n\n\n<p>Have you visited Pico Island or the Azores? Let us know in the comments below.<\/p>\n\n\n\n<p>Thanks for reading.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this project, we&#8217;ll build an altimeter datalogger with the ESP32 and the BMP388 sensor. The BMP388 is a precise pressure sensor that allows us to estimate altitude with great &#8230; <\/p>\n<p class=\"read-more-container\"><a title=\"Altimeter Datalogger: ESP32 with BMP388, MicroSD Card Storage and OLED Display\" class=\"read-more button\" href=\"https:\/\/randomnerdtutorials.com\/altimeter-datalogger-esp32-bmp388\/#more-105001\" aria-label=\"Read more about Altimeter Datalogger: ESP32 with BMP388, MicroSD Card Storage and OLED Display\">CONTINUE READING \u00bb<\/a><\/p>\n","protected":false},"author":5,"featured_media":105090,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[281,276,277,299,264],"tags":[],"class_list":["post-105001","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-esp32-project","category-esp32","category-esp32-arduino-ide","category-0-esp32","category-project"],"aioseo_notices":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/07\/Altimeter-Datalogger-ESP32-BMP388-microSD-Card-Storage-OLED-Display.jpg?fit=1280%2C720&quality=100&strip=all&ssl=1","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts\/105001","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/users\/5"}],"replies":[{"embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/comments?post=105001"}],"version-history":[{"count":27,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts\/105001\/revisions"}],"predecessor-version":[{"id":105546,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts\/105001\/revisions\/105546"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/media\/105090"}],"wp:attachment":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/media?parent=105001"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/categories?post=105001"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/tags?post=105001"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}