BMP180 Pressure/Temperature Sensor library
Dependents: frdm_mikroklimat Weather_Station WMG Sample_BMP180 ... more
BMP180.cpp
00001 /* 00002 @file BMP180.cpp 00003 00004 @brief Barometric Pressure and Temperature Sensor BMP180 Breakout I2C Library 00005 00006 @Author spiridion (http://mailme.spiridion.net) 00007 00008 Tested on LPC1768 and FRDM-KL25Z 00009 00010 Copyright (c) 2014 spiridion 00011 Released under the MIT License (see http://mbed.org/license/mit) 00012 00013 Documentation regarding the BMP180 can be found here: 00014 http://mbed.org/media/uploads/spiridion/bst-bmp180-ds000-09.pdf 00015 */ 00016 00017 #include "BMP180.h" 00018 #include "mbed.h" 00019 00020 // Uncomment to test the documentation algorithm against the documentation example 00021 // Result should be 699.64 hPa and 15°C 00022 // #define BMP180_TEST_FORMULA 00023 00024 BMP180::BMP180(PinName sda, PinName scl, int address) 00025 : m_i2c(sda,scl), m_addr(address) 00026 { 00027 m_altitude = 0; 00028 m_oss = BMP180_OSS_NORMAL; 00029 m_temperature = UNSET_BMP180_TEMPERATURE_VALUE; 00030 m_pressure = UNSET_BMP180_PRESSURE_VALUE; 00031 } 00032 00033 BMP180::BMP180(I2C& i2c, int address) 00034 : m_i2c(i2c), m_addr(address) 00035 { 00036 m_altitude = 0; 00037 m_oss = BMP180_OSS_NORMAL; 00038 m_temperature = UNSET_BMP180_TEMPERATURE_VALUE; 00039 m_pressure = UNSET_BMP180_PRESSURE_VALUE; 00040 } 00041 00042 int BMP180::Initialize(float altitude, int overSamplingSetting) 00043 { 00044 char data[22]; 00045 int errors = 0; 00046 00047 m_altitude = altitude; 00048 m_oss = overSamplingSetting; 00049 m_temperature = UNSET_BMP180_TEMPERATURE_VALUE; 00050 m_pressure = UNSET_BMP180_PRESSURE_VALUE; 00051 00052 // read calibration data 00053 data[0]=0xAA; 00054 errors = m_i2c.write(m_addr, data, 1); // set the eeprom pointer position to 0xAA 00055 errors += m_i2c.read(m_addr, data, 22); // read 11 x 16 bits at this position 00056 wait_ms(10); 00057 00058 // store calibration data for further calculus 00059 ac1 = data[0] << 8 | data[1]; 00060 ac2 = data[2] << 8 | data[3]; 00061 ac3 = data[4] << 8 | data[5]; 00062 ac4 = data[6] << 8 | data[7]; 00063 ac5 = data[8] << 8 | data[9]; 00064 ac6 = data[10] << 8 | data[11]; 00065 b1 = data[12] << 8 | data[13]; 00066 b2 = data[14] << 8 | data[15]; 00067 mb = data[16] << 8 | data[17]; 00068 mc = data[18] << 8 | data[19]; 00069 md = data[20] << 8 | data[21]; 00070 00071 #ifdef BMP180_TEST_FORMULA 00072 ac1 = 408; 00073 ac2 = -72; 00074 ac3 = -14383; 00075 ac4 = 32741; 00076 ac5 = 32757; 00077 ac6 = 23153; 00078 b1 = 6190; 00079 b2 = 4; 00080 mb = -32768; 00081 mc = -8711; 00082 md = 2868; 00083 m_oss = 0; 00084 errors = 0; 00085 #endif // #ifdef BMP180_TEST_FORMULA 00086 00087 return errors? 0 : 1; 00088 } 00089 00090 int BMP180::ReadData(float* pTemperature, float* pPressure) 00091 { 00092 long t, p; 00093 00094 if (!ReadRawTemperature(&t) || !ReadRawPressure(&p)) 00095 { 00096 m_temperature = UNSET_BMP180_TEMPERATURE_VALUE; 00097 m_pressure = UNSET_BMP180_PRESSURE_VALUE; 00098 return 0; 00099 } 00100 00101 m_temperature = TrueTemperature(t); 00102 m_pressure = TruePressure(p); 00103 00104 if (pPressure) 00105 *pPressure = m_pressure; 00106 if (pTemperature) 00107 *pTemperature = m_temperature; 00108 00109 return 1; 00110 } 00111 00112 int BMP180::ReadRawTemperature(long* pUt) 00113 { 00114 int errors = 0; 00115 char data[2]; 00116 00117 // request temperature measurement 00118 data[0] = 0xF4; 00119 data[1] = 0x2E; 00120 errors = m_i2c.write(m_addr, data, 2); // write 0XF2 into reg 0XF4 00121 00122 wait_ms(4.5F); 00123 00124 // read raw temperature data 00125 data[0] = 0xF6; 00126 errors += m_i2c.write(m_addr, data, 2); // set eeprom pointer position to 0XF6 00127 errors += m_i2c.read(m_addr, data, 2); // get 16 bits at this position 00128 00129 #ifdef BMP180_TEST_FORMULA 00130 errors = 0; 00131 #endif // #ifdef BMP180_TEST_FORMULA 00132 00133 if (errors) 00134 return 0; 00135 else 00136 *pUt = data[0] << 8 | data[1]; 00137 00138 #ifdef BMP180_TEST_FORMULA 00139 *pUt = 27898; 00140 #endif // #ifdef BMP180_TEST_FORMULA 00141 00142 return 1; 00143 } 00144 00145 int BMP180::ReadRawPressure(long* pUp) 00146 { 00147 int errors = 0; 00148 char data[2]; 00149 00150 // request pressure measurement 00151 data[0] = 0xF4; 00152 data[1] = 0x34 + (m_oss << 6); 00153 errors = m_i2c.write(m_addr, data, 2); // write 0x34 + (m_oss << 6) into reg 0XF4 00154 00155 switch (m_oss) 00156 { 00157 case BMP180_OSS_ULTRA_LOW_POWER: wait_ms(4.5); break; 00158 case BMP180_OSS_NORMAL: wait_ms(7.5); break; 00159 case BMP180_OSS_HIGH_RESOLUTION: wait_ms(13.5); break; 00160 case BMP180_OSS_ULTRA_HIGH_RESOLUTION: wait_ms(25.5); break; 00161 } 00162 00163 // read raw pressure data 00164 data[0] = 0xF6; 00165 errors += m_i2c.write(m_addr, data, 1); // set eeprom pointer position to 0XF6 00166 errors += m_i2c.read(m_addr, data, 2); // get 16 bits at this position 00167 00168 #ifdef BMP180_TEST_FORMULA 00169 errors = 0; 00170 #endif // #ifdef BMP180_TEST_FORMULA 00171 00172 if (errors) 00173 return 0; 00174 else 00175 *pUp = (data[0] << 16 | data[1] << 8) >> (8 - m_oss); 00176 #ifdef BMP180_TEST_FORMULA 00177 *pUp = 23843; 00178 #endif // #ifdef BMP180_TEST_FORMULA 00179 00180 return 1; 00181 } 00182 00183 float BMP180::TrueTemperature(long ut) 00184 { 00185 long t; 00186 00187 // straight out from the documentation 00188 x1 = ((ut - ac6) * ac5) >> 15; 00189 x2 = ((long)mc << 11) / (x1 + md); 00190 b5 = x1 + x2; 00191 t = (b5 + 8) >> 4; 00192 00193 // convert to celcius 00194 return t / 10.F; 00195 } 00196 00197 float BMP180::TruePressure(long up) 00198 { 00199 long p; 00200 00201 // straight out from the documentation 00202 b6 = b5 - 4000; 00203 x1 = (b2 * (b6 * b6 >> 12)) >> 11; 00204 x2 = ac2 * b6 >> 11; 00205 x3 = x1 + x2; 00206 b3 = (((ac1 * 4 + x3) << m_oss) + 2) >> 2; 00207 x1 = (ac3 * b6) >> 13; 00208 x2 = (b1 * ((b6 * b6) >> 12)) >> 16; 00209 x3 = ((x1 + x2) + 2) >> 2; 00210 b4 = ac4 * (unsigned long)(x3 + 32768) >> 15; 00211 b7 = ((unsigned long)up - b3)* (50000 >> m_oss); 00212 if (b7 < 0x80000000) 00213 p = (b7 << 1) / b4; 00214 else 00215 p = (b7 / b4) << 1; 00216 x1 = (p >> 8) * (p >> 8); 00217 x1 = (x1 * 3038) >> 16; 00218 x2 = (-7357 * p) >> 16; 00219 p = p + ((x1 + x2 + 3791) >> 4); 00220 00221 // convert to hPa and, if altitude has been initialized, to sea level pressure 00222 if (m_altitude == 0.F) 00223 return p / 100.F; 00224 else 00225 return p / (100.F * pow((1.F - m_altitude / 44330.0L), 5.255L)); 00226 }
Generated on Mon Jul 18 2022 05:11:00 by 1.7.2