ESP32 Send BME280 Sensor Readings to InfluxDB

In this ESP32 guide, we will introduce you to InfluxDB and show you how to send BME280 sensor readings to the InfluxDB time-series database. We will show you how to create a database bucket and send ESP32 sensor data to the InfluxDB database. Moreover, we will also show you how to build your dashboard so that you are able to view your data in a more meaningful manner e.g. charts, graphs, etc. By the end of this tutorial, you will be able to know how to set up an ESP32 InfluxDB database and visualize the temperature, pressure, and humidity readings acquired from BME280 in a dashboard. One of the great features of using the InfluxDB database is that you can store your data in timestamps over a determined period of time. This makes it extremely handy to use in IoT projects where data logging with time is of importance.

ESP32 BME280 sensor InfluxDB

You may also like to check:

InfluxDB Introduction

InfluxDB is an open-source time series database. It is used for storing and acquiring time series data commonly used in IoT applications, real time data analysis, operations monitoring etc. A vast amount of data can be efficiently stored every second with timestamps associated with each data point.

InfluxDB logo

Let us define some InfluxDB key terms that are commonly used while using this database.

Bucket: A bucket is a specified place where the data is stored. While creating a bucket you specify the name and the time period for the data to get deleted.

Point: A point consists of a set of data in a row. It comprises of a measurement, tag set, field key, field value and a timestamp.

Tag (tag key and tag value): The columns in a data are known as tags. A tag consists of a set of data that gives us information about other data that are usually queried. Although they are optional but it helps in organizing the data in an efficient manner. They are indexed.

Field (field key and field value): A field consists of a field key and a field value stored in their respective columns. They are not indexed. Here a field key is a string type that depicts the name of the field. A field value on the other hand depicts the value of the field. It can be type string, float, int or boolean.

Measurement: This shows the data (tags, fields, timestamps) stored in the related fields. A measurement name is a string and is chosen in such a way that it describes the data it holds.

Recommended Reading: InfluxDB data elements

Setting up an InfluxDB Database

