BME280 with ESP32 – Display Values on OLED ( Arduino IDE)

In this tutorial, we will explore how to interface the BME280 sensor with an ESP32 microcontroller using the Arduino IDE. The BME280 sensor is capable of measuring pressure, humidity, and temperature, making it a versatile choice for various environmental monitoring applications. We’ll start with an overview of the BME280 sensor and its connection to the ESP32. Following that, we’ll guide you through the installation of the BME280 library in the Arduino IDE. Then, we’ll demonstrate a simple Arduino example to illustrate the sensor’s functionality. Finally, we will measure temperature, humidity, and pressure, displaying the data on both the serial monitor and an SSD1306 OLED display.

We have a similar guide with MicroPython:

MicroPython: BME280 with ESP32 and ESP8266

We will cover the following topics in this article:

  • Interface BME280 with ESP32
  • Display Sensor readings on Arduino serial monitor
  • Print Sensor readings on SSD1306 OLED

We also have a similar tutorial with ESP8266 NodeMC:

BME280 with ESP8266 NodeMCU – Display Values on OLED ( Arduino IDE)

BME280 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.

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.

Pinout Diagram

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

ESP32 and ESP8266 Schematic with BME280

The connection of BME280 with the ESP boards is very easy. We should connect the VCC terminal of BME280 with 3.3V of ESP32, ground with the ground (common ground), SCL of the sensor with SCL of ESP32, 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. The connections between the two devices can be seen below.

ESP32BME280
VCC=3.3VVin
GPIO21(I2C SDA)SDA
GPIO22(I2C SCL)SCL
GROUNDGROUND

ESP32 I2C Pins

The I2C pins stated above are set in default. If we want to change the GPIO pins we have to set them in code. The diagrams below show the I2C pins of ESP32 marked with red color rectangles.

ESP32 I2C Pins
ESP32 I2C Pins

For more information on ESP32 pins, refer to the following article:

Interfacing BME280 sensor 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.

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 ESP32. 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 BME280 sensor are commonly grounded.

Installing BME280 Arduino Library

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.

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

Arduino Code – Getting BME280 Readings on Arduino Serial Monitor

BME280 sensor interfacing with ESP32

This BM280 example sketch displays temperature, pressure, approximate altitude, and humidity readings on Arduino serial monitor.

/* Include libraries of BME280 sensor */
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>

/*#include <SPI.h>  // uncomment his if you are using SPI interface
#define BME_SCK 18
#define BME_MISO 19
#define BME_MOSI 23
#define BME_CS 5*/

#define SEALEVELPRESSURE_HPA (1013.25)

Adafruit_BME280 bme; // I2C
//Adafruit_BME280 bme(BME_CS); // hardware SPI
//Adafruit_BME280 bme(BME_CS, BME_MOSI, BME_MISO, BME_SCK); // software SPI


void setup() {
  Serial.begin(9600);
  Serial.println(F("BME280 test"));

  bool status;

  // default settings
  // (you can also pass in a Wire library object like &Wire2)
  status = bme.begin(0x76);  
  if (!status) {
    Serial.println("Could not detect a BME280 sensor, Fix wiring Connections!");
    while (1);
  }

  Serial.println("-- Print BME280 readings--");
  Serial.println();
}


void loop() { 
  Serial.print("Temperature = ");
  Serial.print(bme.readTemperature());
  Serial.println(" *C");
  
  // Convert temperature to Fahrenheit
  /*Serial.print("Temperature = ");
  Serial.print(1.8 * bme.readTemperature() + 32);
  Serial.println(" *F");*/
  
  Serial.print("Pressure = ");
  Serial.print(bme.readPressure() / 100.0F);
  Serial.println(" hPa");

  Serial.print("Approx. Altitude = ");
  Serial.print(bme.readAltitude(SEALEVELPRESSURE_HPA));
  Serial.println(" m");

  Serial.print("Humidity = ");
  Serial.print(bme.readHumidity());
  Serial.println(" %");

  Serial.println();
  delay(1000);
}

How Code Works?

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

Including Libraries

The code starts with including all the necessary libraries which are needed for the proper functionality of the code. The Wire.h will allow us to communicate through the I2C protocol and the SPI.h allows us to communicate through the SPI protocol. Both communication protocols are included. The Adafruit_Sensor and the Adafruit_BME280 libraries which we installed in Arduino IDE earlier are also included as they are necessary to interface with the sensor.

#include <Wire.h>
#include <SPI.h>	
#include <Adafruit_BME280.h>
#include <Adafruit_Sensor.h>

This code is using the I2C protocol to communicate with ESP32 and BME280. If you want to use SPI protocol instead, just uncomment the following block of code which defines the default pins:

/*#define BME_SCK 18
#define BME_MISO 19
#define BME_MOSI 23
#define BME_CS 5*/

Next, the code defines the SEALEVELPRESSURE_HPA by creating a variable by the set name. It takes into account the sea level pressure of your current location and compares it with a given pressure to estimate the altitude. You have to pass your sea-level pressure in hPa according to your location. The 1013.25 is the value that is set in default.

