ESP32 Send Sensor Readings to ThingSpeak using Arduino IDE (BME280)

In this user guide, we will learn how to publish sensor readings to ThingSpeak using Arduino IDE and ESP32. We will use the BME280 sensor which provides temperature, humidity, and pressure. Our main aim is to transmit these sensor readings to ThingSpeak easily and interactively demonstrate them. For this purpose, we will use the ThingSpeak Arduino library. Any appropriate sensor can be used such as DS18B20, BME680, LM35, and MPU6050 but for this article, we will use a BME280 sensor which is used to measure temperature, pressure, and humidity.

We will cover the following content in this article:

  1. Introduction to BME280 sensor
  2. Connecting BME280 sensor with the ESP32 development board
  3. Installing ThingSpeak Arduino Library
  4. Getting ThingSpeak API Ready
  5. Publish a single field of sensor readings to ThingSpeak (Only Temperature)
  6. Publish multiple fields of sensor readings to ThingSpeak (Temperature, humidity, and pressure)

BME280 sensor Introduction

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 microcontrollers. Although there are several different versions of BME280 available in the market, the one we will be studying uses the I2C communication protocol and SPI.

Recommended Readings:

Connecting BME280 sensor with the ESP32 development board

The connection of the 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 the SCL of the module, and SDA of the sensor with the SDA pin of the ESP modules.

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

Required Components:

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

In some BME280 sensors as seen in the above connection diagram, the SCK terminal means the SCL pin and is connected with its respective GPIO pin on the ESP board. Likewise, the SDI terminal means the SDA pin and is connected with its respective GPIO pin on the board. Vin is connected with a 3.3V pin on the module and both the ESP board and the sensor are commonly grounded.

You can learn more about ESP32 I2C communication here:

Setting up Arduino IDE

We will use Arduino IDE to program our ESP32 development board. 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 plugins installed you can visit the link below:

Installing ESP32 library in Arduino IDE and upload code.

Installing BME280 Libraries

To connect the BME280 sensor with the ESP32, we need to install the BME280 libraries. This project requires two libraries:

  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 each library name in the search bar and install them both.

Adafruit BME280 library Arduino IDE
Adafruit unified sensor library install

Installing ThingSpeak Library

Likewise, we will also have to install the ThingSpeak Library as well. We will use the ThingSpeak Arduino Library to make it easier to transmit sensor readings from BME280 to the dashboard. This library will make our work very convenient.

We will use the Library Manager in our Arduino IDE to install the latest version of the library. Open your Arduino IDE and go to Sketch > Include Libraries > Manage Libraries. In the search tab type ‘ThingSpeak’ and press the enter button.

Install the library which is shown below:

thingspeak library

Getting ThingSpeak API Ready

ThingSpeak is an open-source API that is used to store or retrieve data using HTTP or MQTT protocol. This takes place over the Internet or through the LAN. We will use this API to publish sensor readings from BME280 integrated with our ESP32 board. In ThingSpeak you can access your data from anywhere in the world. You can display your data in plots and graphs.

For more information about ThingSpeak API, you can have a look at our tutorials given below:

Create ThingSpeak Account

ThingSpeak API is free to use but we will have to create a MathWorks Account. First, go to the following website:

The following window will appear. Click on the ‘Get Started for Free’ button.

ESP32 HTTP ThingSpeak get started

Now you will be redirected to the account window. If you already have an existing MathWorks account you can use that to log in. Otherwise, you will have to create a new one. Click ‘Create One!’ to make a new MathWorks account.

ESP32 HTTP ThingSpeak account

When you have successfully signed in you will receive the following notification:
Click ‘OK’.

ESP32 HTTP ThingSpeak account successful

ESP32: Publish Sensor Readings to a single field of ThingSpeak (Only Temperature)

We will start by creating a new channel for our project. Go to Channels > My Channels. Then click ‘New Channel’.

ESP32 HTTP ThingSpeak new channel

You have been prompted to give a name to your channel. We will provide a name, a description, and mark the first field. In this section, we will show you how to publish single-field data. We will start with temperature readings first. You can use any name, description, and field according to your preference. Please click ‘Save Channel’ to proceed.

thingspeak create new channel

Your channel will now be created.

thinsgpeak create new channel2

Go to ‘Private View’ and click the pencil icon on top of the Field 1 Chart. This will let us customize the graphs according to our preferences. You can add details accordingly.