Now let us see how to easily set up our InfluxDB database for ESP32 data logging. Firstly, head over to the official InfluxDB website (https://www.influxdata.com/) and click the ‘Get InfluxDB’ button as highlighted below.

InfluxDB create account 1

You will have to create a free InfluxDB cloud account. You can either continue with your Google or Microsoft account or login by providing your details as shown below to create an account.

InfluxDB create account 2

The next step is to choose where you would like to store the data. We are selecting Google Cloud as storage. You also have the option of using Amazon web services and Microsoft Azure. Moreover, the company name will also be required. Do not forget to tick the agreement after reading it.

InfluxDB store data

Next up we will be asked to select a plan. We will stick with the ‘Free’ plan as it works well with our projects.

InfluxDB choose plan

Now the get started page will open up. By now we have successfully logged into InfluxDB, set our storage destination and chosen our InfluxDB cloud plan. Now we are ready to load data.

InfluxDB getting started page

Load Data

To load data to InfluxDB start by clicking the More button as highlighted below.

InfluxDB load data

This will open the load data section. Here under the ‘Sources’ tab select Arduino as the client library.

InfluxDB load data 2

This will open up the bucket page with sample code as well. Currently we don’t have any bucket. First, we will have to create a bucket. Click ‘+ CREATE BUCKET’ to proceed forward.

InfluxDB create Bucket 1

Give a name to your bucket and customize the option to delete data according to your requirements. After that click ‘CREATE’ to complete the process of bucket creation.

InfluxDB create Bucket 2

Now as you may see, in the bucket page we can view the bucket we just created. We had named it ‘ESP32’ and it can be found under the bucket section. Double click on it for the bucket to get selected.

InfluxDB create Bucket 3

Obtain InfluxDB Parameters (URL, ORG and Bucket)

This is a very important step. We will obtain the InfluxDB URL, ORG and Bucket. These parameters will be used inside our program sketch to successfully send data to InfluxDB.

Inside our ESP32 bucket, head over to ‘Initialize the Client’ section. Here you can view the definitions of different InfluxDB parameters. Copy the INFLUXDB_URL, INFLUXDB_ORG and INFLUXDB_BUCKET.

InfluxDB create Bucket 4

Obtain API Token

The next important step is to generate an API Token. This is also required for securely reading/writing to the InfluxDB database.

At the far left side, click the arrow icon as shown below and then select API Tokens.

InfluxDB API Token 1

Now click + GENERATE API TOKEN and then click All Access API Token as highlighted below:

InfluxDB API Token 2

Give a description to your All Access API Token and save it.

InfluxDB API Token 3

Now your API token will get generated. Copy it and save it securely. You will not be able to view it again.

InfluxDB API Token 4

ESP32: Record BME280 readings to InfluxDB

Now we are all set to send ESP32 data points in InfluxDB. For demonstration purposes, we will interface our ESP32 board with a BME280 sensor and send current temperature, humidity and pressure readings to our ESP32 bucket in InfluxDB.

The BME280 sensor is used to measure readings regarding ambient temperature, barometric pressure, and relative humidity. It is mostly used in web and mobile applications where low power consumption is key. This sensor uses I2C or SPI to communicate data with the micro-controllers. Although there are several different versions of BME280 available in the market, the one we will be studying uses the I2C communication protocol.

I2C means Inter-Integrated Circuit and works on the principle of the synchronous, multi-master multi-slave system. With BME280 and the ESP boards, the ESP32 acts as a master, and the BME280 sensor as a slave because it is an external device, acts as a slave. The ESP development boards communicate with the BME280 sensor through the I2C protocol to get temperature, barometric pressure, and relative humidity.

The figure below shows the BME280 sensor and its pinout.

BME280 Pinout Diagram
         BME280 Pinout
  • VCC: connected with 3.3V
  • SCL: used to generate the clock signal
  • SDA: used in sending and receiving data

Interfacing BME280 sensor with ESP32

BME280 sensor interfacing with ESP32

The connection of BME280 with the ESP32 boards is very easy. We have to connect the VCC terminal with 3.3V, ground with the ground (common ground), SCL of the sensor with SCL of the module, and SDA of the sensor with the SDA pin of the ESP module.

The I2C pin in ESP32 for SDA is GPIO21 and for SCL is GPIO22.

We will need the following components to connect our ESP32 board with the BME280 sensor.

  1. ESP32 board
  2. BME280 Sensor
  3. Connecting Wires
  4. Breadboard

Follow the schematic diagram below for the ESP32 module and connect them accordingly.

BME280 with ESP32 MicroPython
Connection Diagram

Setting up Arduino IDE for ESP32 sensor data recording to InfluxDB

We will use Arduino IDE to program our ESP32. Thus, you should have the latest version of Arduino IDE. Additionally, you also need to install the ESP32 plugin.

If your IDE does not have the plugin installed you can visit the link below: Installing ESP32 library in Arduino IDE and upload code.

Install InfluxDB Library in Arduino IDE

Open Arduino IDE and click on Sketch > Library > Manage Libraries

MPU-6050 Install library

The following window will open up.

search library Arduino IDE

Type ‘Influxdb’ in the search bar and press enter. Install the latest version of the library as shown below. This library is compatible with both ESP8266 and ESP32 development boards.

Install InfluxDB Library

Installing BME280 Arduino Library

As we are connecting the BME280 sensor with ESP32 so we will have to install BME280 libraries to our module. We will require two libraries for this project:

  1. Adafruit_BME280 library
  2. Adafruit_Sensor library

We will use the Library Manager in our Arduino IDE to install the latest versions of the libraries. Open your Arduino IDE and go to Sketch > Include Libraries > Manage Libraries. Type Adafruit BME280 library name in the search bar and install them both.

Adafruit BME280 library Arduino IDE

Open your Arduino IDE and go to Sketch > Include Libraries > Manage Libraries. Type Adafruit unified sensor library name in the search bar and install it.

Adafruit unified sensor library install

After installation of the libraries, restart your IDE.

Sketch: ESP32 Record BME280 Sensor Data to InfluxDB

Open your Arduino IDE and go to File > New to open a new file. Copy the code given below in that file. Remember to change the Wi-Fi credentials, InfluxDB URL, ORG, Bucket name and the API token. Additionally, set the time zone string according to your location to synch time correctly.

This sketch creates three data points (temperature, humidity and pressure) on the database with tags and fields. After every 10 seconds, it saves the sensor readings taken from BME280 connected with ESP32 development board.

#include <WiFiMulti.h>
#include <InfluxDbClient.h>
#include <InfluxDbCloud.h>
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>

WiFiMulti wifiMulti;
Adafruit_BME280 bme; 

float temperature;
float humidity;
float pressure;

#define DEVICE "ESP32"
#define WIFI_SSID "WRITE_YOUR_SSID"
#define WIFI_PASSWORD "WRITE_YOUR_PASSWORD"
#define INFLUXDB_URL "WRITE_YOUR_URL"
#define INFLUXDB_TOKEN "WRITE_YOUR_API_TOKEN"
#define INFLUXDB_ORG "WRITE_YOUR_ORG"
#define INFLUXDB_BUCKET "WRITE_YOUR_BUCKET"

// Set timezone string according to https://www.gnu.org/software/libc/manual/html_node/TZ-Variable.html
#define TZ_INFO "PKT-5"

// InfluxDB client instance with preconfigured InfluxCloud certificate
InfluxDBClient client(INFLUXDB_URL, INFLUXDB_ORG, INFLUXDB_BUCKET, INFLUXDB_TOKEN, InfluxDbCloud2CACert);

// Data points
Point sensor1("temperature_status");
Point sensor2("humidity_status");
Point sensor3("pressure_status");


void setup() {
  Serial.begin(115200);
  WiFi.mode(WIFI_STA);
  wifiMulti.addAP(WIFI_SSID, WIFI_PASSWORD);
  Serial.print("Connecting to wifi");
  while (wifiMulti.run() != WL_CONNECTED) {
    Serial.print(".");
    delay(500);
  }
  Serial.println();
 
  if (!bme.begin(0x76)) {
    Serial.println("Could not detect a BME280 sensor, Fix wiring Connections!");
    while (1);
  }

  // Add tags
  sensor1.addTag("device", DEVICE);
  sensor1.addTag("SSID", WiFi.SSID());

  sensor2.addTag("device", DEVICE);
  sensor2.addTag("SSID", WiFi.SSID());

  sensor3.addTag("device", DEVICE);
  sensor3.addTag("SSID", WiFi.SSID());
  
  timeSync(TZ_INFO, "pool.ntp.org", "time.nis.gov");
  
  if (client.validateConnection()) {
    Serial.print("Connected to InfluxDB: ");
    Serial.println(client.getServerUrl());
  } else {
    Serial.print("InfluxDB connection failed: ");
    Serial.println(client.getLastErrorMessage());
  }
}

void loop() {
  // Store measured values into points
  sensor1.clearFields();
  sensor2.clearFields();
  sensor3.clearFields();
  
  temperature = bme.readTemperature();
  humidity = bme.readHumidity();
  pressure = bme.readPressure() / 100.0F;
  
  sensor1.addField("Temperature",temperature);
  sensor2.addField("Humidity",humidity);
  sensor3.addField("Pressure",pressure);

  Serial.print("Writing: ");
  Serial.println(client.pointToLineProtocol(sensor1));
  Serial.println(client.pointToLineProtocol(sensor2));
  Serial.println(client.pointToLineProtocol(sensor3));
  
  // If no Wifi signal, try to reconnect it
  if (wifiMulti.run() != WL_CONNECTED) {
    Serial.println("Wifi connection lost");
  }
  // Write point
  if (!client.writePoint(sensor1)) {
    Serial.print("InfluxDB write failed for temperature: ");
    Serial.println(client.getLastErrorMessage());
  }

    if (!client.writePoint(sensor2)) {
    Serial.print("InfluxDB write failed for humidity: ");
    Serial.println(client.getLastErrorMessage());
  }

    if (!client.writePoint(sensor3)) {
    Serial.print("InfluxDB write failed for pressure: ");
    Serial.println(client.getLastErrorMessage());
  }
  Serial.println("");
  Serial.println("Delay 10s");
  delay(10000);
}

How the Code Works?

The first step is to include all the necessary libraries for this project. WiFiMulti library will allow us to add multiple Wi-Fi networks inside our sketch and the ESP32 connects with the strongest network. However, we will use a single network in this example. Secondly, also include the InfluxDB libraries that we just installed. This will ensure an easy and successful ESP32 communication with InfluxDB. Moreover, the other libraries included are for BME280 functionality.

#include <WiFiMulti.h>
#include <InfluxDbClient.h>
#include <InfluxDbCloud.h>
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>

Next, create an object of WiFiMulti as shown below:

WiFiMulti wifiMulti;

Then, define the Adafruit_BME280 object named bme by setting it on the default I2C GPIO pins of ESP32.

Adafruit_BME280 bme; 

Next, declare variables to hold BME280 sensor readings such as temperature, pressure, and humidity. These are declared as float types because we will be dealing with numerical values which could have floating decimal points. In other words, the values returned by BME280 sensor are floating point values.


float temperature;
float humidity;
float pressure;

InfluxDB Parameters

Specify the name of the device that you will be using. In our case it is ESP32.

#define DEVICE "ESP32"

The next step is very important. Carefully define your Wi-Fi SSID, Wi-Fi password, InfluxDB URL, InfluxDB ORG, InfluxDB API token and InfluxDB bucket name. The parameters related to InfluxDB are the ones that we previously acquired and saved.

#define WIFI_SSID "WRITE_YOUR_SSID"
#define WIFI_PASSWORD "WRITE_YOUR_PASSWORD"
#define INFLUXDB_URL "WRITE_YOUR_URL"
#define INFLUXDB_TOKEN "WRITE_YOUR_API_TOKEN"
#define INFLUXDB_ORG "WRITE_YOUR_ORG"
#define INFLUXDB_BUCKET "WRITE_YOUR_BUCKET"

Now, define the time zone according to your location. This is necessary to synch the time.

Refer to the link given below to obtain the time zone closest to your location and define it in code.

https://github.com/nayarsystems/posix_tz_db/blob/master/zones.csv

We have set the time zone for Asia/Karachi hence we use PKT-5.

// Set timezone string according to https://www.gnu.org/software/libc/manual/html_node/TZ-Variable.html
#define TZ_INFO "PKT-5"

The next step is to create an InfluxDBClient instance. This will generate a secure client with a preconfigured certificate.

InfluxDBClient client(INFLUXDB_URL, INFLUXDB_ORG, INFLUXDB_BUCKET, INFLUXDB_TOKEN, InfluxDbCloud2CACert);

Here we will create three data points called ‘temperature_status’, ‘humidity_status’ and ‘pressure_status’ in the InfluxDB database. These will consist of a measurement, tag set, field key, field value and timestamp. In this case the point instances are called sensor1, sensor2 and sensor3 respectively for the three readings.

Point sensor1("temperature_status");
Point sensor2("humidity_status");
Point sensor3("pressure_status");

setup()

Inside the setup() function, we will open the serial communication at a baud rate of 115200. Then we will set the ESP32 in station mode.

Serial.begin(115200);
WiFi.mode(WIFI_STA);

Then add the Wi-Fi network for the ESP32 to connect with. This will be done using the addAP() method on the WiFiMulti object. Here we will specify two parameters. The first parameter is the SSID and the second parameter is the password. You can add as many networks as you want. We are only adding a single network.

wifiMulti.addAP(WIFI_SSID, WIFI_PASSWORD);

We will use the run() method on the WiFimulti object, to connect ESP32 with the strongest Wi-Fi connection. This returns the status of the Wi-Fi connection.

The following lines of code will be used to monitor if the ESP32 is connected or not. While the connection is lost, it will try to connect again.

Serial.print("Connecting to wifi");
  while (wifiMulti.run() != WL_CONNECTED) {
    Serial.print(".");
    delay(500);
  }
  Serial.println();

Check if the BME280 sensor is initialized or not.

  if (!bme.begin(0x76)) {
    Serial.println("Could not detect a BME280 sensor, Fix wiring Connections!");
    while (1);
  }

Now add the tags to the data points. This is done using the addTag() method on the point instances. It takes in two parameters. The first is the tag key and the second is the tag value.

Here we are adding two tags to the three data points. One for the device name and another for the Wi-Fi SSID.

  sensor1.addTag("device", DEVICE);
  sensor1.addTag("SSID", WiFi.SSID());

  sensor2.addTag("device", DEVICE);
  sensor2.addTag("SSID", WiFi.SSID());

  sensor3.addTag("device", DEVICE);
  sensor3.addTag("SSID", WiFi.SSID());

Next we will synch the time with the NTP server using the timeSync() function.

timeSync(TZ_INFO, "pool.ntp.org", "time.nis.gov");

Lastly, the InfluxDB client confirms its connection to the server. A relevant message will be printed in the serial monitor in either case if the client is connected or not.


  if (client.validateConnection()) {
    Serial.print("Connected to InfluxDB: ");
    Serial.println(client.getServerUrl());
  } else {
    Serial.print("InfluxDB connection failed: ");
    Serial.println(client.getLastErrorMessage());
  }

loop()

Inside the loop() function, we store the data to the point. First of all we will clear all the fields of the point instances.

  sensor1.clearFields();
  sensor2.clearFields();
  sensor3.clearFields();

Then we will access the BME280 sensor readings and save them in the float variables temperature, humidity and pressure. Temperature readings are acquired through bme.readTemperature(). Pressure and humidity readings are accessed using the bme.readPressure()/ 100.0F and bme.readHumidity() functions respectively.

  temperature = bme.readTemperature();
  humidity = bme.readHumidity();
  pressure = bme.readPressure() / 100.0F;

Next, we add the Temperature field to our temperature_status point, Humidity field to our humidity_status point and Pressure field to our pressure_status point This is done by using the addField() method on the Point instances. We specify the key as the first parameter and the value as the second parameter.

  sensor1.addField("Temperature",temperature);
  sensor2.addField("Humidity",humidity);
  sensor3.addField("Pressure",pressure);

Then we will display on the serial monitor the information that is being written to the points. The data will be shown in the Line Protocol form.

  Serial.print("Writing: ");
  Serial.println(client.pointToLineProtocol(sensor1));
  Serial.println(client.pointToLineProtocol(sensor2));
  Serial.println(client.pointToLineProtocol(sensor3));

Additionally, connect to the Wi-Fi network incase of disconnection.

  if (wifiMulti.run() != WL_CONNECTED) {
    Serial.println("Wifi connection lost");
  }

Lastly, write the point to the database after every 10 seconds. This is done by using client.writePoint() and passing the point as the parameter inside it.

if (!client.writePoint(sensor1)) {
    Serial.print("InfluxDB write failed for temperature: ");
    Serial.println(client.getLastErrorMessage());
  }

    if (!client.writePoint(sensor2)) {
    Serial.print("InfluxDB write failed for humidity: ");
    Serial.println(client.getLastErrorMessage());
  }

    if (!client.writePoint(sensor3)) {
    Serial.print("InfluxDB write failed for pressure: ");
    Serial.println(client.getLastErrorMessage());
  }
  Serial.println("");
  Serial.println("Delay 10s");
  delay(10000);

Demonstration

Choose the correct board and COM port before uploading your code to the board.
Go to Tools > Board and select ESP32 Dev Module.

select esp32 board

Next, go to Tools > Port and select the appropriate port through which your board is connected.

Selecting COM PORT ESP32

Click on the upload button to upload the code into the ESP32 development board. After you have uploaded your code to the ESP32 development board press its ENABLE button.

ESP32 enable reset button

In your Arduino IDE, open up the serial monitor and set the baud rate to 115200. First the board will connect with the local Wi-Fi then the time will sync. Next the client gets connected to InfluxDB server and you can view the data being written to the database after every 10 seconds.

ESP32 send BME280 readings to InfluxDB serial monitor

Visualize Data in InfluxDB

Now let us visualize the data that we sent to InfluxDB Cloud. Login to your InfluxDB account and head over to Data Explorer as shown below.

InfluxDB Data Explorer

This will open the Data Explorer page. Here we will be able to graph the data that is being sent to the InfluxDB cloud. First click the ESP32 bucket. Then to view temperature readings click temperature_status under the measurement filter, the SSID being used under the SSID filter, Temperature which is the field tag under the field filter and ESP32 under the device filter. Click Submit to display the data.

ESP32 send BME280 readings to InfluxDB data explorer temperature 1

Now you can view the temperature data being plotted in a graph. You can also customize it as well.

ESP32 send BME280 readings to InfluxDB data explorer temperature 2

To view pressure readings click pressure_status under the measurement filter, the SSID being used under the SSID filter, Pressure which is the field tag under the field filter and ESP32 under the device filter. Click Submit to display the data.

Now you can view the pressure data being plotted in a graph.

ESP32 send BME280 readings to InfluxDB data explorer pressure

Similarly, to view humidity readings click humidity_status under the measurement filter, the SSID being used under the SSID filter, Humidity which is the field tag under the field filter and ESP32 under the device filter. Click Submit to display the data.

Now you can view the humidity data being plotted in a graph.

ESP32 send BME280 readings to InfluxDB data explorer humidity

Moreover, you can also display the data in various formats including band, gauge, histogram, map etc. Just select it from the dropdown below.

InfluxDB Data Explorer 4

Build InfluxDB BME20 Dashboard

Now let us show you how to display the data in various formats on the same page. We will create a dashboard. Head over to the Dashboard icon and click it.

InfluxDB Create Dashboard

This will open the Dashboard open. Currently, we do not have any dashboard created. Click ‘+ CREATE DASHBOARD’ button as highlighted below:

InfluxDB Create Dashboard 1

Give a name to your dashboard. Then click ADD CELL to add a visualization.

InfluxDB Create Dashboard 2

Temperature

Specify the name of the cell. We have given it the name ‘BME280 Temperature Reading Celsius’. Next choose the visualization from the dropdown menu. We have selected Single Stat.

To obtain the data make a query like we did previously in the data explorer. First click the ESP32 bucket, then tick temperature_status under the measurement filter, the SSID being used under the SSID filter, Temperature which is the field tag under the field filter and ESP32 under the device filter. Click the submit button for the changes to take place. You will be able to view the visualization. As we are displaying the temperature reading as a single stat hence we got the reading 29.99. You can also customize the visualization from the CUSTOMIZE button. After you are satisfied, then click the tick button for the cell to be added to the dashboard.

ESP32 send BME280 readings to InfluxDB data Create Dashboard 1

As you may see, the reading can now be seen in our dashboard.

ESP32 send BME280 readings to InfluxDB data Create Dashboard 2

To add more visualizations click ‘ADD CELL’ again and follow the procedure as described previously.

Pressure

Next to add the visualization for pressure readings we will create another cell. Give it a name. We have given it the name ‘BME280 Pressure Readings’. Next choose the visualization from the dropdown menu. We have selected Graph this time.

To obtain the data make a query like we did previously in the data explorer. First click the ESP32 bucket, then tick pressure_status under the measurement filter, the SSID being used under the SSID filter, Pressure which is the field tag under the field filter and ESP32 under the device filter. Click the submit button for the changes to take place. You will be able to view the visualization. We have customized the graph by adding the y-axis label Pressure (hPa). After you are satisfied, then click the tick button for the cell to be added to the dashboard.

ESP32 send BME280 readings to InfluxDB data Create Dashboard 3

Humidity

Similarly, we add the visualization for humidity readings. Create a new cell and give it a name. We have given it the name ‘BME280 Humidity Reading’. Next choose the visualization from the dropdown menu. We have selected Gauge this time.

To obtain the data make a query like we did previously in the data explorer. First click the ESP32 bucket, then tick humidity_status under the measurement filter, the SSID being used under the SSID filter, Humidity which is the field tag under the field filter and ESP32 under the device filter. Click the submit button for the changes to take place. You will be able to view the visualization. We have customized the gauge by adding % as a suffix. After you are satisfied, then click the tick button for the cell to be added to the dashboard.

ESP32 send BME280 readings to InfluxDB data Create Dashboard 4

This is how our ESP32 BME280 Sensor Readings dashboard looks like with the three cells added. You can also change the settings to set the time to refresh your dashboard.

ESP32 send BME280 readings to InfluxDB data Create Dashboard 5

Leave a Comment