#define SEALEVELPRESSURE_HPA (1013.25)

Then, it defines the Adafruit_BME280 object named bme by setting it on the default I2C GPIO pins. If using SPI protocol instead, make sure to comment on this line and uncomment the lines which are initializing the SPI pins.

Adafruit_BME280 bme; // I2C
//Adafruit_BME280 bme(BME_CS); // hardware SPI
//Adafruit_BME280 bme(BME_CS, BME_MOSI, BME_MISO, BME_SCK); // software SPI

The setup() function is created. This initiates the serial communication at a baud rate of 115200 by using the begin() function.

Serial.begin(115200);

Then, the BME280 sensor gets initialized and in case of failure, an error message is printed on the serial monitor.

Serial.println(F("BME280 test"));

  bool status;

  // default settings
  // (you can also pass in a Wire library object like &Wire2)
  status = bme.begin(0x76);  
  if (!status) {
    Serial.println("Could not detect a BME280 sensor, Fix wiring Connections!");
    while (1);
  }

  Serial.println("-- Print BME280 readings--");
  Serial.println();

Inside the for loop, We take BME280 sensor readings by using bme.readTemperature(), bme.readPressure(), bme.readAltitude(SEALEVELPRESSURE_HPA) and bme.readHumidity() and display them on Arduino serial monitor. These functions measure ambient temperature, barometric pressure, relative humidity, and approximate altitude, respectively. The units are also displayed. The BME280 sensor readings are updated on Arduino serial monitor after every one second.

Serial.print("Temperature = ");
  Serial.print(bme.readTemperature());
  Serial.println(" *C");
  
  // Convert temperature to Fahrenheit
  /*Serial.print("Temperature = ");
  Serial.print(1.8 * bme.readTemperature() + 32);
  Serial.println(" *F");*/
  
  Serial.print("Pressure = ");
  Serial.print(bme.readPressure() / 100.0F);
  Serial.println(" hPa");

  Serial.print("Approx. Altitude = ");
  Serial.print(bme.readAltitude(SEALEVELPRESSURE_HPA));
  Serial.println(" m");

  Serial.print("Humidity = ");
  Serial.print(bme.readHumidity());
  Serial.println(" %");

  Serial.println();
  delay(1000);
}

Demonstration

In Arduino IDE, click Tools > Board and select ESP32.

select esp32 board

Now, click Tools > Port and choose the port which you are using. Now, upload the code by clicking on the upload button.

Selecting COM PORT ESP32

After you have uploaded the following code on your ESP32 development board, press the ENABLE button as follows:

ESP32 enable reset button

In your Arduino IDE, open up the serial monitor and you will see the serial monitor displaying all the BME280 sensor readings such as Pressure, Temperature, Humidity, and altitude as shown below:

Display BME280 sensor readings on Arduino serial monitor

Displaying BME280 Sensor values on OLED Display ( Arduino IDE)

In this section, we will see how to display BME280 sensor readings such as Pressure, Temperature, and Humidity values on a 0.96 SSD1306 OLED display using Arduino IDE and ESP32. 

Installing SSD1306 OLED Library in Arduino IDE

To use the OLED display in our project, we have to install the Adafruit SSD 1306 library in Arduino IDE. Follow the steps below to successfully install it.

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 ‘SSD1306’ in the search tab and install the Adafruit SSD1306 OLED library.

Install OLED SSD1306 Library Arduino IDE

You may like this in-depth guide on OLED interfacing with ESP32:

Schematic – OLED with ESP32 and BME280

The table below shows the terminals of the three devices which should be connected together.

OLED DisplayESP32BME280
VCCVCC=3.3VVCC
GNDGNDGND
SCLGPIO22SCL
SDAGPIO21SDA

Assemble the circuit as shown in the schematic diagram below:

BME280 with ESP32 and OLED

As you can see above, we have connected all the VCC terminals with a 3.3V power supply. The SCL terminals are connected with GPIO22 and the SDA terminals are connected with GPIO21. The grounds are also common.

Arduino Sketch to Display BM280 Readings on OLED

Copy the following code to your Arduino IDE and upload it to the ESP32 after assembling the above circuit diagram.

#include <Wire.h>
#include <SPI.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
/*#include <SPI.h>
#define BME_SCK 18
#define BME_MISO 19
#define BME_MOSI 23
#define BME_CS 5*/

#define SEALEVELPRESSURE_HPA (1013.25)

Adafruit_BME280 bme; // I2C
//Adafruit_BME280 bme(BME_CS); // hardware SPI
//Adafruit_BME280 bme(BME_CS, BME_MOSI, BME_MISO, BME_SCK); // software SPI

Adafruit_SSD1306 display = Adafruit_SSD1306(128, 32, &Wire);
unsigned long delayTime;

