BMP280 Pinout, I²C Address, SPI Wiring, Schematic and ESP32 Arduino Example

BMP280 breakout pinout and 0x76/0x77 I2C address configuration, I2C/SPI ESP32 wiring, functional schematic, chip-ID and Arduino code.

The Bosch BMP280AliExpress price measures atmospheric pressure and its own sensor temperature over I²C or SPI. It is popular in ESP32AliExpress price weather stations, low-power sensors and projects that estimate changes in altitude from pressure. Unlike the similarly named BME280AliExpress price, a BMP280 does not measure humidity. The bare sensor, the Adafruit #2651 breakout and inexpensive six-pin GY-BMP280 modules are also not electrically identical—a difference that matters for power and address selection.

Quick start: for the Adafruit BMP280 #2651 STEMMA QT breakout, connect ESP32 3V3 → VIN, GND → GND, GPIO21 → SDI/SDA and GPIO22 → SCK/SCL. Leave CS and SDO unconnected when using the board’s factory I²C configuration. Scan for 0x77 first, then 0x76. The main example below initializes those pins explicitly and tries both valid addresses.

Important: many generic modules place SDO low by default, yielding 0x76. Some have no onboard regulator or level shifters; for a 3.3 V ESP32 assume 3.3 V only unless the specific module schematic proves otherwise. Do not connect a 5 V I²C pull-up to ESP32 GPIO.

Adafruit BMP280 seven signal pinout VIN 3Vo GND SCK SDO SDI CS alongside generic six pin BMP280 module
Adafruit #2651 has seven header signals, including regulated 3Vo output, while generic six-pin BMP280 modules use different header labels and may lack level shifting.

BMP280 specifications: what it measures and what it does not

SpecificationBMP280 / real-world interpretation
MeasurementsAbsolute barometric pressure and sensor temperature; no humidity channel
Pressure range300–1100 hPa according to Bosch’s BMP280 datasheet
Temperature operating range−40 to +85 °C; observed temperature can be influenced by nearby electronics
Pressure accuracyTypically ±1 hPa absolute under specified conditions; relative precision can be better
Bus interfacesI²C or 3-/4-wire SPI; use 4-wire SPI for the Arduino example
I²C addresses0x76 when SDO low; 0x77 when SDO high
Identity register0xD0 returns 0x58 for BMP280; BME280 commonly returns 0x60
Sensor IC electrical supplyVDD is about 1.71–3.6 V; VDDIO is a separate low-voltage digital supply
Adafruit #2651 VINBreakout VIN accepts 3–5 V due to its regulator/level shifting; choose 3.3 V with ESP32
ModesSleep, forced single measurement, normal repeated measurement
FilteringConfigurable oversampling, IIR filtering and standby timing
Altitude estimateComputed from pressure plus an independently supplied sea-level pressure; not a GPS altitude

Pressure is often displayed in hPa or mbar, but the Adafruit Arduino method bmp.readPressure() returns pascals (Pa). Divide by 100 for hPa. For example, 101,325 Pa is 1,013.25 hPa. A forecast-quality weather station should also account for local pressure trends, sensor placement and the regional sea-level pressure reference.

Board layout: Adafruit BMP280 #2651 versus generic GY-BMP280

Adafruit #2651: exactly seven breakout header pins

The Adafruit board’s top-view header labels are VIN, 3Vo, GND, SCK, SDO, SDI, CS; the front photograph and documentation identify these names. There are two STEMMA QT connectors for convenient I²C cabling on recent revisions. They use the same bus as the SDA and SCL functions on the header.

Adafruit headerMeaningWhen using an ESP32
VINInput to onboard regulator and level shiftingESP32 3V3
3VoBreakout regulator’s 3.3 V output; not a second inputNormally leave unconnected
GNDCommon 0 V referenceESP32 GND
SCKSPI clock, or I²C SCLESP32 GPIO22 for I²C; GPIO18 for example SPI
SDOSPI MISO; in I²C mode selects address via high/lowLeave as factory default (typically 0x77), or pull to ground for 0x76
SDISPI MOSI, or I²C SDAESP32 GPIO21 for I²C; GPIO23 for example SPI
CSActive-low SPI chip select / mode selectionLeave in board’s default I²C condition, or ESP32 GPIO5 for example SPI

