BME280 and BMP280 pressure sensors
Bosch pressure sensors on a purple I2C breakout: the BMP280 reads pressure and temperature, and the BME280 adds humidity. Aliases: barometer, GY-BME280.
On the board the two look identical. The only way to tell them apart from a sketch is
the chip-id register, 0xD0: 0x60 for a BME280 and 0x58 for a BMP280.
Pins
| Pin | What it does |
|---|---|
VIN |
Supply. The module has its own regulator, so 3.3 V or 5 V. |
GND |
Ground. |
SCL |
I2C clock. The module carries the pull-ups. |
SDA |
I2C data. |
Properties
address is 0x76 or 0x77, the strap on the board. Most purple modules are at
0x76, and so is this part; Adafruit's own board and library default to 0x77. A
tutorial written for a purple module says bme.begin(0x76), and when begin() fails
the address is the first thing to check.
temperature (°C), pressure (hPa) and, on the BME280, humidity (%RH) are the
weather, and the sliders on the part change them while the circuit runs. Standard
sea-level pressure is 1013.25 hPa, and every 12 hPa less is about 100 m higher.
Counts, and a calibration you do yourself
The chip does not report degrees or pascals. It reports raw ADC counts, twenty bits
for temperature and pressure and sixteen for humidity, and it carries its own
factory-trimmed coefficients in registers 0x88 to 0xA1 and 0xE1 to 0xE7.
Bosch's datasheet gives the integer arithmetic that turns the two into a reading, and
every driver is that arithmetic. The temperature has to come first, because the
pressure and humidity formulas both need a by-product of it, t_fine.
The part works those formulas backwards: from the sliders it finds the counts the
datasheet's own compensation turns back into the same weather. A driver that gets the
arithmetic right reads the sliders; one that gets a shift or a sign wrong reads
nonsense, exactly as it would on a real sensor. The humidity coefficients dig_H4
and dig_H5 are twelve bits each and share register 0xE5, which is the line most
hand-written drivers get wrong.
The libraries
Adafruit_BME280.h, Adafruit_BMP280.h and SparkFunBME280.h all work as their
tutorials use them:
#include <Wire.h>
#include <Adafruit_BME280.h>
Adafruit_BME280 bme;
void setup() {
Serial.begin(9600);
if (!bme.begin(0x76)) {
Serial.println("No BME280");
while (1);
}
}
void loop() {
Serial.println(bme.readTemperature()); // C
Serial.println(bme.readPressure()); // Pa
Serial.println(bme.readAltitude(1013.25)); // m
Serial.println(bme.readHumidity()); // %
delay(1000);
}
The values are floats built from the datasheet's integer results, and the
tutorials' bme.readPressure() / 100.0F works as written on every board;
readPressureHPa(), which Mokxi adds, gives the same without the division.
readAltitude() is worked in integers and lands within a few centimeters of the
same formula in floating point.
What the model gets right
The register map and the reset values: asleep at power-up, data registers at
0x80000 and 0x8000 until something is measured, im_update set for the 2 ms the
chip spends copying its coefficients. Forced mode takes one measurement and goes
back to sleep; normal mode measures, waits the standby time, and repeats. A
measurement takes the datasheet's typical time, from 8 ms at 1x oversampling to
113 ms at 16x, with measuring set while it runs.
ctrl_hum only takes effect at the next write to ctrl_meas, and humidity
oversampling left at 0 means no humidity at all: the register reads its reset value.
Both are straight from the datasheet and both catch people.
Resolution follows oversampling, 16 bits at 1x up to 20 at 16x, and the IIR filter blends each result into the last, so a slider moved with the filter on is followed smoothly rather than in a jump.
What it does not model
Noise. A real reading wanders by a few pascals and a few hundredths of a degree,
which is what oversampling and the filter are for; here more samples change only the
time and the number of bits. The drivers use Bosch's 32-bit pressure formula, since
the smaller boards have no 64-bit multiply, and it reads a few pascals off the 64-bit
one. SPI mode, and so CSB and SDO as pins, are not modeled: this is the I2C
module. The humidity sensor's slow response to a change in the air is not modeled.
Common mistakes
The address: 0x76 on the purple modules, 0x77 in the libraries' defaults.
Forgetting ctrl_hum in a hand-written driver and reading humidity as nonsense.
Reading pressure without first reading temperature, so t_fine is stale.