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 the ThingSpeak Arduino library and ESP32. We will use Arduino IDE to program our ESP32 board which will be connected to a temperature, humidity, and pressure sensor. 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. Setting up Arduino IDE
  4. Getting ThingSpeak API Ready
  5. Publish to a single field of sensor readings to ThingSpeak (Only Temperature)
  6. Publish to 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 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 and SPI.

Recommended Readings:

Connecting BME280 sensor with the ESP32 development board

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 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 is commonly grounded.

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

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 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 transit 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:

Creating Account

ThingSpeak API is free to use but we will have to create a MathWorks Account.
First go to the following website: https://thingspeak.com/
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 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 single field data. We will start with temperature readings first. You can use any name, description and field according to your preference. 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 preference. 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: Single field Arduino Sketch

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 reading sample after 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 will be 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 to 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 let us customize the graphs according to our preference. You can add details accordingly. After you press the Save button, the chart will get updated to the settings you just set.

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

ThingSpeak Multiple fields Arduino Sketch

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 the Code Works?

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 these 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, we were able to learn how to publish sensor readings to ThingSpeak using the ThingSpeak Arduino library in a fairly easy way. Likewise, you can single or multiple data to ThingSpeak API which you will be able to access from anywhere around the world.

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

Leave a Comment