Erriez BMP280 / BME280 library for Arduino  1.0.1
This is a BMP280/BME280 temperature/pressure/humidity sensor library for Arduino.
ErriezBMX280.cpp
Go to the documentation of this file.
1 /*
2  * MIT License
3  *
4  * Copyright (c) 2020 Erriez
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in all
14  * copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23  */
24 
36 #include "ErriezBMX280.h"
37 
43 ErriezBMX280::ErriezBMX280(uint8_t i2cAddr) : _i2cAddr(i2cAddr), _t_fine(0)
44 {
45 
46 }
47 
56 {
57  // Read chip ID
58  _chipID = read8(BME280_REG_CHIPID);
59 
60  // Check sensor ID BMP280 or BME280
61  if ((_chipID != CHIP_ID_BMP280) && ((_chipID != CHIP_ID_BME280))) {
62  // BMP280 / BME280 not found
63  return false;
64  }
65 
66  // Generate soft-reset
68 
69  // Wait for copy completion NVM data to image registers
70  delay(10);
71  while ((read8(BMX280_REG_STATUS) & (1 << STATUS_IM_UPDATE))) {
72  delay(10);
73  }
74 
75  // See datasheet 4.2.2 Trimming parameter readout
76  readCoefficients();
77 
78  // Set default sampling
79  setSampling();
80 
81  // Wait for first completed conversion
82  delay(100);
83 
84  // BMP280 or BME280 detected
85  return true;
86 }
87 
94 {
95  // Return chip ID
96  return _chipID;
97 }
98 
105 {
106  int32_t var1, var2, adc_T;
107  float temperature;
108 
109  // Read temperature registers
110  adc_T = read24(BMX280_REG_TEMP);
111  adc_T >>= 4;
112 
113  // See datasheet 4.2.3 Compensation formulas
114  var1 = ((((adc_T >> 3) - ((int32_t)_dig_T1 << 1))) * ((int32_t)_dig_T2)) >> 11;
115 
116  var2 = (((((adc_T >> 4) - ((int32_t)_dig_T1)) *
117  ((adc_T >> 4) - ((int32_t)_dig_T1))) >> 12) *
118  ((int32_t)_dig_T3)) >> 14;
119 
120  _t_fine = var1 + var2;
121 
122  temperature = ((_t_fine * 5) + 128) >> 8;
123 
124  return temperature / 100.0;
125 }
126 
133 {
134  int64_t var1;
135  int64_t var2;
136  int64_t p;
137  int32_t adc_P;
138 
139  // Read temperature for t_fine
140  readTemperature();
141 
142  // Read pressure registers
143  adc_P = read24(BMX280_REG_PRESS);
144  adc_P >>= 4;
145 
146  // See datasheet 4.2.3 Compensation formulas
147  var1 = ((int64_t)_t_fine) - 128000;
148  var2 = var1 * var1 * (int64_t)_dig_P6;
149  var2 = var2 + ((var1 * (int64_t)_dig_P5) << 17);
150  var2 = var2 + (((int64_t)_dig_P4) << 35);
151  var1 = ((var1 * var1 * (int64_t)_dig_P3) >> 8) + ((var1 * (int64_t)_dig_P2) << 12);
152  var1 = (((((int64_t)1) << 47) + var1)) * ((int64_t)_dig_P1) >> 33;
153 
154  if (var1 == 0) {
155  return 0; // avoid exception caused by division by zero
156  }
157  p = 1048576 - adc_P;
158  p = (((p << 31) - var2) * 3125) / var1;
159  var1 = (((int64_t)_dig_P9) * (p >> 13) * (p >> 13)) >> 25;
160  var2 = (((int64_t)_dig_P8) * p) >> 19;
161 
162  p = ((p + var1 + var2) >> 8) + (((int64_t)_dig_P7) << 4);
163 
164  return (float)p / 256;
165 }
166 
174 float ErriezBMX280::readAltitude(float seaLevel)
175 {
176  float atmospheric = readPressure() / 100.0F;
177 
178  // In Si units for Pascal
179  return 44330.0 * (1.0 - pow(atmospheric / seaLevel, 0.1903));
180 }
181 
188 {
189  int32_t v_x1_u32r;
190  int32_t adc_H;
191  float humidity;
192 
193  if (_chipID != CHIP_ID_BME280) {
194  return 0;
195  }
196 
197  // Read temperature for t_fine
198  readTemperature();
199 
200  // Read humidity registers
201  adc_H = read16(BME280_REG_HUM);
202 
203  // See datasheet 4.2.3 Compensation formulas
204  v_x1_u32r = (_t_fine - ((int32_t)76800));
205 
206  v_x1_u32r = ((((adc_H << 14) - (((int32_t)_dig_H4) << 20) - (((int32_t)_dig_H5) * v_x1_u32r)) +
207  ((int32_t)16384)) >> 15) *
208  (((((((v_x1_u32r *
209  ((int32_t)_dig_H6)) >> 10) *
210  (((v_x1_u32r *
211  ((int32_t)_dig_H3)) >> 11) + ((int32_t)32768))) >> 10) + ((int32_t)2097152)) *
212  ((int32_t)_dig_H2) + 8192) >> 14);
213 
214  v_x1_u32r = (v_x1_u32r - (((((v_x1_u32r >> 15) * (v_x1_u32r >> 15)) >> 7) *
215  ((int32_t)_dig_H1)) >> 4));
216 
217  v_x1_u32r = (v_x1_u32r < 0) ? 0 : v_x1_u32r;
218  v_x1_u32r = (v_x1_u32r > 419430400) ? 419430400 : v_x1_u32r;
219 
220  humidity = (v_x1_u32r >> 12);
221 
222  return humidity / 1024.0;
223 }
224 
228 void ErriezBMX280::readCoefficients(void)
229 {
230  _dig_T1 = read16_LE(BMX280_REG_DIG_T1);
231  _dig_T2 = readS16_LE(BMX280_REG_DIG_T2);
232  _dig_T3 = readS16_LE(BMX280_REG_DIG_T3);
233 
234  _dig_P1 = read16_LE(BMX280_REG_DIG_P1);
235  _dig_P2 = readS16_LE(BMX280_REG_DIG_P2);
236  _dig_P3 = readS16_LE(BMX280_REG_DIG_P3);
237  _dig_P4 = readS16_LE(BMX280_REG_DIG_P4);
238  _dig_P5 = readS16_LE(BMX280_REG_DIG_P5);
239  _dig_P6 = readS16_LE(BMX280_REG_DIG_P6);
240  _dig_P7 = readS16_LE(BMX280_REG_DIG_P7);
241  _dig_P8 = readS16_LE(BMX280_REG_DIG_P8);
242  _dig_P9 = readS16_LE(BMX280_REG_DIG_P9);
243 
244  if (_chipID == CHIP_ID_BME280) {
245  _dig_H1 = read8(BME280_REG_DIG_H1);
246  _dig_H2 = readS16_LE(BME280_REG_DIG_H2);
247  _dig_H3 = read8(BME280_REG_DIG_H3);
248  _dig_H4 = ((int8_t) read8(BME280_REG_DIG_H4) << 4) | (read8(BME280_REG_DIG_H4 + 1) & 0xF);
249  _dig_H5 = ((int8_t) read8(BME280_REG_DIG_H5 + 1) << 4) | (read8(BME280_REG_DIG_H5) >> 4);
250  _dig_H6 = (int8_t) read8(BME280_REG_DIG_H6);
251  }
252 }
253 
270  BMX280_Sampling_e tempSampling,
271  BMX280_Sampling_e pressSampling,
272  BMX280_Sampling_e humSampling,
273  BMX280_Filter_e filter,
274  BMX280_Standby_e standbyDuration)
275 {
276  // Set in sleep mode to provide write access to the “config” register
278 
279  if (_chipID == CHIP_ID_BME280) {
280  // See datasheet 5.4.3 Register 0xF2 “ctrl_hum”
281  write8(BME280_REG_CTRL_HUM, humSampling);
282  }
283  // See datasheet 5.4.6 Register 0xF5 “config”
284  write8(BMX280_REG_CONFIG, (standbyDuration << 5) | (filter << 2));
285  // See datasheet 5.4.5 Register 0xF4 “ctrl_meas”
286  write8(BMX280_REG_CTRL_MEAS, (tempSampling << 5) | (pressSampling << 2) | mode);
287 }
288 
296 uint8_t ErriezBMX280::read8(uint8_t reg)
297 {
298  Wire.beginTransmission(_i2cAddr);
299  Wire.write(reg);
300  if (Wire.endTransmission() != 0) {
301  return 0;
302  }
303  Wire.requestFrom(_i2cAddr, (byte)1);
304  return Wire.read();
305 }
306 
314 void ErriezBMX280::write8(uint8_t reg, uint8_t value)
315 {
316  Wire.beginTransmission(_i2cAddr);
317  Wire.write(reg);
318  Wire.write(value);
319  Wire.endTransmission();
320 }
321 
329 uint16_t ErriezBMX280::read16_LE(uint8_t reg)
330 {
331  uint16_t value;
332 
333  value = read16(reg);
334 
335  return (value >> 8) | (value << 8);
336 }
337 
345 int16_t ErriezBMX280::readS16_LE(uint8_t reg)
346 {
347  return (int16_t)read16_LE(reg);
348 }
349 
357 uint16_t ErriezBMX280::read16(uint8_t reg)
358 {
359  Wire.beginTransmission(_i2cAddr);
360  Wire.write(reg);
361  if (Wire.endTransmission() != 0) {
362  return 0;
363  }
364  Wire.requestFrom(_i2cAddr, (byte)2);
365  return (Wire.read() << 8) | Wire.read();
366 }
367 
375 uint32_t ErriezBMX280::read24(uint8_t reg)
376 {
377  uint32_t value;
378 
379  Wire.beginTransmission(_i2cAddr);
380  Wire.write(reg);
381  Wire.endTransmission();
382  Wire.requestFrom(_i2cAddr, (byte)3);
383 
384  value = Wire.read();
385  value <<= 8;
386  value |= Wire.read();
387  value <<= 8;
388  value |= Wire.read();
389 
390  return value;
391 }
#define BME280_REG_DIG_H3
Humidity coefficient register.
Definition: ErriezBMX280.h:63
ErriezBMX280(uint8_t i2cAddr)
Constructor.
#define BMX280_REG_DIG_P3
Pressure coefficient register.
Definition: ErriezBMX280.h:53
#define BMX280_REG_DIG_T1
Temperature coefficient register.
Definition: ErriezBMX280.h:47
Sleep mode.
Definition: ErriezBMX280.h:89
uint8_t getChipID()
Get chip ID.
#define BME280_REG_HUM
Humidity data register.
Definition: ErriezBMX280.h:77
#define BMX280_REG_DIG_P6
Pressure coefficient register.
Definition: ErriezBMX280.h:56
#define BMX280_REG_DIG_P9
Pressure coefficient register.
Definition: ErriezBMX280.h:59
#define BME280_REG_DIG_H1
Humidity coefficient register.
Definition: ErriezBMX280.h:61
#define BME280_REG_CHIPID
Chip ID register.
Definition: ErriezBMX280.h:68
#define BME280_REG_DIG_H2
Humidity coefficient register.
Definition: ErriezBMX280.h:62
uint8_t read8(uint8_t reg)
Read from 8-bit register.
BMX280_Standby_e
Standby duration bits config register.
Definition: ErriezBMX280.h:120
#define BMX280_REG_DIG_P5
Pressure coefficient register.
Definition: ErriezBMX280.h:55
int16_t readS16_LE(uint8_t reg)
Read from 16-bit signed register little endian.
void write8(uint8_t reg, uint8_t value)
Write to 8-bit register.
BMX280_Sampling_e
Sampling bits registers ctrl_hum, ctrl_meas.
Definition: ErriezBMX280.h:97
#define CHIP_ID_BME280
BME280 chip ID.
Definition: ErriezBMX280.h:81
#define BMX280_REG_DIG_T2
Temperature coefficient register.
Definition: ErriezBMX280.h:48
#define BMX280_REG_PRESS
Pressure data register.
Definition: ErriezBMX280.h:75
#define RESET_KEY
Reset value for reset register.
Definition: ErriezBMX280.h:82
#define BMX280_REG_CONFIG
Config register.
Definition: ErriezBMX280.h:74
uint16_t read16_LE(uint8_t reg)
Read from 16-bit unsigned register little endian.
#define BME280_REG_RESET
Reset register.
Definition: ErriezBMX280.h:69
#define BMX280_REG_TEMP
Temperature data register.
Definition: ErriezBMX280.h:76
BMX280_Filter_e
Filter bits config register.
Definition: ErriezBMX280.h:109
#define BMX280_REG_DIG_P8
Pressure coefficient register.
Definition: ErriezBMX280.h:58
#define BMX280_REG_DIG_T3
Temperature coefficient register.
Definition: ErriezBMX280.h:49
float readPressure()
Read pressure.
float readTemperature()
Read temperature.
#define BME280_REG_DIG_H5
Humidity coefficient register.
Definition: ErriezBMX280.h:65
#define CHIP_ID_BMP280
BMP280 chip ID.
Definition: ErriezBMX280.h:80
#define BMX280_REG_DIG_P7
Pressure coefficient register.
Definition: ErriezBMX280.h:57
uint16_t read16(uint8_t reg)
Read from 16-bit register.
#define BMX280_REG_DIG_P4
Pressure coefficient register.
Definition: ErriezBMX280.h:54
#define BME280_REG_CTRL_HUM
BME280: Control humidity register.
Definition: ErriezBMX280.h:71
uint32_t read24(uint8_t reg)
Read from 24-bit register.
BMP280/BME280 sensor library for Arduino.
float readHumidity()
Read humidity (BME280 only)
#define BME280_REG_DIG_H4
Humidity coefficient register.
Definition: ErriezBMX280.h:64
#define BME280_REG_DIG_H6
Humidity coefficient register.
Definition: ErriezBMX280.h:66
float readAltitude(float seaLevel)
Read approximate altitude.
bool begin()
Sensor initialization.
#define BMX280_REG_CTRL_MEAS
Control measure register.
Definition: ErriezBMX280.h:73
void setSampling(BMX280_Mode_e mode=BMX280_MODE_NORMAL, BMX280_Sampling_e tempSampling=BMX280_SAMPLING_X16, BMX280_Sampling_e pressSampling=BMX280_SAMPLING_X16, BMX280_Sampling_e humSampling=BMX280_SAMPLING_X16, BMX280_Filter_e filter=BMX280_FILTER_OFF, BMX280_Standby_e standbyDuration=BMX280_STANDBY_MS_0_5)
Set sampling registers.
#define BMX280_REG_STATUS
Status register.
Definition: ErriezBMX280.h:72
#define BMX280_REG_DIG_P2
Pressure coefficient register.
Definition: ErriezBMX280.h:52
#define STATUS_IM_UPDATE
im_update bit in status register
Definition: ErriezBMX280.h:83
#define BMX280_REG_DIG_P1
Pressure coefficient register.
Definition: ErriezBMX280.h:51
BMX280_Mode_e
Sleep mode bits ctrl_meas register.
Definition: ErriezBMX280.h:88