The 3Vo connection is an output on the Adafruit board. Do not mistake it for a second place to apply arbitrary external power. Conversely, VIN on a small no-regulator GY-BMP280 may connect almost directly to the sensor’s supply rail. Board markings alone do not establish that a breakout can accept 5 V.

Generic GY-BMP280: inspect the PCB rather than assuming the same order

Common six-pin variants expose VCC, GND, SCL/SCK, SDA/SDI, CSB and SDO. Headers can be mirrored or rearranged between brands; the drawing shows signal names, not an unverified universal physical orientation. A few boards add a regulator; a small 3.3 V board may not. For direct ESP32 use, 3.3 V is the safer default and both devices must share ground.

How to choose I²C address 0x76 or 0x77

The BMP280 chip has only two normal I²C addresses because its SDO pin selects the low address bit:

SDO level in I²C modeResulting 7-bit I²C addressTypical use
GND (LOW)0x76Common inexpensive GY-BMP280 variants, or changed address on Adafruit
VDDIO (HIGH)0x77Adafruit #2651 factory default and many other modules

Adafruit #2651: the board is normally shipped as 0x77 and a rear Addr jumper is visible on documented board photographs; on the matching revision, the bridge connects the address selection to the alternate setting. You can also use the labelled SDO signal as documented. Inspect the exact board revision and test with an I²C scanner before soldering. Generic boards: SDO may be hard-wired via a resistor or an accessible pad—do not assume that an arbitrary rear bridge is an address jumper.

The CSB/CS pin is a separate issue: Bosch recommends CSB be tied to VDDIO for I²C. If the chip detects CSB LOW during startup, it may remain in SPI mode. Leaving a raw-chip CSB pin floating is not a sound design; the Adafruit breakout’s default configuration handles it, but raw-chip wiring must explicitly pull CSB high. Similarly, Bosch warns that SDO must not float when you select an I²C address.

BMP280 SDO address-select circuit 0x76 vs 0x77 with Adafruit rear Addr jumper and CSB high for I2C
Changing SDO selects 0x76 or 0x77. The Adafruit #2651 address bridge and generic-board address options must be verified separately. CSB must be held high for I²C.

BMP280 functional schematic and safe logic levels

The bare Bosch sensor is an eight-pad LGA component. Its pads are 1 GND, 2 CSB, 3 SDI, 4 SCK, 5 SDO, 6 VDDIO, 7 GND and 8 VDD. The sensor is not a 5 V chip; the 5 V tolerance mentioned on some retail breakouts comes from separate onboard regulator and interface circuitry.

For a chip-level 3.3 V I²C reference: power VDD and VDDIO from an appropriate 3.3 V rail, decouple each with a 100 nF capacitor to ground close to the IC, connect SDA to SDI (pin 3) and SCL to SCK (pin 4) with suitable pull-ups to 3.3 V, tie CSB high, and tie SDO definitely high or low. Verify the pull-up population already present on the breakout before adding resistors. The image below gives the verified chip pinout rather than an AI-generated electrical schematic. Use the Bosch datasheet for the complete reference circuit.

Bosch BMP280 8 pad LGA top view exact pinout VDD VDDIO two GND CSB SDI SCK and SDO without wiring
Bosch BMP280 LGA-8 top-view pinout, with verified physical pad positions. Power and I²C requirements are described in the text; no wires are depicted.

ESP32 pin assignments: I²C and four-wire SPI

I²C wiring for a classic ESP32-WROOM DevKit

