Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
BME280.cpp
00001 /***************************************************************************** 00002 * * 00003 * BOSCH BME208 Temperature Pressure Humidity Sensor Driver / I2C * 00004 * * 00005 * (c) 2015 Jens Schneider * 00006 * mailto:jens.schneider@kaust.edu.sa * 00007 * Visual Computing Center (VCC) * 00008 * King Abdullah University of Science and Technology (KAUST) * 00009 * 4700 Thuwal, Kingdom of Saudi Arabia * 00010 * * 00011 * PERMISSION GRANTED TO USE IN NON-COMMERCIAL AND EDUCATIONAL PROJECTS * 00012 * NO RESPONSIBILITY ASSUMED FOR DAMAGE OR LOSS OF ANY HARDWARE OR SOFTWARE * 00013 * * 00014 * version 0.1 * 00015 * last change 07.Nov.2015 * 00016 * * 00017 *****************************************************************************/ 00018 #include"BME280.h" 00019 00020 const uint8_t BME280::REG_HUM_LSB = 0xFE; 00021 const uint8_t BME280::REG_HUM_MSB = 0xFD; 00022 const uint8_t BME280::REG_TEMP_XLSB = 0xFC; 00023 const uint8_t BME280::REG_TEMP_LSB = 0xFB; 00024 const uint8_t BME280::REG_TEMP_MSB = 0xFA; 00025 const uint8_t BME280::REG_PRESS_XLSB = 0xF9; 00026 const uint8_t BME280::REG_PRESS_LSB = 0xF8; 00027 const uint8_t BME280::REG_PRESS_MSB = 0xF7; 00028 00029 const uint8_t BME280::REG_CONFIG = 0xF5; 00030 const uint8_t BME280::REG_CTRL_MEAS = 0xF4; 00031 const uint8_t BME280::REG_STATUS = 0xF3; 00032 const uint8_t BME280::REG_CTRL_HUM = 0xF2; 00033 const uint8_t BME280::REG_CALIB26_41_BASE = 0xE1; 00034 const uint8_t BME280::REG_RESET = 0xE0; 00035 const uint8_t BME280::REG_ID = 0xD0; 00036 const uint8_t BME280::REG_CALIB00_25_BASE = 0x88; 00037 00038 const uint8_t BME280::VAL_CALIB26_41_SIZE = 0x10; 00039 const uint8_t BME280::VAL_CALIB00_25_SIZE = 0x1A; 00040 const uint8_t BME280::VAL_CHIP_ID = 0x60; 00041 const uint8_t BME280::VAL_RESET = 0xB6; 00042 00043 const uint8_t BME280::STATUS_IDLE = 0x00; 00044 const uint8_t BME280::STATUS_MEASURING = 0x08; 00045 const uint8_t BME280::STATUS_UPDATING = 0x01; 00046 const uint8_t BME280::STATUS_ERROR = 0xFF; 00047 00048 const std::string BME280::m_name = std::string("Bosch BME280"); 00049 00050 BME280::BME280(void) : m_pI2C(NULL), m_address(0x00), m_fine_temp(0x1F3E6), m_mode(MODE_SLEEP),m_bOk(false) { 00051 // initialized m_fine_temp to 25C 00052 } 00053 00054 BME280::~BME280(void) { 00055 done(); 00056 } 00057 00058 bool BME280::init(I2C& i2c, uint8_t address) { 00059 m_bOk = false; 00060 m_pI2C = &i2c; 00061 m_address = address<<1; 00062 m_fine_temp = 0x1F3E6; 00063 if (!reset()) return false; 00064 if (read_chip_id()!=0x60) return false; 00065 if (!read_calibration()) return false; 00066 m_bOk = true; 00067 return true; 00068 } 00069 00070 const bool& BME280::is_ok(void) const { 00071 return m_bOk; 00072 } 00073 00074 bool BME280::done(void) { 00075 stop(); 00076 m_pI2C = NULL; 00077 m_address = 0x00; 00078 m_mode = MODE_SLEEP; 00079 return true; 00080 } 00081 00082 00083 bool BME280::start( BME280::sampling_t hum, 00084 BME280::sampling_t temp, 00085 BME280::sampling_t press, 00086 BME280::standby_t standby, 00087 BME280::filter_t filter, 00088 BME280::mode_t mode) { 00089 // 1. Reset 00090 if (!reset()) return false; 00091 00092 // 2. Write CONFIG 00093 uint8_t val_cfg = uint8_t(standby)<<5; 00094 val_cfg|=uint8_t(filter)<<2; 00095 if (!write8(REG_CONFIG,val_cfg)) return false; 00096 00097 // 3. Write CTRL_HUM 00098 if (!write8(REG_CTRL_HUM,uint8_t(hum))) return false; 00099 00100 // 4. Write CTRL_MEAS 00101 uint8_t val_meas = uint8_t(temp)<<5; 00102 val_meas |= uint8_t(press)<<2; 00103 val_meas |= uint8_t(mode); 00104 if (!write8(REG_CTRL_MEAS,val_meas)) return false; 00105 00106 m_mode = mode; 00107 m_bOk = true; 00108 00109 return true; 00110 } 00111 00112 bool BME280::stop(void) { 00113 return reset(); 00114 } 00115 00116 bool BME280::get(float& temperature, float& pressure, float& humidity) { 00117 int32_t T; 00118 uint32_t P, H; 00119 if (!get(T,P,H)) return false; 00120 temperature = float(T)*0.01f; // in degree C 00121 pressure = 0.01f*(float(P)/256.0f); // in hPa / mbar 00122 humidity = float(H)/1024.0f; // in % 00123 return true; 00124 } 00125 00126 bool BME280::get(int32_t& temperature, uint32_t& pressure, uint32_t& humidity) { 00127 if (m_mode!=MODE_AUTO) { 00128 // Trigger forced conversion by updating CTRL_MEAS register 00129 uint8_t val = 0x00; 00130 if (!read8(REG_CTRL_MEAS,val)) return false; 00131 val = (val&0xFC)|uint8_t(MODE_FORCED); 00132 if (!write8(REG_CTRL_MEAS,val)) return false; 00133 // Wait for measurement to finish 00134 do { 00135 val = read_status(); 00136 if ((val&STATUS_MEASURING)!=0) wait_ms(1); 00137 } while(val&STATUS_MEASURING); 00138 } 00139 int32_t rawT, rawP, rawH; 00140 if (!raw_data(rawT,rawP,rawH)) return false; 00141 temperature = compensate_T(rawT); 00142 pressure = compensate_P(rawP); 00143 humidity = compensate_H(rawH); 00144 return true; 00145 } 00146 00147 const std::string& BME280::name(void) const { 00148 return m_name; 00149 } 00150 00151 bool BME280::raw_data(int32_t& rawT, int32_t& rawP, int32_t& rawH) { 00152 if (m_pI2C==NULL) return false; 00153 uint8_t data[8]; 00154 if (!burst_read(data,8,REG_PRESS_MSB)) { 00155 rawT = rawP = rawH = 0; 00156 return false; 00157 } 00158 rawP = (int32_t(data[0])<<12)|(int32_t(data[1])<<4)|(int32_t(data[2])>>4); 00159 rawT = (int32_t(data[3])<<12)|(int32_t(data[4])<<4)|(int32_t(data[5])>>4); 00160 rawH = (int32_t(data[6])<<8)|int32_t(data[7]); 00161 return true; 00162 } 00163 00164 00165 int16_t BME280::conv_s16(const uint8_t* data, int lo, int hi) const { 00166 return int16_t(uint16_t(data[lo])|(uint16_t(data[hi])<<8)); 00167 } 00168 00169 uint16_t BME280::conv_u16(const uint8_t* data, int lo, int hi) const { 00170 return uint16_t(data[lo])|(uint16_t(data[hi])<<8); 00171 } 00172 00173 bool BME280::read_calibration(void) { 00174 if (m_pI2C==NULL) return false; 00175 return read_calibration_lo() && read_calibration_hi(); 00176 } 00177 00178 bool BME280::read_calibration_lo(void) { 00179 if (m_pI2C==NULL) return false; 00180 uint8_t data[VAL_CALIB00_25_SIZE]; 00181 if (!burst_read(data,VAL_CALIB00_25_SIZE,REG_CALIB00_25_BASE)) return false; 00182 m_calib.dig_T1 = conv_u16(data,0,1); // 0x88:89 00183 m_calib.dig_T2 = conv_s16(data,2,3); // 0x8A:8B 00184 m_calib.dig_T3 = conv_s16(data,4,5); // 0x8C:8D 00185 m_calib.dig_P1 = conv_u16(data,6,7); // 0x8E:8F 00186 m_calib.dig_P2 = conv_s16(data,8,9); // 0x90:91 00187 m_calib.dig_P3 = conv_s16(data,10,11); // 0x92:93 00188 m_calib.dig_P4 = conv_s16(data,12,13); // 0x94:95 00189 m_calib.dig_P5 = conv_s16(data,14,15); // 0x96:97 00190 m_calib.dig_P6 = conv_s16(data,16,17); // 0x98:99 00191 m_calib.dig_P7 = conv_s16(data,18,19); // 0x9A:9B 00192 m_calib.dig_P8 = conv_s16(data,20,21); // 0x9C:9D 00193 m_calib.dig_P9 = conv_s16(data,22,23); // 0x9E:9F 00194 // 0xA0 00195 m_calib.dig_H1 = data[25]; // 0xA1 00196 return true; 00197 } 00198 00199 bool BME280::read_calibration_hi(void) { 00200 if (m_pI2C==NULL) return false; 00201 uint8_t data[VAL_CALIB26_41_SIZE]; 00202 if (!burst_read(data,VAL_CALIB26_41_SIZE,REG_CALIB26_41_BASE)) return false; 00203 m_calib.dig_H2 = conv_s16(data,0,1); // 0xE1:E2 00204 m_calib.dig_H3 = data[2]; // 0xE3 00205 m_calib.dig_H4 = int16_t((uint16_t(data[3])<<8)|uint16_t((data[4]&0xF)<<4))>>4; // 0xE4:E5[3:0] 00206 m_calib.dig_H5 = int16_t((uint16_t(data[5])<<8)|uint16_t((data[4]&0xF0))>>4); // 0xE5[7:4]:E6 00207 m_calib.dig_H6 = int8_t(data[6]); // 0xE7 00208 return true; 00209 } 00210 00211 int32_t BME280::compensate_T(int32_t raw_T) { 00212 int32_t var1, var2, T; 00213 var1 = ((((raw_T>>3) - ((int32_t)m_calib.dig_T1<<1))) * ((int32_t)m_calib.dig_T2)) >> 11; 00214 var2 = (((((raw_T>>4) - ((int32_t)m_calib.dig_T1)) * ((raw_T>>4) - ((int32_t)m_calib.dig_T1))) >> 12) * ((int32_t)m_calib.dig_T3)) >> 14; 00215 m_fine_temp = var1 + var2; 00216 T = (m_fine_temp * 5 + 128) >> 8; 00217 return T; 00218 } 00219 00220 uint32_t BME280::compensate_P(int32_t raw_P) { 00221 int64_t var1, var2, p; 00222 var1 = ((int64_t)m_fine_temp) - 128000; 00223 var2 = var1 * var1 * (int64_t)m_calib.dig_P6; 00224 var2 = var2 + ((var1*(int64_t)m_calib.dig_P5)<<17); 00225 var2 = var2 + (((int64_t)m_calib.dig_P4)<<35); 00226 var1 = ((var1 * var1 * (int64_t)m_calib.dig_P3)>>8) + ((var1 * (int64_t)m_calib.dig_P2)<<12); 00227 var1 = (((((int64_t)1)<<47)+var1))*((int64_t)m_calib.dig_P1)>>33; 00228 if (var1 == 0) return false; // avoid division by zero 00229 p = 1048576-raw_P; 00230 p = (((p<<31)-var2)*3125)/var1; 00231 var1 = (((int64_t)m_calib.dig_P9) * (p>>13) * (p>>13)) >> 25; 00232 var2 = (((int64_t)m_calib.dig_P8) * p) >> 19; 00233 p = ((p + var1 + var2) >> 8) + (((int64_t)m_calib.dig_P7)<<4); 00234 return (uint32_t)p; 00235 } 00236 00237 uint32_t BME280::compensate_H(int32_t raw_H) { 00238 int32_t v_x1_u32r; 00239 v_x1_u32r = (m_fine_temp - ((int32_t)76800)); 00240 v_x1_u32r = (((((raw_H << 14) - (((int32_t)m_calib.dig_H4) << 20) - (((int32_t)m_calib.dig_H5) * v_x1_u32r)) + 00241 ((int32_t)16384)) >> 15) * (((((((v_x1_u32r * ((int32_t)m_calib.dig_H6)) >> 10) * (((v_x1_u32r * 00242 ((int32_t)m_calib.dig_H3)) >> 11) + ((int32_t)32768))) >> 10) + ((int32_t)2097152)) * 00243 ((int32_t)m_calib.dig_H2) + 8192) >> 14)); 00244 v_x1_u32r = (v_x1_u32r - (((((v_x1_u32r >> 15) * (v_x1_u32r >> 15)) >> 7) * ((int32_t)m_calib.dig_H1)) >> 4)); 00245 v_x1_u32r = (v_x1_u32r < 0 ? 0 : v_x1_u32r); 00246 v_x1_u32r = (v_x1_u32r > 419430400 ? 419430400 : v_x1_u32r); 00247 return (uint32_t)(v_x1_u32r>>12); 00248 } 00249 00250 // ======================================== LOW LEVEL API ======================================== 00251 bool BME280::reset(void) { 00252 m_bOk = false; 00253 if (write8(REG_RESET,VAL_RESET)) { 00254 wait_ms(2); 00255 m_mode = MODE_SLEEP; 00256 return true; 00257 } 00258 return false; 00259 } 00260 00261 uint8_t BME280::read_chip_id(void) { 00262 uint8_t result; 00263 if (read8(REG_ID,result)) return result; 00264 else return 0x00; 00265 } 00266 00267 uint8_t BME280::read_status(void) { 00268 uint8_t result; 00269 if (read8(REG_STATUS,result)) return result&0x9; 00270 else return STATUS_ERROR; 00271 } 00272 00273 bool BME280::read8(uint8_t reg, uint8_t& val) { 00274 if (m_pI2C==NULL) return false; 00275 uint8_t ok = 0x00; 00276 val = 0x00; 00277 m_pI2C->start(); 00278 ok = (ok<<1)|m_pI2C->write(m_address); 00279 ok = (ok<<1)|m_pI2C->write(reg); 00280 m_pI2C->start(); 00281 ok = (ok<<1)|m_pI2C->write(m_address|1); 00282 val = m_pI2C->read(0); 00283 m_pI2C->stop(); 00284 return ok==0x7; 00285 } 00286 00287 bool BME280::write8(uint8_t reg, uint8_t val) { 00288 if (m_pI2C==NULL) return false; 00289 uint8_t ok = 0x00; 00290 m_pI2C->start(); 00291 ok = (ok<<1)|m_pI2C->write(m_address); 00292 ok = (ok<<1)|m_pI2C->write(reg); 00293 ok = (ok<<1)|m_pI2C->write(val); 00294 m_pI2C->stop(); 00295 return ok==0x7; 00296 } 00297 00298 const BME280::calib_t& BME280::calib(void) const { 00299 return m_calib; 00300 } 00301 00302 bool BME280::burst_read(uint8_t* data, uint8_t nBytes, uint8_t reg) { 00303 if (m_pI2C==NULL) return false; 00304 if (nBytes==0) return false; 00305 if (data==NULL) return false; 00306 uint8_t ok = 0x00; 00307 m_pI2C->start(); 00308 ok = (ok<<1)|m_pI2C->write(m_address); 00309 ok = (ok<<1)|m_pI2C->write(reg); 00310 m_pI2C->start(); 00311 ok = (ok<<1)|m_pI2C->write(m_address|1); 00312 for (int i=0; i<nBytes-1; i++) data[i] = m_pI2C->read(1); 00313 data[nBytes-1] = m_pI2C->read(0); 00314 m_pI2C->stop(); 00315 if (ok!=0x7) { 00316 memset(data,0,nBytes); 00317 return false; 00318 } 00319 return true; 00320 }
Generated on Wed Jul 13 2022 19:37:59 by
1.7.2