thingspeak create new channel3
thingspeak create new channel4

After you press the Save button, the chart will get updated to the settings you just set.

thingspeak create new channel5

After that go to the API key tab and click it. You will now be able to access your unique API key. Save it and keep it secure as you will need it later in the program code.

thingspeak api_key1

ESP32 ThingSpeak Code: Single field

Open your Arduino IDE and go to File > New to open a new file. Copy the code given below in that file. This code will work with your ESP32 board. You just have to replace the network credentials and your API key.

#include <WiFi.h>
#include "ThingSpeak.h"
#include <Adafruit_BME280.h>
#include <Adafruit_Sensor.h>

const char* ssid = "Your_SSID";   // Write your SSID
const char* password = "Your_Password";   // Write your WIFI password

WiFiClient  client;

unsigned long Channel_ID = 1422***;  //replace with your Channel ID
const char * API_key = "RQSPUD8O5BKQ****";


unsigned long last_time = 0;
unsigned long Delay = 30000;

float temperature;

// Create a sensor object
Adafruit_BME280 bme; 

void initBME(){
  if (!bme.begin(0x76)) {
    Serial.println("BME280 not connected properly!");
    while (1);
  }
}

void setup() {
  Serial.begin(115200);  
  initBME();
  
  WiFi.mode(WIFI_STA);   
  
  ThingSpeak.begin(client);  // Initialize ThingSpeak
}

void loop() {
  if ((millis() - last_time) > Delay) {
    

    if(WiFi.status() != WL_CONNECTED){
      Serial.print("Connecting...");
      while(WiFi.status() != WL_CONNECTED){
        WiFi.begin(ssid, password); 
        delay(5000);     
      } 
      Serial.println("\nConnected.");
    }


    temperature = bme.readTemperature();
    Serial.print("Temperature (degree celsius): ");
    Serial.println(temperature);
        
    int Data = ThingSpeak.writeField(Channel_ID, 1, temperature,API_key);
 
    if(Data == 200){
      Serial.println("Channel updated successfully!");
    }
    else{
      Serial.println("Problem updating channel. HTTP error code " + String(Data));
    }
    last_time = millis();
  }
}

How does the Code work?

Now, let us understand how each part of the code works.

Including Libraries

Firstly, we will include the relevant libraries which are necessary for this project. We are using four libraries: WiFi.h, ThingSpeak.h, Adafruit_BME280.h and Adafruit_Sensor.h.
The WiFi.h library is used to connect our ESP32 module with the local WIFI network. The other three libraries are the ones that we previously installed and will be required for the ThingSpeak and sensor functionality.

#include <WiFi.h>	
#include "ThingSpeak.h"
#include <Adafruit_BME280.h>
#include <Adafruit_Sensor.h>

Setting Network Credentials

Next, we will create two global variables to save the SSID and the password values. You have to replace both of them with your network credentials to successfully connect with your router.

const char* ssid = "Your_SSID";   // Write your SSID
const char* password = "Your_Password";   // Write your WIFI password

Create a WiFiClient object which will be used to connect ESP32 to ThingSpeak:

WiFiClient  client;

Configuring your API key and Channel ID

We will specify our Channel ID and save it in the variable Channel_ID. Also, we will create a global variable named API_key to hold our unique API key. This is the key that we saved previously when creating a new channel in ThingSpeak.

unsigned long Channel_ID = 14229**;  //replace with your Channel ID
const char * API_key = "RQSPUD8O5BKQ****";  //replace with your API Key

Adding Delay

We will publish sensor readings after every 30 seconds. We will incorporate this value in the Delay variable in milliseconds.

unsigned long last_time = 0;
unsigned long Delay = 30000;

Sensor Reading Variable

The temperature variable will hold the temperature output from BME280 and we will obtain a reading sample every 30 seconds.

float temperature;

Creating BME280 Object

Additionally, we will also create an object of Adafruit_BME280 called bme which we will use later on to initialize the BEM280 sensor.

Adafruit_BME280 bme;

Initializing Sensor

The initBME() function will initialize the BME280 sensor. If the connection between the module and the sensor is incorrect, it will print that message on the serial monitor that is “BME280 not connected properly!”. This function will be called inside the setup() function.