ESP32 DevKitAdafruit BMP280 #2651Generic 3.3 V BMP280
3V3VINVCC (only if board accepts 3.3 V)
GNDGNDGND
GPIO21 (SDA)SDISDA / SDI
GPIO22 (SCL)SCKSCL / SCK
Optional address selectSDO LOW for 0x76; otherwise use documented defaultTie SDO LOW or HIGH according to desired address
I²C mode selectLeave CS in documented factory I²C stateCSB HIGH

GPIO21 and GPIO22 are examples for the classic ESP32-WROOM family. On an ESP32-C3, C6, S3, etc., choose valid GPIOs appropriate to that board and update Wire.begin(SDA,SCL). Avoid 5 V signal levels on an ESP32 even if the sensor breakout can accept 5 V with other controllers.

Four-wire SPI wiring

ESP32 classic exampleBMP280 breakout signalSPI role
3V3VIN (Adafruit) / supported 3.3 V board VCCLogic power
GNDGNDCommon ground
GPIO18SCKClock
GPIO23SDIESP32 MOSI → sensor data in
GPIO19SDOSensor data out → ESP32 MISO
GPIO5CSActive-low chip select

In SPI mode, SDO is MISO rather than an I²C address setting. SPI shares SCK, MOSI and MISO across devices, while each sensor gets its own CS pin. Software must create an SPI-based BMP280 instance. Do not leave the address jumper strapped in a way that could interfere with an SPI MISO signal; consult the breakout schematic when switching modes.

ESP32 BMP280 wire free pin mapping tables for I2C GPIO21 GPIO22 and SPI GPIO18 GPIO23 GPIO19 GPIO5
Wire-free ESP32 pin assignment tables for I²C and SPI. All mappings refer to the Adafruit BMP280 breakout and a classic ESP32 DevKit.

Arduino IDE: read BMP280 pressure, temperature and altitude

Install the Adafruit BMP280 Library using Arduino IDE Library Manager, together with its prompted Adafruit BusIO and Adafruit Unified Sensor dependencies. The following example is for a classic ESP32-WROOM DevKit using I²C. It probes the chip-ID register at 0xD0 before starting; this helps diagnose modules sold as BMP280 that contain a BME280, a different pressure sensor, or incorrect circuitry.

#include <Arduino.h>
#include <Wire.h>
#include <Adafruit_BMP280.h>

constexpr int I2C_SDA = 21;
constexpr int I2C_SCL = 22;
constexpr float SEA_LEVEL_HPA = 1013.25f; // replace with local QNH
Adafruit_BMP280 bmp(&Wire);
uint8_t activeAddress = 0;

uint8_t readChipID(uint8_t address) {
  Wire.beginTransmission(address);
  Wire.write(0xD0); // BMP280/BME280 chip-ID register
  if (Wire.endTransmission(false) != 0) return 0xFF;
  if (Wire.requestFrom(address, uint8_t(1)) != 1) return 0xFF;
  return Wire.read();
}

void setup() {
  Serial.begin(115200);
  delay(400);
  Wire.begin(I2C_SDA, I2C_SCL);
  Wire.setClock(100000);

  for (uint8_t addr : {uint8_t(0x76), uint8_t(0x77)}) {
    uint8_t id = readChipID(addr);
    Serial.printf("Address 0x%02X: chip ID 0x%02X\n", addr, id);
    if (id == 0x58 && bmp.begin(addr)) {
      activeAddress = addr;
      break;
    }
  }

  if (!activeAddress) {
    Serial.println("BMP280 not detected. Expected chip ID 0x58.");
    Serial.println("Check power, SDA/SCL, CSB, SDO and address.");
    while (true) delay(1000);
  }

  bmp.setSampling(Adafruit_BMP280::MODE_NORMAL,
                  Adafruit_BMP280::SAMPLING_X2,
                  Adafruit_BMP280::SAMPLING_X16,
                  Adafruit_BMP280::FILTER_X16,
                  Adafruit_BMP280::STANDBY_MS_500);

  Serial.printf("BMP280 ready at 0x%02X\n", activeAddress);
}

