Documentation

BME280 Environmental Sensor - Raspberry Pi, Arduino, ESP32 I2C Humidity, Pressure, and Temperature Measurement
Documentation / BME280 Environmental Sensor - Raspberry Pi, Arduino, ESP32 I2C Humidity, Pressure, and Temperature Measurement

BME280 Environmental Sensor - Raspberry Pi, Arduino, ESP32 I2C Humidity, Pressure, and Temperature Measurement

Overview

The BME280 is a precision environmental sensor from Bosch Sensortec that measures temperature, humidity, and barometric pressure in a single tiny package. It communicates via I2C (or SPI), sips very little power, and delivers laboratory-grade readings — making it the go-to sensor for weather stations, indoor air quality monitors, drone altimeters, IoT gateways, and HVAC projects.

ShillehTek's pre-soldered BME280 module comes ready to use with headers already attached, runs on 3.3V or 5V (an onboard regulator and level shifter handle both), and exposes the four I2C pins plus CSB and SDO for I2C address selection. The default I2C address is 0x76 (SDO pulled to GND), and pulling SDO to VCC switches it to 0x77 — which lets you run two BME280s on the same bus.

This manual walks you through specifications, the pinout, wiring for Arduino, ESP32, Raspberry Pi, and the Pico, a working "hello world" code example for each platform, and common troubleshooting questions.

At a Glance

Voltage
3.3V - 5V
Interface
I2C / SPI
I2C Address
0x76 / 0x77
Measures
Temp / Humidity / Pressure
Pressure Range
300 - 1100 hPa
Pins
6 (Pre-Soldered)

Specifications

Parameter Value
Operating Voltage 3.3V - 5V (onboard regulator)
Sensor IC Bosch BME280
Communication I2C (default) or SPI
I2C Addresses 0x76 (SDO = GND) / 0x77 (SDO = VCC)
Temperature Range -40°C to +85°C (±1.0°C accuracy)
Humidity Range 0 - 100% RH (±3% accuracy)
Pressure Range 300 - 1100 hPa (±1 hPa accuracy)
Altitude Resolution ~0.25 m (from pressure)
Current Draw ~3.6 μA @ 1 Hz sampling
Pin Count 6 (VCC, GND, SCL, SDA, CSB, SDO)
Board Format Pre-soldered with male headers

Pinout Diagram

BME280 Pinout Diagram

Wiring Guide

Arduino Wiring

The BME280 module has an onboard regulator and level shifter, so you can safely power it from the Arduino Uno's 5V rail. Only four wires are needed for basic I2C operation.

Module Pin Arduino Pin
VCC 5V
GND GND
SCL A5 (SCL)
SDA A4 (SDA)
CSB Not connected (pulls high for I2C)
SDO Not connected or GND (address 0x76)
Tip: The module has built-in I2C pull-ups, so external resistors are not required for most setups.

ESP32 Wiring

Connect the BME280 to the ESP32's default I2C bus. The ESP32 is a 3.3V device, but the module's regulator handles both 3.3V and 5V safely.

Module Pin ESP32 Pin
VCC 3.3V
GND GND
SCL GPIO 22
SDA GPIO 21
CSB Not connected
SDO Not connected or GND
Info: Any free GPIO pair can be remapped as I2C on the ESP32 using Wire.begin(sda, scl).

Raspberry Pi Wiring

Use the Raspberry Pi's hardware I2C on GPIO 2 and GPIO 3. Enable I2C via sudo raspi-config before running your code.

Module Pin Raspberry Pi Pin
VCC 3.3V (Pin 1)
GND GND (Pin 6)
SCL GPIO 3 (Pin 5, SCL)
SDA GPIO 2 (Pin 3, SDA)
CSB Not connected
SDO Not connected or GND
Tip: Verify the sensor is detected with i2cdetect -y 1. You should see 76 (or 77 if SDO is tied high).

Raspberry Pi Pico Wiring

Connect the BME280 to the Pico's I2C0 bus on GP0 and GP1. MicroPython or C SDK both support I2C natively.

Module Pin Pico Pin
VCC 3.3V (Pin 36)
GND GND (Pin 38)
SCL GP1 (Pin 2, I2C0 SCL)
SDA GP0 (Pin 1, I2C0 SDA)
CSB Not connected
SDO Not connected or GND
Info: The Pico has two I2C peripherals. You can also use I2C1 on GP2/GP3 if I2C0 is occupied.

Code Examples

Arduino

