The BME280 is a combined digital humidity, pressure and temperature sensor based on proven sensing principles.
The API can be downloaded from Github. The BSEC can be downloaded from the Bosch Sensortec website.
The humidity sensor data is expressed as a percentage (10% - 90% at 0°C-65°C).
The pressure sensor data is in hPa (300hPa - 1100hPa at 0°C-65°C).
The temperature sensor data is in °C (-40°C - 85°C).
The function bme280_get_sensor_data in the API is used to get the sensor data.
The accuracy represents how accurate the sensor can be under certain condition.
Table 1 lists the accuracy of humidity sensor, pressure sensor, and temperature sensor.
The pressure sensor drift represents the error in the measured value. Basically, there are two drifts on the pressure part in the BME280, i.e. solder drift and long-term drift.
The TCO (offset temperature coefficient) is the change in the pressure signal caused by a change in the temperature.
For the pressure sensor, the TCO is ±1.5 Pa/K, equivalent to ±12.6 cm at 1 °C temperature change, which means the pressure sensor data changes within ±1.5 Pa, with 1 °C temperature change at constant pressure.
The BME280 can be operated in three working modes: sleep mode, normal mode, and force mode, which can be selected using the mode [1:0] setting (in register 0xF4 [1:0], sleep mode -> b11, force mode -> b10 and b01, normal mode -> b11). The function bme280_set_sensor_mode in the API can also used to set power mode.
During the measurement cycle, the BME280 measures temperature, pressure and humidity, with optional oversampling.
After the measurement cycle, the pressure and temperature data can be passed through an optional IIR filter, which removes short-term fluctuations in pressure (e.g. caused by slamming a door). For humidity, such a filter is not needed and has not been implemented.
Oversampling can be enabled during the measurement, which can reduce noise but also consumes more power. Different sensors have different OSRs (oversampling rate).
The osrs_h<2:0> settings are explained as follows:
b101, and other settings -> oversamplingx16
The osrs_p<4:2> settings are explained as follows:
The osrs_t<7:5> settings are explained as follows:
The function bme280_set_sensor_settings in the API can also be used to set the OSR for any sensor. See below for the example.
...
int8_t rslt;
uint8_t settings_sel;
dev->settings.osr_h = BME280_OVERSAMPLING_1X;
dev->settings.osr_p = BME280_OVERSAMPLING_16X;
dev->settings.osr_t = BME280_OVERSAMPLING_2X;
...
settings_sel = BME280_OSR_PRESS_SEL | BME280_OSR_TEMP_SEL | BME280_OSR_HUM_SEL | BME280_FILTER_SEL;
rslt = bme280_set_sensor_settings(settings_sel, dev);
....
return rslt;
...
The environmental pressure is subject to many short-term changes caused by, for example, door or window slamming, wind blowing into the sensor, etc. The BME280 features an internal IIR filter which can suppress these disturbances in the output data without causing additional interface traffic and processor workload. By setting the filter coefficient (c), the bandwidth of the temperature and pressure output signals can be effectively reduced and the resolution of the pressure and temperature output data can be increased to 20 bits. The output of the next measurement step is filtered using the following formula:
Where, data_filter_old is the data coming from the current filter memory. data_ADC is the data coming from current ADC acquisition. data_filtered is the new value of filter memory and the value that will be sent to the output registers.
The filter<4:2> settings are explained as follows:
The function bme280_set_sensor_settings in the API can also be used to set filter. See below for the example.
...
int8_t rslt;
uint8_t settings_sel;
...
dev->settings.filter = BME280_FILTER_COEFF_16;
...
settings_sel = BME280_OSR_PRESS_SEL | BME280_OSR_TEMP_SEL | BME280_OSR_HUM_SEL | BME280_FILTER_SEL;
...
rslt = bme280_set_sensor_settings(settings_sel, dev);
...
return rslt;
The calibration table for pressure and temperature is subtracted from the registers calib25...calib00
located at addresses 0x88 - 0xA1
Reading is carried out immediately 24 bytes(as described in the chapter "3.9 Data readout" Data sheet)
Read data starting from address 0x88:
unsigned short LSB bf MSB 00 dig_T1 00bf
short LSB 00 MSB 00 dig_T2 0000
short LSB 00 MSB ff dig_T3 ff00
unsigned short LSB 81 MSB 03 dig_P1 0381
short LSB 0f MSB 00 dig_P2 000f
short LSB 00 MSB 00 dig_P3 0000
short LSB 00 MSB ff dig_P4 ff00
short LSB 00 MSB 00 dig_P5 0000
short LSB 00 MSB 00 dig_P6 0000
short LSB 00 MSB 00 dig_P7 0000
short LSB ff MSB ff dig_P8 ffff
short LSB 00 MSB ff dig_P9 ff00
To calculate the temperature and pressure data, the recommended "compensation" formulas were used using the obtained " raw " temperature and pressure data and calibration data:
// Returns temperature in DegC, resolution is 0.01 DegC. Output value of “5123” equals 51.23 DegC.
int bmp280_compensate_T_int32(int adc_T)
{
int var1, var2, T;
var1 = ((((adc_T>>3) - ((int)dig_T1<<1))) * ((int)dig_T2)) >> 11;
var2 = (((((adc_T>>4) - ((int)dig_T1)) * ((adc_T>>4) - ((int)dig_T1))) >> 12) *((int)dig_T3)) >> 14;
t_fine = var1 + var2;
T = (t_fine * 5 + 128) >> 8;
return T;
}
// Returns pressure in Pa as unsigned 32 bit integer. Output value of “96386” equals 96386 Pa = 963.86 hPa
uint32_t bmp280_compensate_P_int32(uint32_t adc_P)
{
int32_t var1, var2;
uint32_t p;
var1 = (((uint32_t)t_fine)>>1) - (uint32_t)64000;
var2 = (((var1>>2) * (var1>>2)) >> 11 ) * ((uint32_t)dig_P6);
var2 = var2 + ((var1*((uint32_t)dig_P5))<<1);
var2 = (var2>>2)+(((uint32_t)dig_P4)<<16);
var1 = (((dig_P3 * (((var1>>2) * (var1>>2)) >> 13 )) >> 3) + ((((uint32_t)dig_P2) * var1)>>1))>>18;
var1 =((((32768+var1))*((uint32_t)dig_P1))>>15);
if(var1 == 0)
{
return 0; // avoid exception caused by division by zero
}
p = (((uint32_t)(((uint32_t)1048576)-adc_P)-(var2>>12)))*3125;
if(p < 0x80000000)
{
p = (p << 1) / ((uint32_t)var1);
}
else
{
p = (p / (uint32_t)var1) * 2;
}
var1 = (((uint32_t)dig_P9) * ((uint32_t)(((p>>3) * (p>>3))>>13)))>>12;
var2 = (((uint32_t)(p>>2)) * ((uint32_t)dig_P8))>>13;
p = (uint32_t)((uint32_t)p + ((var1 + var2 + dig_P7) >> 4));
return p;
}
Results of temperature and pressure measurements
----- in the room(really +26 - +28 )--------------------------------------
calculated "raw" value calculated "raw" value
value hex dec value hex dec
-----------------------------------------------------------------------
PRES=4683012 [P_raw = 0xc9d8 (51672)] TMPR=-74 [T_raw=0xbd88 (48520)]
PRES=4662151 [P_raw = 0xd68d (54925)] TMPR=-77 [T_raw=0xe580 (58752)]
PRES=4646370 [P_raw = 0xe135 (57653)] TMPR=-80 [T_raw=0x0760 (1888)]
PRES=4627881 [P_raw = 0xec4e (60494)] TMPR=-82 [T_raw=0x2b40 (11072)]
PRES=4605759 [P_raw = 0xf9da (63962)] TMPR=-86 [T_raw=0x56d0 (22224)]
----- на улице (примерно -15)-------------------
PRES=4879343 [P_raw = 0x4eb5 (20149)] TMPR=-49 [T_raw=0x4b78 (19320)]
PRES=4878219 [P_raw = 0x4f78 (20344)] TMPR=-49 [T_raw=0x4e30 (20016)]
PRES=4879327 [P_raw = 0x4eb8 (20152)] TMPR=-49 [T_raw=0x4d28 (19752)]
the IIR filter part is very well explained, thnaks
Can you make clearer the difference between BME280_NO_OVERSAMPLING and BME280_OVERSAMPLING_1X?