void loop() {
  float tempC = bmp.readTemperature();
  float pressurePa = bmp.readPressure();
  float pressureHpa = pressurePa / 100.0f;
  float altitudeM = bmp.readAltitude(SEA_LEVEL_HPA);

  Serial.printf("T=%.2f C  P=%.2f hPa  alt~=%.1f m\n",
                tempC, pressureHpa, altitudeM);
  delay(2000);
}

Expected output: on a working sensor, the serial monitor reports the detected address and measurements, for example Address 0x77: chip ID 0x58, followed by T=24.70 C P=1012.43 hPa alt~=6.8 m. These are illustrative values, not bench-test results. A status value of 0xFF commonly means no response; 0x60 suggests a BME280 and calls for the matching BME library.

Optional SPI code: using the same Adafruit library

Change the physical wiring to the SPI table, then construct the sensor for hardware SPI. Keep either the I²C example or the SPI example in your sketch, not both at once.

#include <Arduino.h>
#include <SPI.h>
#include <Adafruit_BMP280.h>

constexpr int BMP_CS = 5;
Adafruit_BMP280 bmp(BMP_CS, &SPI); // hardware SPI

void setup() {
  Serial.begin(115200);
  SPI.begin(18, 19, 23, BMP_CS); // SCK, MISO, MOSI, SS
  if (!bmp.begin()) {
    Serial.println("BMP280 SPI communication failed");
    while (true) delay(1000);
  }
}
void loop() {
  Serial.printf("Pressure %.2f hPa, T %.2f C\n",
                bmp.readPressure() / 100.0f, bmp.readTemperature());
  delay(2000);
}

I²C scanner and chip-ID check: is it really a BMP280?

An I²C scanner confirms only that some device responds at an address—it does not identify whether the sensor is a BMP280 or BME280. Read register 0xD0 to identify the silicon and select the correct code:

Observed ID at 0xD0InterpretationNext action
0x58BMP280 expected chip IDUse Adafruit BMP280 library
0x60BME280 expected chip IDUse Adafruit BME280 library; humidity available
No reply / 0xFFBus/power/address failure or absent deviceCheck wires, bus speed, supply and CSB
Other valueUnknown or incompatible device, possibly another Bosch familyConsult that chip’s own datasheet and driver

Some inexpensive modules are incorrectly advertised as BME280 although they actually hold BMP280 silicon. If a humidity sketch fails to initialize while the chip ID is 0x58, the seller’s label is not evidence of humidity capability. The site already has a BMP280 versus BME280 comparison and a separate BME280 breakout reference.

BMP280 chip identification diagram showing 0xD0 register equals 0x58 BMP280 vs 0x60 BME280 plus pressure units oversampling modes
Chip ID, operating modes and pressure-to-altitude conversion: a BMP280 gives temperature and pressure, never humidity. Altitude requires an external sea-level pressure reference.

Sampling modes, oversampling and filter configuration

Mode or settingPractical behaviour
SleepMeasurements stopped; registers remain accessible
Forced modeOne measurement, then sensor returns to sleep; well suited to low-duty-cycle battery nodes
Normal modeCycles between measurements and standby automatically
Temperature oversamplingImproves temperature resolution at cost of conversion time
Pressure oversamplingReduces pressure noise but consumes additional time and current
IIR filterSmooths short variations; too much filtering delays rapid pressure events
Standby timeControls time between normal-mode conversions

For an indoor weather station reporting every few seconds, a normal-mode setting with moderate temperature oversampling, higher pressure oversampling and some filtering is usually sensible. For a battery-powered node that wakes every minute, use MODE_FORCED and call takeForcedMeasurement() for a fresh reading. The library’s setSampling() function exposes these controls.

Pressure, altitude and sensor-placement accuracy

The pressure reading is absolute atmospheric pressure at the sensor. The convenience method readAltitude(seaLevelPressureHpa) estimates elevation by comparing that pressure with your supplied sea-level reference. Its default 1013.25 hPa is a standard-atmosphere assumption, not your real-time local sea-level pressure. Changing weather can alter the calculated altitude even if the board never moves.

