The BMP280 measures air pressure (±1 hPa) and temperature. It is the sensor behind most hobby altimeters and weather-trend displays, and the cheap purple board costs about ₹80.
That purple board is a 3.3 V-only part with no regulator, so on the ESP32 DevKit V1 it goes straight to 3V3 and the I2C pins D21/D22 — no level shifting. The sketch checks both addresses, uses the datasheet’s low-noise weather settings, and prints temperature, pressure in hPa and altitude every two seconds.
Wiring
| ESP32 DevKit V1 | BMP280 breakout (GY-BMP280) | Wire | Notes |
|---|---|---|---|
| 3V3 | VCC | red | The purple GY-BMP280-3.3 board has no regulator — 3V3 only. VIN (5 V) would damage the chip. |
| GND | GND | black | |
| D22 | SCL | yellow | |
| D21 | SDA | blue | |
| GND | SDO | black | SDO to GND fixes the address at 0x76 (to 3V3 → 0x77). Leave CSB unconnected for I2C. |
3.3 V (boards with a regulator: 3.3–5 V) part, 3.3 V board. The common purple 6-pin GY-BMP280-3.3 board has no regulator and no level shifting: power it from 3.3 V only. On a 5 V Uno, use a board with a regulator or a level shifter on SDA/SCL.
Board quirks
- GPIO21 (SDA) and GPIO22 (SCL) are the ESP32’s default
Wirepins; the sketch names them inWire.begin(21, 22)so you can move them to any other free pair if needed. - Many sellers ship BME280 chips on “BMP280” boards and the other way round. The sketch accepts chip ID 0x58 (BMP280) and 0x60 (BME280) and tells you which one you have.
- Altitude is calculated from pressure against 1013.25 hPa. Weather moves the reading by tens of metres; put your city’s current sea-level pressure (QNH, from any aviation weather site) into
SEA_LEVEL_HPAfor a real altitude. - The BMP280 is on the same 3.3 V rail as the ESP32 module, so its temperature reads a degree or two high when the board sits next to it. Use a short cable.
Code
// BMP280 temperature + pressure on an ESP32 DevKit V1 (purple GY-BMP280 board, 3.3 V only).
// VCC → 3V3, GND → GND, SCL → D22, SDA → D21. SDO → GND selects 0x76; CSB left open (I2C).
#include <Wire.h>
#include <Adafruit_BMP280.h>
Adafruit_BMP280 bmp(&Wire);
constexpr float SEA_LEVEL_HPA = 1013.25; // set to your local QNH for a true altitude
bool startSensor() {
const uint8_t addrs[] = {0x76, 0x77};
for (uint8_t a : addrs) {
if (bmp.begin(a, BMP280_CHIPID)) {
Serial.printf("BMP280 found at 0x%02X (chip ID 0x%02X)\n", a, bmp.sensorID());
return true;
}
if (bmp.begin(a, 0x60)) { // a BME280 answers with 0x60 — still readable here
Serial.printf("Chip at 0x%02X is a BME280 (ID 0x60) — reading temp/pressure only\n", a);
return true;
}
}
return false;
}
void setup() {
Serial.begin(115200);
Wire.begin(21, 22); // SDA = GPIO21, SCL = GPIO22 (the DevKit V1 defaults)
if (!startSensor()) {
Serial.println("No BMP280 at 0x76 or 0x77 — check SDA/SCL and 3V3");
while (true) delay(1000);
}
// Weather-station settings from the datasheet: low noise, slow is fine.
bmp.setSampling(Adafruit_BMP280::MODE_NORMAL, Adafruit_BMP280::SAMPLING_X2,
Adafruit_BMP280::SAMPLING_X16, Adafruit_BMP280::FILTER_X16,
Adafruit_BMP280::STANDBY_MS_500);
}
void loop() {
float t = bmp.readTemperature();
float p = bmp.readPressure() / 100.0f; // Pa → hPa
float alt = bmp.readAltitude(SEA_LEVEL_HPA);
Serial.printf("Temp %.2f °C Pressure %.1f hPa Altitude %.0f m\n", t, p, alt);
delay(2000);
}// BMP280 temperature + pressure on an ESP32 DevKit V1 (purple GY-BMP280 board, 3.3 V only).
// VCC → 3V3, GND → GND, SCL → D22, SDA → D21. SDO → GND selects 0x76; CSB left open (I2C).
#include <Wire.h>
#include <Adafruit_BMP280.h>
Adafruit_BMP280 bmp(&Wire);
constexpr float SEA_LEVEL_HPA = 1013.25; // set to your local QNH for a true altitude
bool startSensor() {
const uint8_t addrs[] = {0x76, 0x77};
for (uint8_t a : addrs) {
if (bmp.begin(a, BMP280_CHIPID)) {
Serial.printf("BMP280 found at 0x%02X (chip ID 0x%02X)\n", a, bmp.sensorID());
return true;
}
if (bmp.begin(a, 0x60)) { // a BME280 answers with 0x60 — still readable here
Serial.printf("Chip at 0x%02X is a BME280 (ID 0x60) — reading temp/pressure only\n", a);
return true;
}
}
return false;
}
void setup() {
Serial.begin(115200);
Wire.begin(21, 22); // SDA = GPIO21, SCL = GPIO22 (the DevKit V1 defaults)
if (!startSensor()) {
Serial.println("No BMP280 at 0x76 or 0x77 — check SDA/SCL and 3V3");
while (true) delay(1000);
}
// Weather-station settings from the datasheet: low noise, slow is fine.
bmp.setSampling(Adafruit_BMP280::MODE_NORMAL, Adafruit_BMP280::SAMPLING_X2,
Adafruit_BMP280::SAMPLING_X16, Adafruit_BMP280::FILTER_X16,
Adafruit_BMP280::STANDBY_MS_500);
}
void loop() {
float t = bmp.readTemperature();
float p = bmp.readPressure() / 100.0f; // Pa → hPa
float alt = bmp.readAltitude(SEA_LEVEL_HPA);
Serial.printf("Temp %.2f °C Pressure %.1f hPa Altitude %.0f m\n", t, p, alt);
delay(2000);
}Library: Adafruit BMP280 Library (Adafruit (also install Adafruit Unified Sensor)) — compiled with Adafruit BMP280 Library 3.0.0.
Expected serial output
BMP280 found at 0x76 (chip ID 0x58)
Temp 29.14 °C Pressure 1006.8 hPa Altitude 54 m
Temp 29.15 °C Pressure 1006.8 hPa Altitude 54 mBMP280 found at 0x76 (chip ID 0x58) Temp 29.14 °C Pressure 1006.8 hPa Altitude 54 m Temp 29.15 °C Pressure 1006.8 hPa Altitude 54 m
Common errors
“No BMP280 at 0x76 or 0x77”
SDA/SCL swapped, a loose breadboard row, or the board powered from VIN and now damaged. Run the I2C scanner — no address at all means wiring.
Pressure reads about 600 hPa or other nonsense
Usually a damaged chip from 5 V on a 3.3 V-only board, or SDO floating so the address flips. Tie SDO to GND and power from 3V3.
Altitude is off by 50–100 m
Expected: altitude from pressure needs today’s sea-level pressure. Set SEA_LEVEL_HPA to the local QNH.