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
| Parameter | Value |
|---|---|
| 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) |
| Interface | I2C or SPI |
| I2C address | 0x76 (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
| Component | Qty | Notes | Buy |
|---|---|---|---|
| ESP32 dev board | 1 | AliExpress | Amazon.de .co.uk .com | |
| BME280 sensor module | 1 | AliExpress | Amazon.de .co.uk .com | |
| Breadboard | 1 | AliExpress | Amazon.de .co.uk .com | |
| Jumper wires | 4 | AliExpress | 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 Pin | ESP32 Pin | Notes |
|---|---|---|
| VIN / VCC | 3.3V | Use 3.3V (some modules accept 5V via onboard regulator) |
| GND | GND | |
| SDA | GPIO 21 | Default I2C data line on ESP32 |
| SCL | GPIO 22 | Default 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:
- Adafruit BME280 Library by Adafruit -- provides the main sensor interface
- Adafruit Unified Sensor by Adafruit -- a dependency
To install:
- Go to Sketch > Include Library > Manage Libraries...
- Search for Adafruit BME280 and install it
- 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
| Problem | Possible Cause | Solution |
|---|---|---|
| "Could not find BME280" | Wrong I2C address | Try 0x77 instead of 0x76 |
| "Could not find BME280" | Wiring issue | Verify SDA/SCL connections; make sure VCC and GND are correct |
| Humidity always reads 0% | You have a BMP280, not a BME280 | Check the chip marking on your module |
| Pressure reads but seems wrong | Not at sea level | The raw reading is station pressure, not sea-level adjusted |
| Temperature reads a few degrees high | Self-heating from the chip | Mount the sensor away from heat sources; add an offset in code |
| I2C communication errors | Missing pull-ups or bus conflict | Most 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