void initBME(){
  if (!bme.begin(0x76)) {
    Serial.println("BME280 not connected properly!");
    while (1);
  }

Setup() function

Inside the setup() function, we will open a serial connection at a baud rate of 115200.

Serial.begin(115200);

We will set up the ESP32 board in station mode through WiFi.mode():

WiFi.mode(WIFI_STA);

The connection with ThingSpeak API will also be initialized.

ThingSpeak.begin(client);

loop() function

Inside the infinite loop() function we will publish the temperature readings. After every 30 seconds, the temperature value will be sent from the ESP32 to ThingSpeak. Moreover, we will connect our ESP32 board with the local network whose network credentials we already specified above using the WiFi.begin() function. After the connection is established, ‘Connected’ will be displayed on the serial monitor.

if(WiFi.status() != WL_CONNECTED){
      Serial.print("Connecting...");
      while(WiFi.status() != WL_CONNECTED){
        WiFi.begin(ssid, password); 
        delay(5000);     
      } 
      Serial.println("\nConnected.");
    }

Through bme.readTemperature(), the sensor reading will get saved in the variable ‘temperature.’ This will get displayed on the serial monitor.

temperature = bme.readTemperature();
Serial.print("Temperature (degree celsius): ");
Serial.println(temperature);

We will use the writeField() method to send the temperature readings to ThingSpeak. This method takes in four arguments. Channel ID, the number of your field (in our case it is a single field hence we specified 1), the data to be published, and your API key. All of these parameters were passed inside the method and this was saved in the variable of data type int named Data. Upon successfully publishing the readings, this method will return the number 200 which will get saved in ‘Data’.

int data= ThingSpeak.writeField(Channel_ID, 1, temperature,API_key);
 
    if(data== 200){
      Serial.println("Channel updated successfully!");
    }
    else{
      Serial.println("Problem updating channel. HTTP error code " + String(Data));
    } 

Demonstration

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

ESP32 enable reset button
Press ENABLE Button

In your Arduino IDE, open up the serial monitor and you will be able to see the status of your connection. After every 30 seconds new temperature readings will keep appearing on the serial monitor.

thingspeak publish sensor readings single field serial monitor demo
Serial Monitor

Next, open the ThingSpeak API and you will be able to see temperature readings updating after 30 seconds for your Field 1 chart.

thingspeak publish sensor readings single field dashboard demo
ThingSpeak Dashboard

Publish Multiple Fields of Sensor Readings to ThingSpeak (Temperature, Humidity, and Pressure)

Now we will learn how to publish multiple sensor readings simultaneously. Previously we only created a single field for temperature but this time we will create three fields for temperature, pressure, and humidity respectively.

You can use the previous channel to include more fields or create a new channel altogether. We will create a new channel for our project.

Go to Channels > My Channels. Then click ‘New Channel’.

ESP32 HTTP ThingSpeak new channel

You will be prompted to give a name to your channel. We will give a name, some description and mark the first field. In this section, we will show you how to publish multiple data. You can use any name, description, and field according to your preference. There are a total of eight fields that we can add to our channel at the same time. We will tick the first three fields and add the names. Click ‘Save Channel’ to proceed.

thingspeak create new channel multiple fields1

Your channel will now be created.

thingspeak create new channel multiple fields2

Go to private view and click the pencil icon on top of each Field Chart. This will allow us to customize the graphs according to our preferences. You can add details accordingly. After you press the Save button, the chart will be updated with the settings you just made.

thingspeak create new channel multiple fields3

After that go to the API key tab and click it. You will now be able to access your unique API key. Save it and keep it secure as you will need it later in the program code.

thingspeak create new channel multiple fields4

ESP32 ThingSpeak Code: Multiple Fields

Open your Arduino IDE and go to File > New to open a new file. Copy the code given below in that file. This code will work with your ESP32 board. You just have to replace the network credentials and your API key.

#include <WiFi.h>
#include "ThingSpeak.h"
#include <Adafruit_BME280.h>
#include <Adafruit_Sensor.h>

const char* ssid = "Your_SSID";   
const char* password = "Your_Password";   

WiFiClient  client;

unsigned long Channel_ID = 1423***;
const char * API_Key = "****************";

unsigned long last_time = 0;
unsigned long Delay = 30000;

// Variables to store sensor readings
float temperature;
float humidity;
float pressure;


// Create a sensor object
Adafruit_BME280 bme; 

void initBME(){
  if (!bme.begin(0x76)) {
    Serial.println("BME280 not properly connected!");
    while (1);
  }
}

void setup() {
  Serial.begin(115200);  
  initBME();
  
  WiFi.mode(WIFI_STA);   
  
  ThingSpeak.begin(client); 
}

void loop() {
  if ((millis() - last_time) > Delay) {
    
    // Connect or reconnect to WiFi
    if(WiFi.status() != WL_CONNECTED){
      Serial.print("Connecting...");
      while(WiFi.status() != WL_CONNECTED){
        WiFi.begin(ssid, password); 
        delay(5000);     
      } 
      Serial.println("\nConnected.");
    }

    // Obtaining a new sensor reading for all fields
    temperature = bme.readTemperature();
    Serial.print("Temperature (ºC): ");
    Serial.println(temperature);
    humidity = bme.readHumidity();
    Serial.print("Humidity (%): ");
    Serial.println(humidity);
    pressure = bme.readPressure() / 100.0F;
    Serial.print("Pressure (hPa): ");
    Serial.println(pressure);
    
    ThingSpeak.setField(1, temperature);
    ThingSpeak.setField(2, pressure);
    ThingSpeak.setField(3, humidity);
   
    int Data = ThingSpeak.writeFields(Channel_ID, API_Key);

    if(Data == 200){
      Serial.println("Channel updated successfully!");
    }
    else{
      Serial.println("Problem updating channel. HTTP error code " + String(Data));
    }
    last_time = millis();
  }
}

How does the Code Work?

Most of the program code is similar to the one above it so we will only look at parts where we are incorporating multiple fields.

We will now create three variables to store the sensor readings individually. One for temperature. Another for humidity and one for pressure.

float temperature;
float humidity;
float pressure;

In the loop() function we will use the bme object on readTemperature(), readHumidity(), and readPressure() individually. These sensor readings will be saved in the variables which we previously defined above temperature, humidity, and pressure. Likewise, all three readings will get printed on the serial monitor with a delay of 30 seconds.

  // Obtaining a new sensor reading for all fields
    temperature = bme.readTemperature();
    Serial.print("Temperature (ºC): ");
    Serial.println(temperature);
    humidity = bme.readHumidity();
    Serial.print("Humidity (%): ");
    Serial.println(humidity);
    pressure = bme.readPressure() / 100.0F;
    Serial.print("Pressure (hPa): ");
    Serial.println(pressure);

Next, we will use ThingSpeak.setField() to assign a value to each field. The first argument will be the field number. For our case, we set field 1 as temperature, field 2 as pressure, and field 3 as humidity. You will use the ordering of the fields you used when creating your channel. The second argument will be the data variables we created for each field: temperature, pressure, and humidity.

ThingSpeak.setField(1, temperature);
ThingSpeak.setField(2, pressure);
ThingSpeak.setField(3, humidity);

Lastly, we will use the writeFields() method and pass the channel ID and API key as parameters.

int Data = ThingSpeak.writeFields(Channel_ID, API_Key);

Demonstration

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

ESP32 enable reset button
Press ENABLE Button

In your Arduino IDE, open up the serial monitor and you will be able to see the status of your connection. After every 30 seconds, new sensor readings will keep appearing on the serial monitor.

thingspeak publish sensor readings multiple fields serial monitor demo
Serial Monitor

Next, open the ThingSpeak API and you will be able to see temperature, pressure and humidity readings updating after 30 seconds in your charts.

thingspeak publish sensor readings multiple fields dashboard demo
ThingSpeak Dashboard

Conclusion

In conclusion, this user guide provided a comprehensive overview of how to publish sensor readings to ThingSpeak using the Arduino IDE and ESP32. By utilizing the BME280 sensor and the ThingSpeak Arduino library, users can easily transmit temperature, humidity, and pressure data to ThingSpeak and interactively demonstrate and analyze the information. The guide covered various topics such as the introduction of the BME280 sensor, connecting it with the ESP32 development board, setting up the Arduino IDE, installing necessary libraries, and configuring ThingSpeak API. Additionally, it provided step-by-step instructions and code examples for publishing sensor readings to ThingSpeak both for a single field and multiple fields.

If you are using the esp-idf instead of the Arduino framework, you can refer to this guide:

If you find this ESP32 project useful, you may also like to read:

Leave a Comment