BMP180 Pressure/Temperature Sensor library
Dependents: GliderFuncTest1 DropTest
Fork of BMP180 by
BMP180.cpp@3:ae101ea7bd90, 2017-04-24 (annotated)
- Committer:
- chasefarmer2808
- Date:
- Mon Apr 24 21:34:02 2017 +0000
- Revision:
- 3:ae101ea7bd90
- Parent:
- 2:1dad52218be5
accurat;
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
spiridion | 0:9a0671b6009f | 1 | /* |
spiridion | 0:9a0671b6009f | 2 | @file BMP180.cpp |
spiridion | 0:9a0671b6009f | 3 | |
spiridion | 0:9a0671b6009f | 4 | @brief Barometric Pressure and Temperature Sensor BMP180 Breakout I2C Library |
spiridion | 0:9a0671b6009f | 5 | |
spiridion | 0:9a0671b6009f | 6 | @Author spiridion (http://mailme.spiridion.net) |
spiridion | 0:9a0671b6009f | 7 | |
spiridion | 0:9a0671b6009f | 8 | Tested on LPC1768 and FRDM-KL25Z |
spiridion | 0:9a0671b6009f | 9 | |
spiridion | 0:9a0671b6009f | 10 | Copyright (c) 2014 spiridion |
spiridion | 0:9a0671b6009f | 11 | Released under the MIT License (see http://mbed.org/license/mit) |
spiridion | 0:9a0671b6009f | 12 | |
spiridion | 0:9a0671b6009f | 13 | Documentation regarding the BMP180 can be found here: |
chasefarmer2808 | 3:ae101ea7bd90 | 14 | http://mbed.org/media/uploads/spiridion/bst-bmp180-ds000-09.pdf |
spiridion | 0:9a0671b6009f | 15 | */ |
spiridion | 0:9a0671b6009f | 16 | |
spiridion | 0:9a0671b6009f | 17 | #include "BMP180.h" |
spiridion | 0:9a0671b6009f | 18 | #include "mbed.h" |
spiridion | 0:9a0671b6009f | 19 | |
spiridion | 0:9a0671b6009f | 20 | // Uncomment to test the documentation algorithm against the documentation example |
spiridion | 0:9a0671b6009f | 21 | // Result should be 699.64 hPa and 15°C |
spiridion | 0:9a0671b6009f | 22 | // #define BMP180_TEST_FORMULA |
spiridion | 0:9a0671b6009f | 23 | |
spiridion | 0:9a0671b6009f | 24 | BMP180::BMP180(PinName sda, PinName scl, int address) |
spiridion | 0:9a0671b6009f | 25 | : m_i2c(sda,scl), m_addr(address) |
spiridion | 0:9a0671b6009f | 26 | { |
spiridion | 1:072073c79cfd | 27 | m_altitude = 0; |
spiridion | 1:072073c79cfd | 28 | m_oss = BMP180_OSS_NORMAL; |
spiridion | 1:072073c79cfd | 29 | m_temperature = UNSET_BMP180_TEMPERATURE_VALUE; |
spiridion | 1:072073c79cfd | 30 | m_pressure = UNSET_BMP180_PRESSURE_VALUE; |
spiridion | 0:9a0671b6009f | 31 | } |
spiridion | 0:9a0671b6009f | 32 | |
spiridion | 0:9a0671b6009f | 33 | BMP180::BMP180(I2C& i2c, int address) |
spiridion | 0:9a0671b6009f | 34 | : m_i2c(i2c), m_addr(address) |
spiridion | 0:9a0671b6009f | 35 | { |
spiridion | 1:072073c79cfd | 36 | m_altitude = 0; |
spiridion | 1:072073c79cfd | 37 | m_oss = BMP180_OSS_NORMAL; |
spiridion | 1:072073c79cfd | 38 | m_temperature = UNSET_BMP180_TEMPERATURE_VALUE; |
spiridion | 1:072073c79cfd | 39 | m_pressure = UNSET_BMP180_PRESSURE_VALUE; |
spiridion | 0:9a0671b6009f | 40 | } |
spiridion | 0:9a0671b6009f | 41 | |
spiridion | 0:9a0671b6009f | 42 | int BMP180::Initialize(float altitude, int overSamplingSetting) |
spiridion | 0:9a0671b6009f | 43 | { |
spiridion | 0:9a0671b6009f | 44 | char data[22]; |
spiridion | 0:9a0671b6009f | 45 | int errors = 0; |
spiridion | 0:9a0671b6009f | 46 | |
spiridion | 0:9a0671b6009f | 47 | m_altitude = altitude; |
spiridion | 0:9a0671b6009f | 48 | m_oss = overSamplingSetting; |
spiridion | 0:9a0671b6009f | 49 | m_temperature = UNSET_BMP180_TEMPERATURE_VALUE; |
spiridion | 0:9a0671b6009f | 50 | m_pressure = UNSET_BMP180_PRESSURE_VALUE; |
spiridion | 0:9a0671b6009f | 51 | |
spiridion | 0:9a0671b6009f | 52 | // read calibration data |
spiridion | 0:9a0671b6009f | 53 | data[0]=0xAA; |
spiridion | 0:9a0671b6009f | 54 | errors = m_i2c.write(m_addr, data, 1); // set the eeprom pointer position to 0xAA |
spiridion | 0:9a0671b6009f | 55 | errors += m_i2c.read(m_addr, data, 22); // read 11 x 16 bits at this position |
spiridion | 0:9a0671b6009f | 56 | wait_ms(10); |
spiridion | 0:9a0671b6009f | 57 | |
spiridion | 0:9a0671b6009f | 58 | // store calibration data for further calculus |
spiridion | 0:9a0671b6009f | 59 | ac1 = data[0] << 8 | data[1]; |
spiridion | 0:9a0671b6009f | 60 | ac2 = data[2] << 8 | data[3]; |
spiridion | 0:9a0671b6009f | 61 | ac3 = data[4] << 8 | data[5]; |
spiridion | 0:9a0671b6009f | 62 | ac4 = data[6] << 8 | data[7]; |
spiridion | 0:9a0671b6009f | 63 | ac5 = data[8] << 8 | data[9]; |
spiridion | 0:9a0671b6009f | 64 | ac6 = data[10] << 8 | data[11]; |
spiridion | 0:9a0671b6009f | 65 | b1 = data[12] << 8 | data[13]; |
spiridion | 0:9a0671b6009f | 66 | b2 = data[14] << 8 | data[15]; |
spiridion | 0:9a0671b6009f | 67 | mb = data[16] << 8 | data[17]; |
spiridion | 0:9a0671b6009f | 68 | mc = data[18] << 8 | data[19]; |
spiridion | 0:9a0671b6009f | 69 | md = data[20] << 8 | data[21]; |
spiridion | 0:9a0671b6009f | 70 | |
spiridion | 0:9a0671b6009f | 71 | #ifdef BMP180_TEST_FORMULA |
spiridion | 0:9a0671b6009f | 72 | ac1 = 408; |
spiridion | 0:9a0671b6009f | 73 | ac2 = -72; |
spiridion | 0:9a0671b6009f | 74 | ac3 = -14383; |
spiridion | 0:9a0671b6009f | 75 | ac4 = 32741; |
spiridion | 0:9a0671b6009f | 76 | ac5 = 32757; |
spiridion | 0:9a0671b6009f | 77 | ac6 = 23153; |
spiridion | 0:9a0671b6009f | 78 | b1 = 6190; |
spiridion | 0:9a0671b6009f | 79 | b2 = 4; |
spiridion | 0:9a0671b6009f | 80 | mb = -32768; |
spiridion | 0:9a0671b6009f | 81 | mc = -8711; |
spiridion | 0:9a0671b6009f | 82 | md = 2868; |
spiridion | 0:9a0671b6009f | 83 | m_oss = 0; |
spiridion | 0:9a0671b6009f | 84 | errors = 0; |
spiridion | 0:9a0671b6009f | 85 | #endif // #ifdef BMP180_TEST_FORMULA |
spiridion | 0:9a0671b6009f | 86 | |
spiridion | 0:9a0671b6009f | 87 | return errors? 0 : 1; |
spiridion | 0:9a0671b6009f | 88 | } |
spiridion | 0:9a0671b6009f | 89 | |
chasefarmer2808 | 2:1dad52218be5 | 90 | int BMP180::ReadData(float* pTemperature, float* pPressure, float* pAltitude) |
spiridion | 0:9a0671b6009f | 91 | { |
spiridion | 0:9a0671b6009f | 92 | long t, p; |
spiridion | 0:9a0671b6009f | 93 | |
spiridion | 0:9a0671b6009f | 94 | if (!ReadRawTemperature(&t) || !ReadRawPressure(&p)) |
spiridion | 0:9a0671b6009f | 95 | { |
spiridion | 0:9a0671b6009f | 96 | m_temperature = UNSET_BMP180_TEMPERATURE_VALUE; |
spiridion | 0:9a0671b6009f | 97 | m_pressure = UNSET_BMP180_PRESSURE_VALUE; |
spiridion | 0:9a0671b6009f | 98 | return 0; |
spiridion | 0:9a0671b6009f | 99 | } |
spiridion | 0:9a0671b6009f | 100 | |
spiridion | 0:9a0671b6009f | 101 | m_temperature = TrueTemperature(t); |
spiridion | 0:9a0671b6009f | 102 | m_pressure = TruePressure(p); |
spiridion | 0:9a0671b6009f | 103 | |
spiridion | 0:9a0671b6009f | 104 | if (pPressure) |
spiridion | 0:9a0671b6009f | 105 | *pPressure = m_pressure; |
spiridion | 0:9a0671b6009f | 106 | if (pTemperature) |
spiridion | 0:9a0671b6009f | 107 | *pTemperature = m_temperature; |
chasefarmer2808 | 3:ae101ea7bd90 | 108 | |
chasefarmer2808 | 3:ae101ea7bd90 | 109 | *pAltitude = getAltitude(pPressure); |
chasefarmer2808 | 3:ae101ea7bd90 | 110 | return 1; |
spiridion | 0:9a0671b6009f | 111 | } |
spiridion | 0:9a0671b6009f | 112 | |
chasefarmer2808 | 3:ae101ea7bd90 | 113 | float BMP180::getAltitude(float* p) |
chasefarmer2808 | 3:ae101ea7bd90 | 114 | { /* |
chasefarmer2808 | 3:ae101ea7bd90 | 115 | // formula for conversion directly from documentation |
chasefarmer2808 | 3:ae101ea7bd90 | 116 | float altitude = (*p / SENSORS_PRESSURE_SEALEVELHPA); |
chasefarmer2808 | 2:1dad52218be5 | 117 | altitude = pow(altitude, (float)(1 / 5.255)); |
chasefarmer2808 | 2:1dad52218be5 | 118 | altitude = 44330 * (1 - altitude); |
chasefarmer2808 | 2:1dad52218be5 | 119 | return altitude; |
chasefarmer2808 | 3:ae101ea7bd90 | 120 | */ |
chasefarmer2808 | 3:ae101ea7bd90 | 121 | return 44330.0 * (1.0 - pow((float)(*p / SENSORS_PRESSURE_SEALEVELHPA), (float)0.1903)); |
chasefarmer2808 | 2:1dad52218be5 | 122 | } |
chasefarmer2808 | 2:1dad52218be5 | 123 | |
spiridion | 0:9a0671b6009f | 124 | int BMP180::ReadRawTemperature(long* pUt) |
spiridion | 0:9a0671b6009f | 125 | { |
spiridion | 0:9a0671b6009f | 126 | int errors = 0; |
spiridion | 0:9a0671b6009f | 127 | char data[2]; |
spiridion | 0:9a0671b6009f | 128 | |
spiridion | 0:9a0671b6009f | 129 | // request temperature measurement |
spiridion | 0:9a0671b6009f | 130 | data[0] = 0xF4; |
spiridion | 0:9a0671b6009f | 131 | data[1] = 0x2E; |
spiridion | 0:9a0671b6009f | 132 | errors = m_i2c.write(m_addr, data, 2); // write 0XF2 into reg 0XF4 |
spiridion | 0:9a0671b6009f | 133 | |
spiridion | 0:9a0671b6009f | 134 | wait_ms(4.5F); |
spiridion | 0:9a0671b6009f | 135 | |
spiridion | 0:9a0671b6009f | 136 | // read raw temperature data |
spiridion | 0:9a0671b6009f | 137 | data[0] = 0xF6; |
spiridion | 0:9a0671b6009f | 138 | errors += m_i2c.write(m_addr, data, 2); // set eeprom pointer position to 0XF6 |
spiridion | 0:9a0671b6009f | 139 | errors += m_i2c.read(m_addr, data, 2); // get 16 bits at this position |
spiridion | 0:9a0671b6009f | 140 | |
spiridion | 0:9a0671b6009f | 141 | #ifdef BMP180_TEST_FORMULA |
spiridion | 0:9a0671b6009f | 142 | errors = 0; |
spiridion | 0:9a0671b6009f | 143 | #endif // #ifdef BMP180_TEST_FORMULA |
spiridion | 0:9a0671b6009f | 144 | |
spiridion | 0:9a0671b6009f | 145 | if (errors) |
spiridion | 0:9a0671b6009f | 146 | return 0; |
spiridion | 0:9a0671b6009f | 147 | else |
spiridion | 0:9a0671b6009f | 148 | *pUt = data[0] << 8 | data[1]; |
spiridion | 0:9a0671b6009f | 149 | |
spiridion | 0:9a0671b6009f | 150 | #ifdef BMP180_TEST_FORMULA |
spiridion | 0:9a0671b6009f | 151 | *pUt = 27898; |
spiridion | 0:9a0671b6009f | 152 | #endif // #ifdef BMP180_TEST_FORMULA |
spiridion | 0:9a0671b6009f | 153 | |
spiridion | 0:9a0671b6009f | 154 | return 1; |
spiridion | 0:9a0671b6009f | 155 | } |
spiridion | 0:9a0671b6009f | 156 | |
spiridion | 0:9a0671b6009f | 157 | int BMP180::ReadRawPressure(long* pUp) |
spiridion | 0:9a0671b6009f | 158 | { |
spiridion | 0:9a0671b6009f | 159 | int errors = 0; |
spiridion | 0:9a0671b6009f | 160 | char data[2]; |
spiridion | 0:9a0671b6009f | 161 | |
spiridion | 0:9a0671b6009f | 162 | // request pressure measurement |
spiridion | 0:9a0671b6009f | 163 | data[0] = 0xF4; |
spiridion | 0:9a0671b6009f | 164 | data[1] = 0x34 + (m_oss << 6); |
spiridion | 0:9a0671b6009f | 165 | errors = m_i2c.write(m_addr, data, 2); // write 0x34 + (m_oss << 6) into reg 0XF4 |
spiridion | 0:9a0671b6009f | 166 | |
spiridion | 0:9a0671b6009f | 167 | switch (m_oss) |
spiridion | 0:9a0671b6009f | 168 | { |
spiridion | 0:9a0671b6009f | 169 | case BMP180_OSS_ULTRA_LOW_POWER: wait_ms(4.5); break; |
spiridion | 0:9a0671b6009f | 170 | case BMP180_OSS_NORMAL: wait_ms(7.5); break; |
spiridion | 0:9a0671b6009f | 171 | case BMP180_OSS_HIGH_RESOLUTION: wait_ms(13.5); break; |
spiridion | 0:9a0671b6009f | 172 | case BMP180_OSS_ULTRA_HIGH_RESOLUTION: wait_ms(25.5); break; |
spiridion | 0:9a0671b6009f | 173 | } |
spiridion | 0:9a0671b6009f | 174 | |
spiridion | 0:9a0671b6009f | 175 | // read raw pressure data |
spiridion | 0:9a0671b6009f | 176 | data[0] = 0xF6; |
spiridion | 0:9a0671b6009f | 177 | errors += m_i2c.write(m_addr, data, 1); // set eeprom pointer position to 0XF6 |
spiridion | 0:9a0671b6009f | 178 | errors += m_i2c.read(m_addr, data, 2); // get 16 bits at this position |
spiridion | 0:9a0671b6009f | 179 | |
spiridion | 0:9a0671b6009f | 180 | #ifdef BMP180_TEST_FORMULA |
spiridion | 0:9a0671b6009f | 181 | errors = 0; |
spiridion | 0:9a0671b6009f | 182 | #endif // #ifdef BMP180_TEST_FORMULA |
spiridion | 0:9a0671b6009f | 183 | |
spiridion | 0:9a0671b6009f | 184 | if (errors) |
spiridion | 0:9a0671b6009f | 185 | return 0; |
spiridion | 0:9a0671b6009f | 186 | else |
spiridion | 0:9a0671b6009f | 187 | *pUp = (data[0] << 16 | data[1] << 8) >> (8 - m_oss); |
spiridion | 0:9a0671b6009f | 188 | #ifdef BMP180_TEST_FORMULA |
spiridion | 0:9a0671b6009f | 189 | *pUp = 23843; |
spiridion | 0:9a0671b6009f | 190 | #endif // #ifdef BMP180_TEST_FORMULA |
spiridion | 0:9a0671b6009f | 191 | |
spiridion | 0:9a0671b6009f | 192 | return 1; |
spiridion | 0:9a0671b6009f | 193 | } |
spiridion | 0:9a0671b6009f | 194 | |
spiridion | 0:9a0671b6009f | 195 | float BMP180::TrueTemperature(long ut) |
spiridion | 0:9a0671b6009f | 196 | { |
spiridion | 0:9a0671b6009f | 197 | long t; |
spiridion | 0:9a0671b6009f | 198 | |
spiridion | 0:9a0671b6009f | 199 | // straight out from the documentation |
spiridion | 0:9a0671b6009f | 200 | x1 = ((ut - ac6) * ac5) >> 15; |
spiridion | 0:9a0671b6009f | 201 | x2 = ((long)mc << 11) / (x1 + md); |
spiridion | 0:9a0671b6009f | 202 | b5 = x1 + x2; |
spiridion | 0:9a0671b6009f | 203 | t = (b5 + 8) >> 4; |
spiridion | 0:9a0671b6009f | 204 | |
spiridion | 0:9a0671b6009f | 205 | // convert to celcius |
spiridion | 0:9a0671b6009f | 206 | return t / 10.F; |
spiridion | 0:9a0671b6009f | 207 | } |
spiridion | 0:9a0671b6009f | 208 | |
spiridion | 0:9a0671b6009f | 209 | float BMP180::TruePressure(long up) |
spiridion | 0:9a0671b6009f | 210 | { |
spiridion | 0:9a0671b6009f | 211 | long p; |
spiridion | 0:9a0671b6009f | 212 | |
spiridion | 0:9a0671b6009f | 213 | // straight out from the documentation |
spiridion | 0:9a0671b6009f | 214 | b6 = b5 - 4000; |
spiridion | 0:9a0671b6009f | 215 | x1 = (b2 * (b6 * b6 >> 12)) >> 11; |
spiridion | 0:9a0671b6009f | 216 | x2 = ac2 * b6 >> 11; |
spiridion | 0:9a0671b6009f | 217 | x3 = x1 + x2; |
spiridion | 0:9a0671b6009f | 218 | b3 = (((ac1 * 4 + x3) << m_oss) + 2) >> 2; |
spiridion | 0:9a0671b6009f | 219 | x1 = (ac3 * b6) >> 13; |
spiridion | 0:9a0671b6009f | 220 | x2 = (b1 * ((b6 * b6) >> 12)) >> 16; |
spiridion | 0:9a0671b6009f | 221 | x3 = ((x1 + x2) + 2) >> 2; |
spiridion | 0:9a0671b6009f | 222 | b4 = ac4 * (unsigned long)(x3 + 32768) >> 15; |
spiridion | 0:9a0671b6009f | 223 | b7 = ((unsigned long)up - b3)* (50000 >> m_oss); |
spiridion | 0:9a0671b6009f | 224 | if (b7 < 0x80000000) |
spiridion | 0:9a0671b6009f | 225 | p = (b7 << 1) / b4; |
spiridion | 0:9a0671b6009f | 226 | else |
spiridion | 0:9a0671b6009f | 227 | p = (b7 / b4) << 1; |
spiridion | 0:9a0671b6009f | 228 | x1 = (p >> 8) * (p >> 8); |
spiridion | 0:9a0671b6009f | 229 | x1 = (x1 * 3038) >> 16; |
spiridion | 0:9a0671b6009f | 230 | x2 = (-7357 * p) >> 16; |
spiridion | 0:9a0671b6009f | 231 | p = p + ((x1 + x2 + 3791) >> 4); |
chasefarmer2808 | 3:ae101ea7bd90 | 232 | |
spiridion | 0:9a0671b6009f | 233 | // convert to hPa and, if altitude has been initialized, to sea level pressure |
spiridion | 0:9a0671b6009f | 234 | if (m_altitude == 0.F) |
spiridion | 0:9a0671b6009f | 235 | return p / 100.F; |
spiridion | 0:9a0671b6009f | 236 | else |
spiridion | 0:9a0671b6009f | 237 | return p / (100.F * pow((1.F - m_altitude / 44330.0L), 5.255L)); |
chasefarmer2808 | 3:ae101ea7bd90 | 238 | |
spiridion | 0:9a0671b6009f | 239 | } |