void setup() {
  Serial.begin(9600);
  Serial.println(F("BME280 test"));
   
  // by default, we'll generate the high voltage from the 3.3v line internally! (neat!)
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  // initialize with the I2C addr 0x3C (for the 128x64)
   // init done
  display.display();
  delay(100);
  display.clearDisplay();
  display.display();
  display.setTextSize(1.2);
  display.setTextColor(WHITE);
  
  bool status;
  // default settings
  // (you can also pass in a Wire library object like &Wire2)
  status = bme.begin(0x76);  
  if (!status) {
    Serial.println("Could not find a valid BME280 sensor, check wiring!");
    while (1);
  }

  Serial.println("-- Default Test --");
  delayTime = 1000;

  Serial.println();
}


void loop() { 
  
  display.setCursor(0,0);
  display.clearDisplay();
  
  Serial.print("Temperature = "); Serial.print(bme.readTemperature()); Serial.println(" *C");
  display.print("Temperature: "); display.print(bme.readTemperature()); display.println(" *C");

  Serial.print("Pressure = "); Serial.print(bme.readPressure() / 100.0F); Serial.println(" hPa");
  display.print("Pressure: "); display.print(bme.readPressure() / 100.0F); display.println(" hPa");

  Serial.print("Humidity = "); Serial.print(bme.readHumidity()); Serial.println(" %");
  display.print("Humidity: "); display.print(bme.readHumidity()); display.println(" %");

  Serial.println();
  display.display();
  delay(1000);
}

How Code Works?

The maximum portion of the code is the same as we have discussed earlier except for the OLED display part. Therefore, we will only explain the OLED display part here.

Include Libraries

We will first include all the required libraries for the BME280 sensor as well as the OLED display which we just installed before.

#include <Wire.h>
#include <SPI.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

Now, we will create another object named display which will be handling the OLED display. Also, define the size of the OLED display by passing arguments to the Adafruit_SSD1306() function.

Adafruit_SSD1306 display = Adafruit_SSD1306(128, 32, &Wire);

This block of code initializes the OLED display.

// by default, we'll generate the high voltage from the 3.3v line internally! (neat!)
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  // initialize with the I2C addr 0x3C (for the 128x32)

We have set the font size as default which is 1. Whenever we increase the size by +1, the pixel resolution of the text increases by 10 in height. Next, we will control the color of the text by using the setTextColor() function and passing WHITE as an argument. If we have a dark background, we will display our text in white and if we have a bright background then we will display the text in black. We do not want to rotate the text, so we are passing 0 as the parameter inside the setRotation() function. The parameter can take in any value from 0,1,2,3 where 0 denotes a rotation of 0 degrees, 1 denotes a rotation of 90 degrees, 2 denotes a rotation of 180 degrees and 3 denotes a rotation of 270 degrees.

// init done
  display.display();
  delay(100);
  display.clearDisplay();
  display.display();
  display.setTextSize(1);
  display.setTextColor(WHITE);

The loop() obtains the readings from the sensors and prints them on the OLED display. The clearDisplay() function wipes off the previous readings from the display after each loop() so that new ones can be printed.

display.clearDisplay();

We will use the setCursor() function to denote the x and the y axis position from where the text should start. We have passed (0,0) as the parameter hence the text starts from the upper left corner.

display.setCursor(0, 0);

Now let’s display the temperature, pressure, and humidity values on the serial monitor and OLED one by one. This block of code displays BME280 sensor values on OLED and updates the value after every 1 second.



  Serial.print("Temperature = "); Serial.print(bme.readTemperature()); Serial.println(" *C");
  display.print("Temperature: "); display.print(bme.readTemperature()); display.println(" *C");

  Serial.print("Pressure = "); Serial.print(bme.readPressure() / 100.0F); Serial.println(" hPa");
  display.print("Pressure: "); display.print(bme.readPressure() / 100.0F); display.println(" hPa");

  Serial.print("Humidity = "); Serial.print(bme.readHumidity()); Serial.println(" %");
  display.print("Humidity: "); display.print(bme.readHumidity()); display.println(" %");

  Serial.println();
  display.display();
  delay(1000);

Demonstration

To see the demonstration of the above code, upload the code to Arduino. But, before uploading code, make sure to select the ESP32 board from Tools Board and also select the correct COM port to which the ESP32 board is connected from Tools Port.

Once the code is uploaded to ESP32, open the serial monitor of Arduino IDE and set the baud rate to 115200. Finally, we can see the BME280 readings on Arduino serial monitor and on the OLED display as follows:

BME280 with ESP32 and display values on OLED

Summary:

In summary, this tutorial provides a comprehensive guide to interfacing the BME280 sensor with an ESP32 using the Arduino IDE. We began by discussing the BME280 sensor and its connections to the ESP32. We then covered the installation of the necessary library in the Arduino IDE. After that, we demonstrated a basic example to showcase the sensor’s capabilities. Finally, we measured temperature, humidity, and pressure, displaying the results on a serial monitor and an SSD1306 OLED display.

If you like this tutorial, you may also like to see other sensors interfacing with ESP32:

If you are using esp-idf instead of Arduino IDE, you can follow this guide:

Leave a Comment