This guide shows how to use the BME280 sensor module with the ESP32 to read pressure, temperature, humidity and estimate altitude using Arduino IDE. The BME280 sensor uses I2C or SPI communication protocol to exchange data with a microcontroller.
We’ll show you how to wire the sensor to the ESP32, install the required libraries, and write a simple sketch that displays the sensor readings.
Recommended reading: ESP32 Web Server with BME280 – Weather Station
Before proceeding with this tutorial you should have the ESP32 add-on installed in your Arduino IDE. Follow the next tutorial to install the ESP32 on the Arduino IDE, if you haven’t already.
You might also like reading other BME280 guides:
- ESP32 Web Server with BME280 – Weather Station
- ESP8266 with BME280 using Arduino IDE
- ESP32/ESP8266 with BME280 using MicroPython
- Arduino Board with BME280
Introducing BME280 Sensor Module
The BME280 sensor module reads barometric pressure, temperature, and humidity. Because pressure changes with altitude, you can also estimate altitude. There are several versions of this sensor module. We’re using the module illustrated in the figure below.
This sensor communicates using I2C communication protocol, so the wiring is very simple. You can use the default ESP32 I2C pins as shown in the following table:
BME280 | ESP32 |
Vin | 3.3V |
GND | GND |
SCL | GPIO 22 |
SDA | GPIO 21 |
There are other versions of this sensor that can use either SPI or I2C communication protocols, like the module shown in the next figure:
If you’re using one of these sensors, to use I2C communication protocol, use the following pins:
BME280 | ESP32 |
SCK (SCL Pin) | GPIO 22 |
SDI (SDA pin) | GPIO 21 |
If you use SPI communication protocol, you need to use the following pins:
BME280 | ESP32 |
SCK (SPI Clock) | GPIO 18 |
SDO (MISO) | GPIO 19 |
SDI (MOSI) | GPIO 23 |
CS (Chip Select) | GPIO 5 |
Parts Required
To complete this tutorial you need the following parts:
You can use the preceding links or go directly to MakerAdvisor.com/tools to find all the parts for your projects at the best price!
Schematic – ESP32 with BME280 using I2C
We’re going to use I2C communication with the BME280 sensor module. For that, wire the sensor to the ESP32 SDA and SCL pins, as shown in the following schematic diagram.
Recommended reading: ESP32 Pinout Reference Guide
Installing the BME280 library
To get readings from the BME280 sensor module you need to use the Adafruit_BME280 library. Follow the next steps to install the library in your Arduino IDE:
Open your Arduino IDE and go to Sketch > Include Library > Manage Libraries. The Library Manager should open.
Search for “adafruit bme280 ” on the Search box and install the library.
Installing the Adafruit_Sensor library
To use the BME280 library, you also need to install the Adafruit_Sensor library. Follow the next steps to install the library in your Arduino IDE:
Go to Sketch > Include Library > Manage Libraries and type “Adafruit Unified Sensor” in the search box. Scroll all the way down to find the library and install it.
After installing the libraries, restart your Arduino IDE.
Reading Pressure, Temperature, and Humidity
To read pressure, temperature, and humidity we’ll use a sketch example from the library.
After installing the BME280 library, and the Adafruit_Sensor library, open the Arduino IDE and, go to File > Examples > Adafruit BME280 library > bme280 test.
/*********
Complete project details at https://randomnerdtutorials.com
*********/
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.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
unsigned long delayTime;
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 find a valid BME280 sensor, check wiring!");
while (1);
}
Serial.println("-- Default Test --");
delayTime = 1000;
Serial.println();
}
void loop() {
printValues();
delay(delayTime);
}
void printValues() {
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();
}
We’ve made a few modifications to the sketch to make it fully compatible with the ESP32.
How the Code Works
Continue reading this section to learn how the code works, or skip to the “Demonstration” section.
Libraries
The code starts by including the needed libraries: the wire library to use I2C, and the Adafruit_Sensor and Adafruit_BME280 libraries to interface with the BME280 sensor.
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
SPI communication
As we’re going to use I2C communication, the following lines that define the SPI pins are commented:
/*#include <SPI.h>
#define BME_SCK 18
#define BME_MISO 19
#define BME_MOSI 23
#define BME_CS 5*/
Note: if you’re using SPI communication, you use the ESP32 SPI pins. For SPI communication on the ESP32 you can use either the HSPI or VSPI pins, as shown in the following table.
SPI | MOSI | MISO | CLK | CS |
HSPI | GPIO 13 | GPIO 12 | GPIO 14 | GPIO 15 |
VSPI | GPIO 23 | GPIO 19 | GPIO 18 | GPIO 5 |
Sea level pressure
A variable called SEALEVELPRESSURE_HPA is created.
#define SEALEVELPRESSURE_HPA (1013.25)
This variable saves the pressure at the sea level in hectopascal (is equivalent to milibar). This variable is used to estimate the altitude for a given pressure by comparing it with the sea level pressure. This example uses the default value, but for more accurate results, replace the value with the current sea level pressure at your location.
I2C
This example uses I2C communication protocol by default. As you can see, you just need to create an Adafruit_BME280 object called bme.
Adafruit_BME280 bme; // I2C
To use SPI, you need to comment this previous line and uncomment one of the following lines depending on whether you’re using hardware or software SPI (hardware SPI uses the ESP32 default HSPI pins; software SPI uses the pins defined on the code).
//Adafruit_BME280 bme(BME_CS); // hardware SPI
//Adafruit_BME280 bme(BME_CS, BME_MOSI, BME_MISO, BME_SCK); // software SPI
setup()
In the setup(), start a serial communication:
Serial.begin(9600);
And initialize the sensor:
status = bme.begin(0x76);
if (!status) {
Serial.println("Could not find a valid BME280 sensor, check wiring!");
while (1);
}
We initialize the sensor with the 0x76 address. In case you’re not getting sensor readings, check the I2C address of your sensor. With the BME280 sensor wired to your ESP32, run this I2C scanner sketch to check the address of your sensor. Then, change the address if needed.
Printing values
In the loop(), the printValues() function reads the values from the BME280 and prints the results in the Serial Monitor.
void loop() {
printValues();
delay(delayTime);
}
Reading temperature, humidity, pressure, and estimate altitude is as simple as using the following methods on the bme object:
- bme.readTemperature() – reads temperature in Celsius;
- bme.readHumidity() – reads absolute humidity;
- bme.readPressure() – reads pressure in hPa (hectoPascal = millibar);
- bme.readAltitude(SEALEVELPRESSURE_HPA) – estimates altitude in meters based on the pressure at the sea level.
Demonstration
Upload the code to your ESP32, and open the Serial Monitor at a baud rate of 9600. Press the on-board RST button to run the code. You should see the readings displayed on the Serial Monitor.
ESP32 Web Server Weather Station with BME280 Sensor
The BME280 sensor measures temperature, humidity, and pressure. So, you can easily build a compact weather station and monitor the measurements using a web server built with your ESP32.
To do that, you can follow this tutorial: ESP32 Web Server with BME280 Weather Station
Wrapping Up
This article was a quick guide on how to get pressure, temperature and humidity readings from a BME280 sensor with the ESP32 using Arduino IDE.
Now, you can take this project further and display your sensor readings in an OLED display; create a datalogger; or create a web server to display the latest sensor readings. Here’s a list of projects that might help with these ideas:
- ESP32 Publish Sensor Readings to Google Sheets
- ESP32 OLED Display with Arduino IDE
- ESP32 Web Server with BME280 – Weather Station
- Low Power Weather Station Datalogger (MicroPython)
- ESP32/ESP8266 Insert Data into MySQL Database using PHP and Arduino IDE
If you want to learn more about the ESP32, make sure you enroll in our course: “Learn ESP32 with Arduino IDE“.
Thanks for reading.
That is a must for me, thanks for the guide
When trying to connect with my browser, I get this on the serial monitor.
What could be the problem?
WiFi connected.
IP address:
172.20.10.2
New Client.
GET / HTTP/1.1
Accept: text/html, application/xhtml+xml, image/jxr, */*
Accept-Language: en-US,en-GB;q=0.8,en-DE;q=0.5,en;q=0.3
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko
Accept-Encoding: gzip, deflate
Host: 172.20.10.2
Connection: Keep-Alive
Exception (28):
epc1=0x40202b6c epc2=0x00000000 epc3=0x00000000 excvaddr=0x00000000 depc=0x00000000
>>>stack>>>
ctx: cont
sp: 3ffffd80 end: 3fffffc0 offset: 01a0
3fffff20: 3ffe88bd 3ffe8a63 3fffff50 40203714
3fffff30: 0000000a 3ffe8a63 3ffee768 40202c50
3fffff40: 3ffe85d9 3ffe8a63 3ffee908 402012e7
3fffff50: 402063a8 00000000 00001388 4020fa2f
3fffff60: 00000000 3ffefcfc 3fff000c 0000005f
3fffff70: ff2f5054 3ffee7b0 3ffee908 4020267f
3fffff80: 0000000a 3ffee7b0 3ffee908 402010d1
3fffff90: 00000000 00000000 00000001 3ffee970
3fffffa0: 3fffdad0 00000000 3ffee940 40203fc8
3fffffb0: feefeffe feefeffe 3ffe8510 40100529
<<<stack<<<
ets Jan 8 2013,rst cause:2, boot mode:(3,7)
load 0x4010f000, len 1384, room 16
tail 8
chksum 0x2d
csum 0x2d
v8b899c12
~ld
Again, Great tutorial! With a little fiddling, able to have temp in Fahrenheit, Pressure in InHg, and altitude in ft. 🙂
What if the server uses https?
Thanks
Paulo
I had to replace the line
status = bme.begin(0x76);
with
status = bme.begin();
to make it work
Hi, trying to follow this. I understand the code to some degree. Reading different sites examples helps.
Question on the BME280. I have it connected to an ESP32 30 pin board. I copied the code, saved it as BME280.py and BMEreadout.main
I have the option of pressing the boot or EN button? I’ve tried both with only the EN returning some error? I never see the readout? Any thoughts?
Hi.
If you want to use the BME280 with MicroPython, this is the tutorial that you should follow: https://randomnerdtutorials.com/micropython-bme280-esp32-esp8266/
Regards,
Sara
this code is C not python. you can use it with Arduino IDE. to use it as a python program you’ll have to install circuit python or micropython on you dev board first, then convert it to python and use the correct python support library.
otherwise copy and paste it into the Arduino IDE and save it, then up load to the board.
Big thanks for the I2C Scanner Checker app. Will put it in my toolbox!
Following this tutorial I have setup stockton.co.z/lcars/ws.php to show not only temperature, humidity and pressure in my South African location but also, with the benefit of Raspberry devices, wind speed and rain fall.
Other than the bme280 readings either overflowing or going negative about once a week system looks reasonable reliable. Reboot fixes that until I find the cause.
BTW My server is a Raspberry Pi V4.
Thank you for this tutorial – it helped me to get up to speed with ESP32 a lot.
I just want to make you aware that the temperature measurement in the BME280 and BMP280 is mainly for internal use in the sensor to compensate for temperature effects on the pressure and humidity signal. I made the experience that it can be some deg. C off from the real value! So, you either need to calibrate it in yourself or – if temperature is important for the project, take a dedicated temperature sensor like MCP9808 which are made for temperature measurement.
Hello
A long time ago I made a weather forecast montage with the BMP180 which works quite well.
http://seta43.duckdns.org/predi.html
All the best
Juan
Español.
Hola
Hace tiempo realice un montaje de prediccion tiempo con el BMP180 que funciona bastante bien.
http://seta43.duckdns.org/predi.html
Un saludo
Juan
Thanks for sharing.
Regards,
Sara
Does anyone have CAD drawings for a ESP-32 connected to an SD card & the BME280? I would like to order a PCB with these so that I don’t have to hardwire the components.
I’am getting “nan” readings for the values. What am I missing or doing wrong
Hi.
Read this: https://randomnerdtutorials.com/solved-could-not-find-a-valid-bme280-sensor/
Regards,
Sara
Hi, thanks for the tutorial. Kindly help me with the following problem.
My serial monitor is showing nothing though I checked the sensor address and the boud rate of the monitor as well. What could be the problem.
Hi.
After uploading the code and making sure the serial monitor is set to the right baud rate, press the on-board RESET button so that it starts running the code.
If that doesn’t work, read our BME280 troubleshooting guide: https://randomnerdtutorials.com/solved-could-not-find-a-valid-bme280-sensor/
Regards,
Sara
Hello.
I was having unreliable results from using a very cheap BMP/e280 sensor.
After a lot of trial and error, I found it worked better with a BMP280I2C driver and modified the code accordingly.
I display the results on a TFT display and combined results obtained from Openweathermap website.
Thank you so much in getting me started.
I highly recommend the TFT_eSPI driver and GitHub site for loads of advice on my IL9341 TFT display.
Kind regards
Melvin Lee
Hi Mel.
We cover that BMP280 situation in this article: https://randomnerdtutorials.com/solved-could-not-find-a-valid-bme280-sensor/#fake-bme280
Regards,
Sara
Neither of the sensors that you show in the article are labelled Mosi or Miso so why use those in your code? My sensor has SCL, SDA, CSB and SDO. So which pins do I connect these to?
Great guides and this is a little off topic as it concerns the BME680 on ESP32 not ESP8266
I am trying to get the BME680 working with the CYD (Great guide by the way) since there is no Default SDA at 21 need to use alt pins no possible work around the BME280 Works fine with the CYD but same code with BME689 does not??
Using the code in this guide as a starting point I got the BME680 working with no problems on the default pins. I was also able to get both a BME280 and a BME680 working at the same time verifying Wiring, Address, Board etc.
Trying your alt pin method (and every other I could find) have been unable to get the the BME680 to work on alt pins.
The below sums it up I can send remaining support code but its pretty simple.
//I2CBME.begin(I2C_SDA, I2C_SCL, 100000); // commented to get default to work
//status1 = bme1.begin(0x77 , &I2CBME); // This reports Check wiring
//status2 = bme2.begin(0x76 , &I2CBME); // This works and produces output
status1 = bme1.begin(0x77); // This works and provides output
status2 = bme2.begin(0x76); // This works and provides output
if (!status1) { Serial.println(“Could not find a valid BME680 sensor, check wiring!”);}
if (!status2) { Serial.println(“Could not find a valid BME280 sensor, check wiring!”);}
Any help or insite would be great.
By the way Adding the BME280 to the CYD guide I think would be a great guide.
Curently I have it running along with 2 20X40 lcd displays for Model railroading applications.