Barometric altitude can be useful for relative floor-level or motion changes under stable weather, but do not present it as surveyed elevation or GPS. Avoid placing the BMP280 immediately above an ESP32 voltage regulator or in direct sun, where board heating can bias the measured temperature. Keep the sensor’s vent opening clear of adhesives, conformal coatings, water and dust. If your project requires relative humidity too, use a BME280 or a separate humidity sensor.

Common BMP280 problems and how to fix them

ProblemDiagnosis and fix
Library cannot find sensorTry 0x76 and 0x77, check shared ground, correct SDA/SCL and whether CSB is held high for I²C.
Sensor detected but ID is 0x60It is likely a BME280, not BMP280. Install the BME280 library instead.
Works on Adafruit board but not cheap six-pin moduleRegulator/level-shifter differences; ensure actual module operates correctly at 3.3 V.
Address changes when soldering the wrong jumperDo not assume a pad belongs to SDO. Trace or verify manufacturer markings and read address with I²C scanner.
Altitude is wrong by tens or hundreds of metresReplace 1013.25 hPa with current local sea-level pressure / QNH; understand weather variations.
Measured temperature too highProximity to ESP32 CPU/regulator, enclosure warming and inadequate ventilation.
Reads zero or nonsense valuesIncorrect library for silicon ID, floating SDO or CSB, poor connections, unsuitable supply.
No SPI responseMISO/MOSI reversed, CS missing, I²C-configured breakout, wrong SPI constructor or mismatched pin choice.
Two sensors same I²C addressMove one to other SDO level if available or use a TCA9548A channel for each.

BMP280 vs BME280 vs BMP180: when is each a better choice?

PartMeasurementsBus / practical choice
BMP280Pressure and temperatureCompact, I²C or SPI; a good basic pressure breakout
BME280Pressure, temperature, relative humidityChoose when humidity matters; similar bus/address behaviour but different library
BMP180Pressure and temperatureOlder I²C design; different driver and address behaviour

If you need to measure light as well, consider the related Bosch sensor comparison rather than inferring humidity readings from a BMP280. For identical address sensors, our TCA9548A ESP32 guide shows how to connect devices with overlapping addresses on separate I²C branches.

BMP280 FAQs

Can I use a BMP280 with 5 V?

The bare BMP280 sensor is not a 5 V silicon device. The Adafruit #2651 breakout has a regulator and level shifting and supports a 3–5 V VIN input; many generic boards do not. With an ESP32, 3.3 V and 3.3 V I²C levels are the straightforward choice.

Is the default BMP280 address 0x76 or 0x77?

Either can be correct depending on how the PCB straps SDO. Adafruit #2651 normally uses 0x77. Many generic boards tie SDO LOW for 0x76. Always check both, and never float SDO on the raw IC.

Can BMP280 measure humidity?

No. It measures pressure and sensor temperature. The BME280 includes a humidity channel and has a different chip ID and driver.

Can I run two BMP280 boards at once?

Yes: connect one as 0x76 and the other as 0x77, if each board supports that address selection, or place identically addressed devices on separate I²C multiplexer channels. With SPI, give each device its own CS pin.

Is the temperature reading room temperature?

It is the sensor’s own temperature, which can be affected by nearby circuitry and enclosure heat. For dependable ambient readings, use thoughtful placement or a dedicated well-positioned temperature sensor.

Technical references

Editorial note: This is a hardware-reference guide for the actual BMP280 and the documented Adafruit #2651 breakout, not a promise that all six-pin clone PCBs share one layout or accept 5 V. Read the silkscreen and confirm your exact module before soldering or connecting higher supply voltages. Example code follows the published Adafruit API and has not been physically bench-tested on every board.

CONTINUE EXPLORING / ARDUINO

Read next

Practical guides related to this article.

Explore the topic →
HARDWARE DECISION GUIDEArduino or ESP32 for your next build?

Compare practical options before you choose hardware.

Compare options →