Driver for Bosch Sensortec BME280 combined humidity and pressure sensor

Dependencies:   mbed

Committer:
Clemo
Date:
Tue Sep 06 15:17:20 2016 +0000
Revision:
0:b16a9b34fa4c
First version, works for me

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Clemo 0:b16a9b34fa4c 1 /*
Clemo 0:b16a9b34fa4c 2 bme280.cpp - driver for Bosch Sensortec BME280 combined humidity and pressure sensor.
Clemo 0:b16a9b34fa4c 3
Clemo 0:b16a9b34fa4c 4 Copyright (c) 2015 Elektor
Clemo 0:b16a9b34fa4c 5
Clemo 0:b16a9b34fa4c 6 26/11/2015 - CPV, Initial release.
Clemo 0:b16a9b34fa4c 7
Clemo 0:b16a9b34fa4c 8 This library is free software; you can redistribute it and/or
Clemo 0:b16a9b34fa4c 9 modify it under the terms of the GNU Lesser General Public
Clemo 0:b16a9b34fa4c 10 License as published by the Free Software Foundation; either
Clemo 0:b16a9b34fa4c 11 version 2.1 of the License, or (at your option) any later version.
Clemo 0:b16a9b34fa4c 12
Clemo 0:b16a9b34fa4c 13 This library is distributed in the hope that it will be useful,
Clemo 0:b16a9b34fa4c 14 but WITHOUT ANY WARRANTY; without even the implied warranty of
Clemo 0:b16a9b34fa4c 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Clemo 0:b16a9b34fa4c 16 Lesser General Public License for more details.
Clemo 0:b16a9b34fa4c 17
Clemo 0:b16a9b34fa4c 18 You should have received a copy of the GNU Lesser General
Clemo 0:b16a9b34fa4c 19 Public License along with this library; if not, write to the
Clemo 0:b16a9b34fa4c 20 Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Clemo 0:b16a9b34fa4c 21 Boston, MA 02111-1307 USA
Clemo 0:b16a9b34fa4c 22
Clemo 0:b16a9b34fa4c 23 */
Clemo 0:b16a9b34fa4c 24
Clemo 0:b16a9b34fa4c 25 #include "bme280.h"
Clemo 0:b16a9b34fa4c 26
Clemo 0:b16a9b34fa4c 27
Clemo 0:b16a9b34fa4c 28 BME280::BME280(void)
Clemo 0:b16a9b34fa4c 29 {
Clemo 0:b16a9b34fa4c 30 _i2c_address = 0;
Clemo 0:b16a9b34fa4c 31 _t_fine = 0;
Clemo 0:b16a9b34fa4c 32 _temperature = 0;
Clemo 0:b16a9b34fa4c 33 _pressure = 0;
Clemo 0:b16a9b34fa4c 34 _humidity = 0;
Clemo 0:b16a9b34fa4c 35 clearCalibrationData();
Clemo 0:b16a9b34fa4c 36 }
Clemo 0:b16a9b34fa4c 37
Clemo 0:b16a9b34fa4c 38
Clemo 0:b16a9b34fa4c 39 void BME280::clearCalibrationData(void)
Clemo 0:b16a9b34fa4c 40 {
Clemo 0:b16a9b34fa4c 41 _dig_T1 = 0;
Clemo 0:b16a9b34fa4c 42 _dig_T2 = 0;
Clemo 0:b16a9b34fa4c 43 _dig_T3 = 0;
Clemo 0:b16a9b34fa4c 44 _dig_P1 = 0;
Clemo 0:b16a9b34fa4c 45 _dig_P2 = 0;
Clemo 0:b16a9b34fa4c 46 _dig_P3 = 0;
Clemo 0:b16a9b34fa4c 47 _dig_P4 = 0;
Clemo 0:b16a9b34fa4c 48 _dig_P5 = 0;
Clemo 0:b16a9b34fa4c 49 _dig_P6 = 0;
Clemo 0:b16a9b34fa4c 50 _dig_P7 = 0;
Clemo 0:b16a9b34fa4c 51 _dig_P8 = 0;
Clemo 0:b16a9b34fa4c 52 _dig_P9 = 0;
Clemo 0:b16a9b34fa4c 53 _dig_H1 = 0;
Clemo 0:b16a9b34fa4c 54 _dig_H2 = 0;
Clemo 0:b16a9b34fa4c 55 _dig_H3 = 0;
Clemo 0:b16a9b34fa4c 56 _dig_H4 = 0;
Clemo 0:b16a9b34fa4c 57 _dig_H5 = 0;
Clemo 0:b16a9b34fa4c 58 _dig_H6 = 0;
Clemo 0:b16a9b34fa4c 59 }
Clemo 0:b16a9b34fa4c 60
Clemo 0:b16a9b34fa4c 61
Clemo 0:b16a9b34fa4c 62 uint8_t BME280::begin(uint8_t i2cAddress)
Clemo 0:b16a9b34fa4c 63 {
Clemo 0:b16a9b34fa4c 64 _i2c_address = i2cAddress;
Clemo 0:b16a9b34fa4c 65 if (readId()==BME280_ID)
Clemo 0:b16a9b34fa4c 66 {
Clemo 0:b16a9b34fa4c 67 clearCalibrationData();
Clemo 0:b16a9b34fa4c 68 readCalibrationData();
Clemo 0:b16a9b34fa4c 69 return 0;
Clemo 0:b16a9b34fa4c 70 }
Clemo 0:b16a9b34fa4c 71 return (uint8_t)-1;
Clemo 0:b16a9b34fa4c 72 }
Clemo 0:b16a9b34fa4c 73
Clemo 0:b16a9b34fa4c 74
Clemo 0:b16a9b34fa4c 75 void BME280::busWrite(uint8_t *p_data, uint8_t data_size, uint8_t repeated_start)
Clemo 0:b16a9b34fa4c 76 {
Clemo 0:b16a9b34fa4c 77 if (_i2c_address==BME280_I2C_ADDRESS1 || _i2c_address==BME280_I2C_ADDRESS2)
Clemo 0:b16a9b34fa4c 78 {
Clemo 0:b16a9b34fa4c 79 // Assume I2C bus.
Clemo 0:b16a9b34fa4c 80 i2cWrite(_i2c_address,p_data,data_size,repeated_start);
Clemo 0:b16a9b34fa4c 81 }
Clemo 0:b16a9b34fa4c 82 else
Clemo 0:b16a9b34fa4c 83 {
Clemo 0:b16a9b34fa4c 84 // Assume SPI bus.
Clemo 0:b16a9b34fa4c 85 // First byte is supposed to be the address of the register to write to, set R/~W bit to 0.
Clemo 0:b16a9b34fa4c 86 p_data[0] &= 0x7f;
Clemo 0:b16a9b34fa4c 87 spiWrite(p_data,data_size);
Clemo 0:b16a9b34fa4c 88 }
Clemo 0:b16a9b34fa4c 89 }
Clemo 0:b16a9b34fa4c 90
Clemo 0:b16a9b34fa4c 91
Clemo 0:b16a9b34fa4c 92 void BME280::busRead(uint8_t *p_data, uint8_t data_size)
Clemo 0:b16a9b34fa4c 93 {
Clemo 0:b16a9b34fa4c 94 if (_i2c_address==BME280_I2C_ADDRESS1 || _i2c_address==BME280_I2C_ADDRESS2)
Clemo 0:b16a9b34fa4c 95 {
Clemo 0:b16a9b34fa4c 96 // Assume I2C bus.
Clemo 0:b16a9b34fa4c 97 i2cRead(_i2c_address,p_data,data_size);
Clemo 0:b16a9b34fa4c 98 }
Clemo 0:b16a9b34fa4c 99 else
Clemo 0:b16a9b34fa4c 100 {
Clemo 0:b16a9b34fa4c 101 // Assume SPI bus.
Clemo 0:b16a9b34fa4c 102 // First byte is supposed to be the address of the register to write to, set R/~W bit to 1.
Clemo 0:b16a9b34fa4c 103 p_data[0] |= 0x80;
Clemo 0:b16a9b34fa4c 104 spiRead(p_data,data_size);
Clemo 0:b16a9b34fa4c 105 }
Clemo 0:b16a9b34fa4c 106 }
Clemo 0:b16a9b34fa4c 107
Clemo 0:b16a9b34fa4c 108
Clemo 0:b16a9b34fa4c 109 uint8_t BME280::readUint8(uint8_t reg)
Clemo 0:b16a9b34fa4c 110 {
Clemo 0:b16a9b34fa4c 111 uint8_t data;
Clemo 0:b16a9b34fa4c 112 busWrite(&reg,1,1); // Use repeated start.
Clemo 0:b16a9b34fa4c 113 busRead(&data,1); // Read one byte.
Clemo 0:b16a9b34fa4c 114 return data;
Clemo 0:b16a9b34fa4c 115 }
Clemo 0:b16a9b34fa4c 116
Clemo 0:b16a9b34fa4c 117
Clemo 0:b16a9b34fa4c 118 uint16_t BME280::readUint16(uint8_t reg)
Clemo 0:b16a9b34fa4c 119 {
Clemo 0:b16a9b34fa4c 120 uint8_t data[2];
Clemo 0:b16a9b34fa4c 121 uint16_t value;
Clemo 0:b16a9b34fa4c 122 busWrite(&reg,1,1); // Use repeated start.
Clemo 0:b16a9b34fa4c 123 busRead(data,2); // Read two bytes.
Clemo 0:b16a9b34fa4c 124 // Process as little endian, which is the case for calibration data.
Clemo 0:b16a9b34fa4c 125 value = data[1];
Clemo 0:b16a9b34fa4c 126 value = (value<<8) | data[0];
Clemo 0:b16a9b34fa4c 127 return value;
Clemo 0:b16a9b34fa4c 128 }
Clemo 0:b16a9b34fa4c 129
Clemo 0:b16a9b34fa4c 130
Clemo 0:b16a9b34fa4c 131 void BME280::readCalibrationData(void)
Clemo 0:b16a9b34fa4c 132 {
Clemo 0:b16a9b34fa4c 133 _dig_T1 = readUint16(BME280_CAL_T1);
Clemo 0:b16a9b34fa4c 134 _dig_T2 = (int16_t) readUint16(BME280_CAL_T2);
Clemo 0:b16a9b34fa4c 135 _dig_T3 = (int16_t) readUint16(BME280_CAL_T3);
Clemo 0:b16a9b34fa4c 136 _dig_P1 = readUint16(BME280_CAL_P1);
Clemo 0:b16a9b34fa4c 137 _dig_P2 = (int16_t) readUint16(BME280_CAL_P2);
Clemo 0:b16a9b34fa4c 138 _dig_P3 = (int16_t) readUint16(BME280_CAL_P3);
Clemo 0:b16a9b34fa4c 139 _dig_P4 = (int16_t) readUint16(BME280_CAL_P4);
Clemo 0:b16a9b34fa4c 140 _dig_P5 = (int16_t) readUint16(BME280_CAL_P5);
Clemo 0:b16a9b34fa4c 141 _dig_P6 = (int16_t) readUint16(BME280_CAL_P6);
Clemo 0:b16a9b34fa4c 142 _dig_P7 = (int16_t) readUint16(BME280_CAL_P7);
Clemo 0:b16a9b34fa4c 143 _dig_P8 = (int16_t) readUint16(BME280_CAL_P8);
Clemo 0:b16a9b34fa4c 144 _dig_P9 = (int16_t) readUint16(BME280_CAL_P9);
Clemo 0:b16a9b34fa4c 145 _dig_H1 = readUint8(BME280_CAL_H1);
Clemo 0:b16a9b34fa4c 146 _dig_H2 = (int16_t) readUint16(BME280_CAL_H2);
Clemo 0:b16a9b34fa4c 147 _dig_H3 = readUint8(BME280_CAL_H3);
Clemo 0:b16a9b34fa4c 148 // H4 & H5 share a byte.
Clemo 0:b16a9b34fa4c 149 uint8_t temp1 = readUint8(BME280_CAL_H4);
Clemo 0:b16a9b34fa4c 150 uint8_t temp2 = readUint8(BME280_CAL_H45);
Clemo 0:b16a9b34fa4c 151 uint8_t temp3 = readUint8(BME280_CAL_H5);
Clemo 0:b16a9b34fa4c 152 _dig_H4 = (temp1<<4) | (temp2&0x0f);
Clemo 0:b16a9b34fa4c 153 _dig_H5 = (temp3<<4) | (temp2>>4);
Clemo 0:b16a9b34fa4c 154 _dig_H6 = (int8_t) readUint8(BME280_CAL_H6);
Clemo 0:b16a9b34fa4c 155 }
Clemo 0:b16a9b34fa4c 156
Clemo 0:b16a9b34fa4c 157
Clemo 0:b16a9b34fa4c 158 uint8_t BME280::readFrom(uint8_t reg, uint8_t data_size, uint8_t *p_data)
Clemo 0:b16a9b34fa4c 159 {
Clemo 0:b16a9b34fa4c 160 // Set start address to read from.
Clemo 0:b16a9b34fa4c 161 busWrite(&reg,1,1); // Use repeated start.
Clemo 0:b16a9b34fa4c 162 // Now read the requested number of bytes.
Clemo 0:b16a9b34fa4c 163 busRead(p_data,data_size);
Clemo 0:b16a9b34fa4c 164 return data_size;
Clemo 0:b16a9b34fa4c 165 }
Clemo 0:b16a9b34fa4c 166
Clemo 0:b16a9b34fa4c 167
Clemo 0:b16a9b34fa4c 168 void BME280::read(void)
Clemo 0:b16a9b34fa4c 169 {
Clemo 0:b16a9b34fa4c 170 // Get all the measurements in one burst (recommended).
Clemo 0:b16a9b34fa4c 171 uint8_t data[BME280_MEASUREMENT_SIZE];
Clemo 0:b16a9b34fa4c 172 readFrom(BME280_MEASUREMENT_REGISTER,BME280_MEASUREMENT_SIZE,data);
Clemo 0:b16a9b34fa4c 173 // We assume Normal mode, so it is not necessary to reissue a Forced mode command here.
Clemo 0:b16a9b34fa4c 174
Clemo 0:b16a9b34fa4c 175 // Process data.
Clemo 0:b16a9b34fa4c 176 int32_t p = assembleRawValue(&data[0],1);
Clemo 0:b16a9b34fa4c 177 int32_t t = assembleRawValue(&data[3],1);
Clemo 0:b16a9b34fa4c 178 int32_t h = assembleRawValue(&data[6],0);
Clemo 0:b16a9b34fa4c 179
Clemo 0:b16a9b34fa4c 180 _temperature = compensateTemperature(t); // First call this before calling the other compensate functions.
Clemo 0:b16a9b34fa4c 181 _pressure = compensatePressure(p); // Uses value calculated by compensateTemperature.
Clemo 0:b16a9b34fa4c 182 _humidity = compensateHumidity(h); // Uses value calculated by compensateTemperature.
Clemo 0:b16a9b34fa4c 183 }
Clemo 0:b16a9b34fa4c 184
Clemo 0:b16a9b34fa4c 185
Clemo 0:b16a9b34fa4c 186 int32_t BME280::assembleRawValue(uint8_t *p_data, uint8_t has_xlsb)
Clemo 0:b16a9b34fa4c 187 {
Clemo 0:b16a9b34fa4c 188 // Needed to decode sensor data.
Clemo 0:b16a9b34fa4c 189 uint32_t value = p_data[0];
Clemo 0:b16a9b34fa4c 190 value <<= 8;
Clemo 0:b16a9b34fa4c 191 value |= p_data[1];
Clemo 0:b16a9b34fa4c 192 if (has_xlsb!=0)
Clemo 0:b16a9b34fa4c 193 {
Clemo 0:b16a9b34fa4c 194 value <<= 4;
Clemo 0:b16a9b34fa4c 195 value |= (p_data[2]>>4);
Clemo 0:b16a9b34fa4c 196 }
Clemo 0:b16a9b34fa4c 197 return (int32_t) value;
Clemo 0:b16a9b34fa4c 198 }
Clemo 0:b16a9b34fa4c 199
Clemo 0:b16a9b34fa4c 200
Clemo 0:b16a9b34fa4c 201 void BME280::writeControlRegisters(uint8_t osrs_t, uint8_t osrs_p, uint8_t osrs_h, uint8_t mode)
Clemo 0:b16a9b34fa4c 202 {
Clemo 0:b16a9b34fa4c 203 uint8_t data[2];
Clemo 0:b16a9b34fa4c 204 data[0] = BME280_CTRL_HUM_REGISTER;
Clemo 0:b16a9b34fa4c 205 data[1] = (osrs_h&0x07);
Clemo 0:b16a9b34fa4c 206 busWrite(data,2,0);
Clemo 0:b16a9b34fa4c 207 // Writing CTRL_MEAS validates previous write to CTRL_HUM.
Clemo 0:b16a9b34fa4c 208 data[0] = BME280_CTRL_MEAS_REGISTER;
Clemo 0:b16a9b34fa4c 209 data[1] = ((osrs_t&0x07)<<5) | ((osrs_p&0x07)<<2) | (mode&0x03);
Clemo 0:b16a9b34fa4c 210 busWrite(data,2,0);
Clemo 0:b16a9b34fa4c 211 }
Clemo 0:b16a9b34fa4c 212
Clemo 0:b16a9b34fa4c 213
Clemo 0:b16a9b34fa4c 214 void BME280::writeConfigRegister(uint8_t t_sb, uint8_t filter, uint8_t spi)
Clemo 0:b16a9b34fa4c 215 {
Clemo 0:b16a9b34fa4c 216 uint8_t data[2];
Clemo 0:b16a9b34fa4c 217 data[0] = BME280_CONFIG_REGISTER;
Clemo 0:b16a9b34fa4c 218 data[1] = ((t_sb&0x07)<<5) | ((filter&0x07)<<2) | (spi&0x01);
Clemo 0:b16a9b34fa4c 219 busWrite(data,2,0);
Clemo 0:b16a9b34fa4c 220 }
Clemo 0:b16a9b34fa4c 221
Clemo 0:b16a9b34fa4c 222
Clemo 0:b16a9b34fa4c 223 void BME280::reset(void)
Clemo 0:b16a9b34fa4c 224 {
Clemo 0:b16a9b34fa4c 225 uint8_t data[2] = { BME280_RESET_REGISTER, BME280_RESET };
Clemo 0:b16a9b34fa4c 226 busWrite(data,2,0);
Clemo 0:b16a9b34fa4c 227 }
Clemo 0:b16a9b34fa4c 228
Clemo 0:b16a9b34fa4c 229
Clemo 0:b16a9b34fa4c 230 uint8_t BME280::readId(void)
Clemo 0:b16a9b34fa4c 231 {
Clemo 0:b16a9b34fa4c 232 return readUint8(BME280_ID_REGISTER);
Clemo 0:b16a9b34fa4c 233 }
Clemo 0:b16a9b34fa4c 234
Clemo 0:b16a9b34fa4c 235
Clemo 0:b16a9b34fa4c 236 #if BME280_ALLOW_FLOAT!=0
Clemo 0:b16a9b34fa4c 237
Clemo 0:b16a9b34fa4c 238 // From the driver by Bosch Sensortec
Clemo 0:b16a9b34fa4c 239
Clemo 0:b16a9b34fa4c 240 //!
Clemo 0:b16a9b34fa4c 241 // @brief Reads actual temperature from uncompensated temperature
Clemo 0:b16a9b34fa4c 242 // @note returns the value in Degree centigrade
Clemo 0:b16a9b34fa4c 243 // @note Output value of "51.23" equals 51.23 DegC.
Clemo 0:b16a9b34fa4c 244 //
Clemo 0:b16a9b34fa4c 245 // @param adc_T : value of uncompensated temperature
Clemo 0:b16a9b34fa4c 246 //
Clemo 0:b16a9b34fa4c 247 // @return Return the actual temperature in floating point
Clemo 0:b16a9b34fa4c 248 //
Clemo 0:b16a9b34fa4c 249 temperature_t BME280::compensateTemperature(int32_t adc_T)
Clemo 0:b16a9b34fa4c 250 {
Clemo 0:b16a9b34fa4c 251 double v_x1_u32;
Clemo 0:b16a9b34fa4c 252 double v_x2_u32;
Clemo 0:b16a9b34fa4c 253 double temperature;
Clemo 0:b16a9b34fa4c 254
Clemo 0:b16a9b34fa4c 255 v_x1_u32 = (((double)adc_T) / 16384.0 - ((double)_dig_T1) / 1024.0) * ((double)_dig_T2);
Clemo 0:b16a9b34fa4c 256 v_x2_u32 = ((((double)adc_T) / 131072.0 - ((double)_dig_T1) / 8192.0) * (((double)adc_T) / 131072.0 - ((double)_dig_T1) / 8192.0)) * ((double)_dig_T3);
Clemo 0:b16a9b34fa4c 257 _t_fine = (int32_t)(v_x1_u32 + v_x2_u32);
Clemo 0:b16a9b34fa4c 258 temperature = (v_x1_u32 + v_x2_u32) / 5120.0;
Clemo 0:b16a9b34fa4c 259 return temperature;
Clemo 0:b16a9b34fa4c 260 }
Clemo 0:b16a9b34fa4c 261
Clemo 0:b16a9b34fa4c 262
Clemo 0:b16a9b34fa4c 263 //!
Clemo 0:b16a9b34fa4c 264 // @brief Reads actual pressure from uncompensated pressure
Clemo 0:b16a9b34fa4c 265 // @note Returns pressure in Pa as double.
Clemo 0:b16a9b34fa4c 266 // @note Output value of "96386.2"
Clemo 0:b16a9b34fa4c 267 // equals 96386.2 Pa = 963.862 hPa.
Clemo 0:b16a9b34fa4c 268 //
Clemo 0:b16a9b34fa4c 269 // @param adc_P : value of uncompensated pressure
Clemo 0:b16a9b34fa4c 270 //
Clemo 0:b16a9b34fa4c 271 // @return Return the actual pressure in floating point
Clemo 0:b16a9b34fa4c 272 //
Clemo 0:b16a9b34fa4c 273 pressure_t BME280::compensatePressure(int32_t adc_P)
Clemo 0:b16a9b34fa4c 274 {
Clemo 0:b16a9b34fa4c 275 double v_x1_u32;
Clemo 0:b16a9b34fa4c 276 double v_x2_u32;
Clemo 0:b16a9b34fa4c 277 double pressure;
Clemo 0:b16a9b34fa4c 278
Clemo 0:b16a9b34fa4c 279 v_x1_u32 = ((double)_t_fine / 2.0) - 64000.0;
Clemo 0:b16a9b34fa4c 280 v_x2_u32 = v_x1_u32 * v_x1_u32 * ((double)_dig_P6) / 32768.0;
Clemo 0:b16a9b34fa4c 281 v_x2_u32 = v_x2_u32 + v_x1_u32 * ((double)_dig_P5) * 2.0;
Clemo 0:b16a9b34fa4c 282 v_x2_u32 = (v_x2_u32 / 4.0) + (((double)_dig_P4) * 65536.0);
Clemo 0:b16a9b34fa4c 283 v_x1_u32 = (((double)_dig_P3) * v_x1_u32 * v_x1_u32 / 524288.0 + ((double)_dig_P2) * v_x1_u32) / 524288.0;
Clemo 0:b16a9b34fa4c 284 v_x1_u32 = (1.0 + v_x1_u32 / 32768.0) * ((double)_dig_P1);
Clemo 0:b16a9b34fa4c 285 pressure = 1048576.0 - (double)adc_P;
Clemo 0:b16a9b34fa4c 286 // Avoid exception caused by division by zero.
Clemo 0:b16a9b34fa4c 287 if (v_x1_u32 != 0) pressure = (pressure - (v_x2_u32 / 4096.0)) * 6250.0 / v_x1_u32;
Clemo 0:b16a9b34fa4c 288 else return 0;
Clemo 0:b16a9b34fa4c 289 v_x1_u32 = ((double)_dig_P9) * pressure * pressure / 2147483648.0;
Clemo 0:b16a9b34fa4c 290 v_x2_u32 = pressure * ((double)_dig_P8) / 32768.0;
Clemo 0:b16a9b34fa4c 291 pressure = pressure + (v_x1_u32 + v_x2_u32 + ((double)_dig_P7)) / 16.0;
Clemo 0:b16a9b34fa4c 292
Clemo 0:b16a9b34fa4c 293 return pressure;
Clemo 0:b16a9b34fa4c 294 }
Clemo 0:b16a9b34fa4c 295
Clemo 0:b16a9b34fa4c 296
Clemo 0:b16a9b34fa4c 297 //!
Clemo 0:b16a9b34fa4c 298 // @brief Reads actual humidity from uncompensated humidity
Clemo 0:b16a9b34fa4c 299 // @note returns the value in relative humidity (%rH)
Clemo 0:b16a9b34fa4c 300 // @note Output value of "42.12" equals 42.12 %rH
Clemo 0:b16a9b34fa4c 301 //
Clemo 0:b16a9b34fa4c 302 // @param adc_H : value of uncompensated humidity
Clemo 0:b16a9b34fa4c 303 //
Clemo 0:b16a9b34fa4c 304 // @return Return the actual humidity in floating point
Clemo 0:b16a9b34fa4c 305 //
Clemo 0:b16a9b34fa4c 306 humidity_t BME280::compensateHumidity(int32_t adc_H)
Clemo 0:b16a9b34fa4c 307 {
Clemo 0:b16a9b34fa4c 308 double var_h;
Clemo 0:b16a9b34fa4c 309
Clemo 0:b16a9b34fa4c 310 var_h = (((double)_t_fine) - 76800.0);
Clemo 0:b16a9b34fa4c 311 if (var_h != 0)
Clemo 0:b16a9b34fa4c 312 {
Clemo 0:b16a9b34fa4c 313 var_h = (adc_H - (((double)_dig_H4) * 64.0 + ((double)_dig_H5) / 16384.0 * var_h)) *
Clemo 0:b16a9b34fa4c 314 (((double)_dig_H2) / 65536.0 * (1.0 + ((double) _dig_H6) / 67108864.0 *
Clemo 0:b16a9b34fa4c 315 var_h * (1.0 + ((double)_dig_H3) / 67108864.0 * var_h)));
Clemo 0:b16a9b34fa4c 316 }
Clemo 0:b16a9b34fa4c 317 else return 0;
Clemo 0:b16a9b34fa4c 318 var_h = var_h * (1.0 - ((double)_dig_H1)*var_h / 524288.0);
Clemo 0:b16a9b34fa4c 319 if (var_h > 100.0) var_h = 100.0;
Clemo 0:b16a9b34fa4c 320 else if (var_h < 0.0) var_h = 0.0;
Clemo 0:b16a9b34fa4c 321 return var_h;
Clemo 0:b16a9b34fa4c 322 }
Clemo 0:b16a9b34fa4c 323
Clemo 0:b16a9b34fa4c 324 #else /* BME280_ALLOW_FLOAT */
Clemo 0:b16a9b34fa4c 325
Clemo 0:b16a9b34fa4c 326 // From the datasheet.
Clemo 0:b16a9b34fa4c 327 // Returns temperature in DegC, resolution is 0.01 DegC. Output value of 5123 equals 51.23 DegC.
Clemo 0:b16a9b34fa4c 328 // _t_fine carries fine temperature as "global" value.
Clemo 0:b16a9b34fa4c 329 temperature_t BME280::compensateTemperature(int32_t adc_T)
Clemo 0:b16a9b34fa4c 330 {
Clemo 0:b16a9b34fa4c 331 int32_t var1, var2, T;
Clemo 0:b16a9b34fa4c 332 var1 = ((((adc_T>>3) - ((int32_t)_dig_T1<<1))) * ((int32_t)_dig_T2)) >> 11;
Clemo 0:b16a9b34fa4c 333 var2 = (((((adc_T>>4) - ((int32_t)_dig_T1)) * ((adc_T>>4) - ((int32_t)_dig_T1))) >> 12) * ((int32_t)_dig_T3)) >> 14;
Clemo 0:b16a9b34fa4c 334 _t_fine = var1 + var2;
Clemo 0:b16a9b34fa4c 335 T = (_t_fine * 5 + 128) >> 8;
Clemo 0:b16a9b34fa4c 336 return T;
Clemo 0:b16a9b34fa4c 337 }
Clemo 0:b16a9b34fa4c 338
Clemo 0:b16a9b34fa4c 339
Clemo 0:b16a9b34fa4c 340 // From the datasheet.
Clemo 0:b16a9b34fa4c 341 // Returns pressure in Pa as unsigned 32 bit integer. Output value of 96386 equals 96386 Pa = 963.86 hPa
Clemo 0:b16a9b34fa4c 342 pressure_t BME280::compensatePressure(int32_t adc_P)
Clemo 0:b16a9b34fa4c 343 {
Clemo 0:b16a9b34fa4c 344 int32_t var1, var2;
Clemo 0:b16a9b34fa4c 345 uint32_t p;
Clemo 0:b16a9b34fa4c 346 var1 = (((int32_t)_t_fine)>>1) - (int32_t)64000;
Clemo 0:b16a9b34fa4c 347 var2 = (((var1>>2) * (var1>>2)) >> 11 ) * ((int32_t)_dig_P6);
Clemo 0:b16a9b34fa4c 348 var2 = var2 + ((var1*((int32_t)_dig_P5))<<1);
Clemo 0:b16a9b34fa4c 349 var2 = (var2>>2)+(((int32_t)_dig_P4)<<16);
Clemo 0:b16a9b34fa4c 350 var1 = (((_dig_P3 * (((var1>>2) * (var1>>2)) >> 13 )) >> 3) + ((((int32_t)_dig_P2) * var1)>>1))>>18;
Clemo 0:b16a9b34fa4c 351 var1 =((((32768+var1))*((int32_t)_dig_P1))>>15);
Clemo 0:b16a9b34fa4c 352 if (var1 == 0)
Clemo 0:b16a9b34fa4c 353 {
Clemo 0:b16a9b34fa4c 354 return 0; // avoid exception caused by division by zero
Clemo 0:b16a9b34fa4c 355 }
Clemo 0:b16a9b34fa4c 356 p = (((uint32_t)(((int32_t)1048576)-adc_P)-(var2>>12)))*3125;
Clemo 0:b16a9b34fa4c 357 if (p < 0x80000000)
Clemo 0:b16a9b34fa4c 358 {
Clemo 0:b16a9b34fa4c 359 p = (p << 1) / ((uint32_t)var1);
Clemo 0:b16a9b34fa4c 360 }
Clemo 0:b16a9b34fa4c 361 else
Clemo 0:b16a9b34fa4c 362 {
Clemo 0:b16a9b34fa4c 363 p = (p / (uint32_t)var1) * 2;
Clemo 0:b16a9b34fa4c 364 }
Clemo 0:b16a9b34fa4c 365 var1 = (((int32_t)_dig_P9) * ((int32_t)(((p>>3) * (p>>3))>>13)))>>12;
Clemo 0:b16a9b34fa4c 366 var2 = (((int32_t)(p>>2)) * ((int32_t)_dig_P8))>>13;
Clemo 0:b16a9b34fa4c 367 p = (uint32_t)((int32_t)p + ((var1 + var2 + _dig_P7) >> 4));
Clemo 0:b16a9b34fa4c 368 return p;
Clemo 0:b16a9b34fa4c 369 }
Clemo 0:b16a9b34fa4c 370
Clemo 0:b16a9b34fa4c 371
Clemo 0:b16a9b34fa4c 372 // From the datasheet.
Clemo 0:b16a9b34fa4c 373 // Returns humidity in %RH as unsigned 32 bit integer in Q22.10 format (22 integer and 10 fractional bits).
Clemo 0:b16a9b34fa4c 374 // Output value of 47445 represents 47445/1024 = 46.333 %RH
Clemo 0:b16a9b34fa4c 375 humidity_t BME280::compensateHumidity(int32_t adc_H)
Clemo 0:b16a9b34fa4c 376 {
Clemo 0:b16a9b34fa4c 377 int32_t v_x1_u32r;
Clemo 0:b16a9b34fa4c 378 v_x1_u32r = (_t_fine - ((int32_t)76800));
Clemo 0:b16a9b34fa4c 379 v_x1_u32r = (((((adc_H << 14) - (((int32_t)_dig_H4) << 20) - (((int32_t)_dig_H5) * v_x1_u32r)) +
Clemo 0:b16a9b34fa4c 380 ((int32_t)16384)) >> 15) * (((((((v_x1_u32r * ((int32_t)_dig_H6)) >> 10) * (((v_x1_u32r *
Clemo 0:b16a9b34fa4c 381 ((int32_t)_dig_H3)) >> 11) + ((int32_t)32768))) >> 10) + ((int32_t)2097152)) *
Clemo 0:b16a9b34fa4c 382 ((int32_t)_dig_H2) + 8192) >> 14));
Clemo 0:b16a9b34fa4c 383 v_x1_u32r = (v_x1_u32r - (((((v_x1_u32r >> 15) * (v_x1_u32r >> 15)) >> 7) * ((int32_t)_dig_H1)) >> 4));
Clemo 0:b16a9b34fa4c 384 v_x1_u32r = (v_x1_u32r < 0 ? 0 : v_x1_u32r);
Clemo 0:b16a9b34fa4c 385 v_x1_u32r = (v_x1_u32r > 419430400 ? 419430400 : v_x1_u32r);
Clemo 0:b16a9b34fa4c 386 return (uint32_t)(v_x1_u32r>>12);
Clemo 0:b16a9b34fa4c 387 }
Clemo 0:b16a9b34fa4c 388
Clemo 0:b16a9b34fa4c 389 #endif /* BME280_ALLOW_FLOAT */