BME280 Environment Sensor

How to use the BME280 temperature, humidity, and pressure sensor with ESP32

The BME280 is a 3-in-1 environmental sensor made by Bosch that measures temperature, humidity, and barometric pressure in a single compact package. It communicates over I2C (or SPI), offers excellent accuracy, and is far more responsive than the DHT-series sensors. If you want one sensor that covers the most common environmental measurements, the BME280 is an outstanding choice and great value for money.

This guide uses the ESP32-WROOM-32 DevKit. Pin labels may differ on your board -- check your board's pinout diagram.

🔗Key Specs

ParameterValue
Temperature range$-40$ to $+85\,\text{°C}$
Temperature accuracy$\pm 1\,\text{°C}$
Humidity range$0$ to $100\,\%\,\text{RH}$
Humidity accuracy$\pm 3\,\%\,\text{RH}$
Pressure range$300$ to $1100\,\text{hPa}$
Pressure accuracy$\pm 1\,\text{hPa}$
Supply voltage$1.8$ to $3.6\,\text{V}$ (module typically has onboard regulator for 3.3--5 V input)
InterfaceI2C or SPI
I2C address0x76 (default) or 0x77

BMP280 vs. BME280: These two sensors look nearly identical and are often confused. The BMP280 measures only temperature and pressure (no humidity). The BME280 measures all three. Check the text printed on the tiny chip on your module -- "BME280" includes humidity, "BMP280" does not. If your board reads $0\,\%\,\text{RH}$ for humidity, you likely have a BMP280.

Alternatives: If humidity is your primary measurement, the SHT31 offers better accuracy ($\pm 2\,\%$ vs $\pm 3\,\%$ RH). The newer SHT4x series is even more precise. If you don't need pressure, any of these are drop-in replacements with the same I2C wiring. See our sensor comparison guide for a full breakdown of the options.

🔗What You'll Need

ComponentQtyNotesBuy
ESP32 dev board1AliExpress | Amazon.de .co.uk .com
BME280 sensor module1AliExpress | Amazon.de .co.uk .com
Breadboard1AliExpress | Amazon.de .co.uk .com
Jumper wires4AliExpress | Amazon.de .co.uk .com

Links marked Amazon/AliExpress are affiliate links. We may earn a small commission at no extra cost to you.

🔗Wiring (I2C)

The BME280 is most commonly used over I2C, which only requires two data lines plus power.

BME280 PinESP32 PinNotes
VIN / VCC3.3VUse 3.3V (some modules accept 5V via onboard regulator)
GNDGND
SDAGPIO 21Default I2C data line on ESP32
SCLGPIO 22Default I2C clock line on ESP32

Pin labels, GPIO numbers, and ADC channels vary between ESP32 boards. GPIOs 21 (SDA) and 22 (SCL) are the default I2C pins on most ESP32-WROOM-32 DevKit boards, but your board may differ. Always check your board's pinout diagram.

🔗I2C Address

Most BME280 breakout modules default to address 0x76. Some modules use 0x77 instead, depending on how the SDO pin is wired on the board. If the sensor is not detected, try both addresses in your code.

If you are not sure what address your sensor uses, you can run an I2C scanner sketch to find all devices on the bus.

🔗Required Libraries

Install the following through the Arduino Library Manager:

  1. Adafruit BME280 Library by Adafruit -- provides the main sensor interface
  2. Adafruit Unified Sensor by Adafruit -- a dependency

To install:

  1. Go to Sketch > Include Library > Manage Libraries...
  2. Search for Adafruit BME280 and install it
  3. When prompted, also install the Adafruit Unified Sensor dependency

🔗Code Example

This sketch reads temperature, humidity, and pressure from the BME280 and prints them to the Serial Monitor.

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

#define BME280_ADDRESS 0x76  // Change to 0x77 if needed

Adafruit_BME280 bme;

void setup() {
    Serial.begin(115200);
    Serial.println("BME280 Sensor Test");

    if (!bme.begin(BME280_ADDRESS)) {
        Serial.println("Error: Could not find BME280 sensor.");
        Serial.println("Check wiring or try address 0x77.");
        while (1) delay(10);  // Halt
    }

    Serial.println("BME280 sensor found.");
}

void loop() {
    float temperature = bme.readTemperature();       // °C
    float humidity    = bme.readHumidity();           // %
    float pressure    = bme.readPressure() / 100.0F;  // hPa

    Serial.print("Temperature: ");
    Serial.print(temperature, 1);
    Serial.print(" °C  |  Humidity: ");
    Serial.print(humidity, 1);
    Serial.print(" %  |  Pressure: ");
    Serial.print(pressure, 1);
    Serial.println(" hPa");

    delay(2000);
}

Tip: The readPressure() function returns the value in Pascals (Pa). Dividing by $100$ converts it to hectopascals (hPa), which is the standard unit used in weather reports. $1\,\text{hPa} = 1\,\text{mbar}$.

🔗Estimating Altitude

Barometric pressure decreases as altitude increases. The BME280 library includes a function to estimate altitude based on the current pressure reading and a reference sea-level pressure:

float altitude = bme.readAltitude(1013.25);  // 1013.25 hPa = standard sea-level pressure
Serial.print("Approx. altitude: ");
Serial.print(altitude, 1);
Serial.println(" m");

For accurate altitude readings, replace 1013.25 with the actual current sea-level pressure for your location (available from weather services). Without this correction, altitude estimates can be off by tens of meters.

🔗How It Works

The BME280 contains three separate sensing elements on a single MEMS chip:

  • A resistive temperature sensor for temperature
  • A capacitive humidity sensor for relative humidity
  • A piezoresistive pressure sensor for barometric pressure

When you request a reading, the sensor performs an internal analog-to-digital conversion and applies factory calibration data. The result is then transmitted to the ESP32 over the I2C bus. The entire process is fast -- you can read all three values many times per second, unlike the DHT22 which requires a $2\,\text{s}$ minimum interval.

🔗Troubleshooting

ProblemPossible CauseSolution
"Could not find BME280"Wrong I2C addressTry 0x77 instead of 0x76
"Could not find BME280"Wiring issueVerify SDA/SCL connections; make sure VCC and GND are correct
Humidity always reads 0%You have a BMP280, not a BME280Check the chip marking on your module
Pressure reads but seems wrongNot at sea levelThe raw reading is station pressure, not sea-level adjusted
Temperature reads a few degrees highSelf-heating from the chipMount the sensor away from heat sources; add an offset in code
I2C communication errorsMissing pull-ups or bus conflictMost breakout boards include pull-ups; check for address conflicts

🔗Next Steps

  • Build a weather station that logs temperature, humidity, and pressure trends over time
  • Calculate and display altitude from the pressure readings
  • Combine the BME280 with a display to create a desktop environmental monitor
  • Send readings over WiFi to an MQTT broker or cloud dashboard