bme280_read.ino
// BME280 - Read temperature, humidity, and pressure
// Requires: Adafruit BME280 Library + Adafruit Unified Sensor

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

Adafruit_BME280 bme; // I2C

void setup() {
  Serial.begin(9600);
  while (!Serial);

  // 0x76 is default; try 0x77 if SDO is tied to VCC
  if (!bme.begin(0x76)) {
    Serial.println("Could not find BME280 sensor. Check wiring!");
    while (1);
  }
  Serial.println("BME280 ready.");
}

void loop() {
  Serial.print("Temp: ");
  Serial.print(bme.readTemperature());
  Serial.println(" *C");

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

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

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

ESP32

bme280_esp32.ino
// BME280 on ESP32 via I2C (GPIO21 SDA, GPIO22 SCL)
// Requires: Adafruit BME280 Library

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

Adafruit_BME280 bme;

void setup() {
  Serial.begin(115200);
  Wire.begin(21, 22); // SDA, SCL

  if (!bme.begin(0x76)) {
    Serial.println("BME280 not found. Check wiring/address.");
    while (1);
  }
  Serial.println("BME280 ready.");
}

void loop() {
  Serial.printf("Temp: %.2f C | Humidity: %.2f %% | Pressure: %.2f hPa\n",
                bme.readTemperature(),
                bme.readHumidity(),
                bme.readPressure() / 100.0F);
  delay(1000);
}

Raspberry Pi

bme280_read.py
# BME280 on Raspberry Pi via I2C
# Install: pip install RPi.bme280 smbus2
# Enable I2C first: sudo raspi-config -> Interface Options -> I2C

import smbus2
import bme280
import time

port = 1           # I2C bus 1 on modern Pi
address = 0x76     # 0x77 if SDO is tied high
bus = smbus2.SMBus(port)

calibration_params = bme280.load_calibration_params(bus, address)

while True:
    data = bme280.sample(bus, address, calibration_params)
    print(f"Temp: {data.temperature:.2f} C")
    print(f"Humidity: {data.humidity:.2f} %")
    print(f"Pressure: {data.pressure:.2f} hPa")
    print("-" * 30)
    time.sleep(1)

Raspberry Pi Pico (MicroPython)

bme280_pico.py
# BME280 on Raspberry Pi Pico via I2C0 (GP0 SDA, GP1 SCL)
# Upload a bme280.py driver module to the Pico filesystem first.

from machine import Pin, I2C
import bme280
import time

i2c = I2C(0, sda=Pin(0), scl=Pin(1), freq=100000)
print("I2C scan:", [hex(d) for d in i2c.scan()])

sensor = bme280.BME280(i2c=i2c, address=0x76)

while True:
    t, p, h = sensor.read_compensated_data()
    print("Temp:    {:.2f} C".format(t / 100))
    print("Pressure: {:.2f} hPa".format(p / 25600))
    print("Humidity: {:.2f} %".format(h / 1024))
    print("-" * 30)
    time.sleep(1)

Frequently Asked Questions

What is the default I2C address of the BME280?
The default address is 0x76 when the SDO pin is left unconnected or tied to GND. Tie SDO to VCC to switch to 0x77. This lets you run two BME280 sensors on the same bus.
What's the difference between the BME280 and the BMP280?
The BME280 measures temperature, humidity, and pressure, while the BMP280 only measures temperature and pressure. If you need humidity readings, make sure you have the BME280.
Why is my temperature reading a few degrees too high?
The BME280 chip generates a small amount of self-heating, especially when sampling at high rates. Lower the sampling frequency (e.g., once per second instead of continuously), and keep it away from heat sources like regulators, ESP32 RF sections, or Pi SoCs for best accuracy.
Can I calculate altitude from this sensor?
Yes. Most libraries expose a readAltitude() function that converts pressure to altitude using a reference sea-level pressure. Accuracy depends on calibrating with the current local pressure (typically found on a weather website).
Can I run this at 3.3V and 5V?
Yes — the ShillehTek pre-soldered module has an onboard regulator and level shifter, so both 3.3V and 5V power rails are safe. The bare BME280 chip itself is 3.3V only.
I2C scan returns nothing — what should I check?
Verify VCC and GND first, then confirm SDA/SCL aren't swapped. On Raspberry Pi, run sudo raspi-config to enable I2C, then use i2cdetect -y 1. If you still see nothing, try pulling SDO to GND explicitly to force address 0x76.

Related Tutorials