BMP180 Pressure/Temperature Sensor library
Dependents: GliderFuncTest1 DropTest
Fork of BMP180 by
BMP180.cpp@0:9a0671b6009f, 2014-03-08 (annotated)
- Committer:
- spiridion
- Date:
- Sat Mar 08 21:42:40 2014 +0000
- Revision:
- 0:9a0671b6009f
- Child:
- 1:072073c79cfd
first release
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: |
spiridion | 0:9a0671b6009f | 14 | ............... |
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 | 0:9a0671b6009f | 27 | Initialize(); |
spiridion | 0:9a0671b6009f | 28 | } |
spiridion | 0:9a0671b6009f | 29 | |
spiridion | 0:9a0671b6009f | 30 | BMP180::BMP180(I2C& i2c, int address) |
spiridion | 0:9a0671b6009f | 31 | : m_i2c(i2c), m_addr(address) |
spiridion | 0:9a0671b6009f | 32 | { |
spiridion | 0:9a0671b6009f | 33 | Initialize(); |
spiridion | 0:9a0671b6009f | 34 | } |
spiridion | 0:9a0671b6009f | 35 | |
spiridion | 0:9a0671b6009f | 36 | int BMP180::Initialize(float altitude, int overSamplingSetting) |
spiridion | 0:9a0671b6009f | 37 | { |
spiridion | 0:9a0671b6009f | 38 | char data[22]; |
spiridion | 0:9a0671b6009f | 39 | int errors = 0; |
spiridion | 0:9a0671b6009f | 40 | |
spiridion | 0:9a0671b6009f | 41 | m_altitude = altitude; |
spiridion | 0:9a0671b6009f | 42 | m_oss = overSamplingSetting; |
spiridion | 0:9a0671b6009f | 43 | |
spiridion | 0:9a0671b6009f | 44 | m_temperature = UNSET_BMP180_TEMPERATURE_VALUE; |
spiridion | 0:9a0671b6009f | 45 | m_pressure = UNSET_BMP180_PRESSURE_VALUE; |
spiridion | 0:9a0671b6009f | 46 | |
spiridion | 0:9a0671b6009f | 47 | // read calibration data |
spiridion | 0:9a0671b6009f | 48 | data[0]=0xAA; |
spiridion | 0:9a0671b6009f | 49 | errors = m_i2c.write(m_addr, data, 1); // set the eeprom pointer position to 0xAA |
spiridion | 0:9a0671b6009f | 50 | errors += m_i2c.read(m_addr, data, 22); // read 11 x 16 bits at this position |
spiridion | 0:9a0671b6009f | 51 | wait_ms(10); |
spiridion | 0:9a0671b6009f | 52 | |
spiridion | 0:9a0671b6009f | 53 | // store calibration data for further calculus |
spiridion | 0:9a0671b6009f | 54 | ac1 = data[0] << 8 | data[1]; |
spiridion | 0:9a0671b6009f | 55 | ac2 = data[2] << 8 | data[3]; |
spiridion | 0:9a0671b6009f | 56 | ac3 = data[4] << 8 | data[5]; |
spiridion | 0:9a0671b6009f | 57 | ac4 = data[6] << 8 | data[7]; |
spiridion | 0:9a0671b6009f | 58 | ac5 = data[8] << 8 | data[9]; |
spiridion | 0:9a0671b6009f | 59 | ac6 = data[10] << 8 | data[11]; |
spiridion | 0:9a0671b6009f | 60 | b1 = data[12] << 8 | data[13]; |
spiridion | 0:9a0671b6009f | 61 | b2 = data[14] << 8 | data[15]; |
spiridion | 0:9a0671b6009f | 62 | mb = data[16] << 8 | data[17]; |
spiridion | 0:9a0671b6009f | 63 | mc = data[18] << 8 | data[19]; |
spiridion | 0:9a0671b6009f | 64 | md = data[20] << 8 | data[21]; |
spiridion | 0:9a0671b6009f | 65 | |
spiridion | 0:9a0671b6009f | 66 | #ifdef BMP180_TEST_FORMULA |
spiridion | 0:9a0671b6009f | 67 | ac1 = 408; |
spiridion | 0:9a0671b6009f | 68 | ac2 = -72; |
spiridion | 0:9a0671b6009f | 69 | ac3 = -14383; |
spiridion | 0:9a0671b6009f | 70 | ac4 = 32741; |
spiridion | 0:9a0671b6009f | 71 | ac5 = 32757; |
spiridion | 0:9a0671b6009f | 72 | ac6 = 23153; |
spiridion | 0:9a0671b6009f | 73 | b1 = 6190; |
spiridion | 0:9a0671b6009f | 74 | b2 = 4; |
spiridion | 0:9a0671b6009f | 75 | mb = -32768; |
spiridion | 0:9a0671b6009f | 76 | mc = -8711; |
spiridion | 0:9a0671b6009f | 77 | md = 2868; |
spiridion | 0:9a0671b6009f | 78 | m_oss = 0; |
spiridion | 0:9a0671b6009f | 79 | errors = 0; |
spiridion | 0:9a0671b6009f | 80 | #endif // #ifdef BMP180_TEST_FORMULA |
spiridion | 0:9a0671b6009f | 81 | |
spiridion | 0:9a0671b6009f | 82 | return errors? 0 : 1; |
spiridion | 0:9a0671b6009f | 83 | } |
spiridion | 0:9a0671b6009f | 84 | |
spiridion | 0:9a0671b6009f | 85 | int BMP180::ReadData(float* pTemperature, float* pPressure) |
spiridion | 0:9a0671b6009f | 86 | { |
spiridion | 0:9a0671b6009f | 87 | long t, p; |
spiridion | 0:9a0671b6009f | 88 | |
spiridion | 0:9a0671b6009f | 89 | if (!ReadRawTemperature(&t) || !ReadRawPressure(&p)) |
spiridion | 0:9a0671b6009f | 90 | { |
spiridion | 0:9a0671b6009f | 91 | m_temperature = UNSET_BMP180_TEMPERATURE_VALUE; |
spiridion | 0:9a0671b6009f | 92 | m_pressure = UNSET_BMP180_PRESSURE_VALUE; |
spiridion | 0:9a0671b6009f | 93 | return 0; |
spiridion | 0:9a0671b6009f | 94 | } |
spiridion | 0:9a0671b6009f | 95 | |
spiridion | 0:9a0671b6009f | 96 | m_temperature = TrueTemperature(t); |
spiridion | 0:9a0671b6009f | 97 | m_pressure = TruePressure(p); |
spiridion | 0:9a0671b6009f | 98 | |
spiridion | 0:9a0671b6009f | 99 | if (pPressure) |
spiridion | 0:9a0671b6009f | 100 | *pPressure = m_pressure; |
spiridion | 0:9a0671b6009f | 101 | if (pTemperature) |
spiridion | 0:9a0671b6009f | 102 | *pTemperature = m_temperature; |
spiridion | 0:9a0671b6009f | 103 | |
spiridion | 0:9a0671b6009f | 104 | return 1; |
spiridion | 0:9a0671b6009f | 105 | } |
spiridion | 0:9a0671b6009f | 106 | |
spiridion | 0:9a0671b6009f | 107 | int BMP180::ReadRawTemperature(long* pUt) |
spiridion | 0:9a0671b6009f | 108 | { |
spiridion | 0:9a0671b6009f | 109 | int errors = 0; |
spiridion | 0:9a0671b6009f | 110 | char data[2]; |
spiridion | 0:9a0671b6009f | 111 | |
spiridion | 0:9a0671b6009f | 112 | // request temperature measurement |
spiridion | 0:9a0671b6009f | 113 | data[0] = 0xF4; |
spiridion | 0:9a0671b6009f | 114 | data[1] = 0x2E; |
spiridion | 0:9a0671b6009f | 115 | errors = m_i2c.write(m_addr, data, 2); // write 0XF2 into reg 0XF4 |
spiridion | 0:9a0671b6009f | 116 | |
spiridion | 0:9a0671b6009f | 117 | wait_ms(4.5F); |
spiridion | 0:9a0671b6009f | 118 | |
spiridion | 0:9a0671b6009f | 119 | // read raw temperature data |
spiridion | 0:9a0671b6009f | 120 | data[0] = 0xF6; |
spiridion | 0:9a0671b6009f | 121 | errors += m_i2c.write(m_addr, data, 2); // set eeprom pointer position to 0XF6 |
spiridion | 0:9a0671b6009f | 122 | errors += m_i2c.read(m_addr, data, 2); // get 16 bits at this position |
spiridion | 0:9a0671b6009f | 123 | |
spiridion | 0:9a0671b6009f | 124 | #ifdef BMP180_TEST_FORMULA |
spiridion | 0:9a0671b6009f | 125 | errors = 0; |
spiridion | 0:9a0671b6009f | 126 | #endif // #ifdef BMP180_TEST_FORMULA |
spiridion | 0:9a0671b6009f | 127 | |
spiridion | 0:9a0671b6009f | 128 | if (errors) |
spiridion | 0:9a0671b6009f | 129 | return 0; |
spiridion | 0:9a0671b6009f | 130 | else |
spiridion | 0:9a0671b6009f | 131 | *pUt = data[0] << 8 | data[1]; |
spiridion | 0:9a0671b6009f | 132 | |
spiridion | 0:9a0671b6009f | 133 | #ifdef BMP180_TEST_FORMULA |
spiridion | 0:9a0671b6009f | 134 | *pUt = 27898; |
spiridion | 0:9a0671b6009f | 135 | #endif // #ifdef BMP180_TEST_FORMULA |
spiridion | 0:9a0671b6009f | 136 | |
spiridion | 0:9a0671b6009f | 137 | return 1; |
spiridion | 0:9a0671b6009f | 138 | } |
spiridion | 0:9a0671b6009f | 139 | |
spiridion | 0:9a0671b6009f | 140 | int BMP180::ReadRawPressure(long* pUp) |
spiridion | 0:9a0671b6009f | 141 | { |
spiridion | 0:9a0671b6009f | 142 | int errors = 0; |
spiridion | 0:9a0671b6009f | 143 | char data[2]; |
spiridion | 0:9a0671b6009f | 144 | |
spiridion | 0:9a0671b6009f | 145 | // request pressure measurement |
spiridion | 0:9a0671b6009f | 146 | data[0] = 0xF4; |
spiridion | 0:9a0671b6009f | 147 | data[1] = 0x34 + (m_oss << 6); |
spiridion | 0:9a0671b6009f | 148 | errors = m_i2c.write(m_addr, data, 2); // write 0x34 + (m_oss << 6) into reg 0XF4 |
spiridion | 0:9a0671b6009f | 149 | |
spiridion | 0:9a0671b6009f | 150 | switch (m_oss) |
spiridion | 0:9a0671b6009f | 151 | { |
spiridion | 0:9a0671b6009f | 152 | case BMP180_OSS_ULTRA_LOW_POWER: wait_ms(4.5); break; |
spiridion | 0:9a0671b6009f | 153 | case BMP180_OSS_NORMAL: wait_ms(7.5); break; |
spiridion | 0:9a0671b6009f | 154 | case BMP180_OSS_HIGH_RESOLUTION: wait_ms(13.5); break; |
spiridion | 0:9a0671b6009f | 155 | case BMP180_OSS_ULTRA_HIGH_RESOLUTION: wait_ms(25.5); break; |
spiridion | 0:9a0671b6009f | 156 | } |
spiridion | 0:9a0671b6009f | 157 | |
spiridion | 0:9a0671b6009f | 158 | // read raw pressure data |
spiridion | 0:9a0671b6009f | 159 | data[0] = 0xF6; |
spiridion | 0:9a0671b6009f | 160 | errors += m_i2c.write(m_addr, data, 1); // set eeprom pointer position to 0XF6 |
spiridion | 0:9a0671b6009f | 161 | errors += m_i2c.read(m_addr, data, 2); // get 16 bits at this position |
spiridion | 0:9a0671b6009f | 162 | |
spiridion | 0:9a0671b6009f | 163 | #ifdef BMP180_TEST_FORMULA |
spiridion | 0:9a0671b6009f | 164 | errors = 0; |
spiridion | 0:9a0671b6009f | 165 | #endif // #ifdef BMP180_TEST_FORMULA |
spiridion | 0:9a0671b6009f | 166 | |
spiridion | 0:9a0671b6009f | 167 | if (errors) |
spiridion | 0:9a0671b6009f | 168 | return 0; |
spiridion | 0:9a0671b6009f | 169 | else |
spiridion | 0:9a0671b6009f | 170 | *pUp = (data[0] << 16 | data[1] << 8) >> (8 - m_oss); |
spiridion | 0:9a0671b6009f | 171 | #ifdef BMP180_TEST_FORMULA |
spiridion | 0:9a0671b6009f | 172 | *pUp = 23843; |
spiridion | 0:9a0671b6009f | 173 | #endif // #ifdef BMP180_TEST_FORMULA |
spiridion | 0:9a0671b6009f | 174 | |
spiridion | 0:9a0671b6009f | 175 | return 1; |
spiridion | 0:9a0671b6009f | 176 | } |
spiridion | 0:9a0671b6009f | 177 | |
spiridion | 0:9a0671b6009f | 178 | float BMP180::TrueTemperature(long ut) |
spiridion | 0:9a0671b6009f | 179 | { |
spiridion | 0:9a0671b6009f | 180 | long t; |
spiridion | 0:9a0671b6009f | 181 | |
spiridion | 0:9a0671b6009f | 182 | // straight out from the documentation |
spiridion | 0:9a0671b6009f | 183 | x1 = ((ut - ac6) * ac5) >> 15; |
spiridion | 0:9a0671b6009f | 184 | x2 = ((long)mc << 11) / (x1 + md); |
spiridion | 0:9a0671b6009f | 185 | b5 = x1 + x2; |
spiridion | 0:9a0671b6009f | 186 | t = (b5 + 8) >> 4; |
spiridion | 0:9a0671b6009f | 187 | |
spiridion | 0:9a0671b6009f | 188 | // convert to celcius |
spiridion | 0:9a0671b6009f | 189 | return t / 10.F; |
spiridion | 0:9a0671b6009f | 190 | } |
spiridion | 0:9a0671b6009f | 191 | |
spiridion | 0:9a0671b6009f | 192 | float BMP180::TruePressure(long up) |
spiridion | 0:9a0671b6009f | 193 | { |
spiridion | 0:9a0671b6009f | 194 | long p; |
spiridion | 0:9a0671b6009f | 195 | |
spiridion | 0:9a0671b6009f | 196 | // straight out from the documentation |
spiridion | 0:9a0671b6009f | 197 | b6 = b5 - 4000; |
spiridion | 0:9a0671b6009f | 198 | x1 = (b2 * (b6 * b6 >> 12)) >> 11; |
spiridion | 0:9a0671b6009f | 199 | x2 = ac2 * b6 >> 11; |
spiridion | 0:9a0671b6009f | 200 | x3 = x1 + x2; |
spiridion | 0:9a0671b6009f | 201 | b3 = (((ac1 * 4 + x3) << m_oss) + 2) >> 2; |
spiridion | 0:9a0671b6009f | 202 | x1 = (ac3 * b6) >> 13; |
spiridion | 0:9a0671b6009f | 203 | x2 = (b1 * ((b6 * b6) >> 12)) >> 16; |
spiridion | 0:9a0671b6009f | 204 | x3 = ((x1 + x2) + 2) >> 2; |
spiridion | 0:9a0671b6009f | 205 | b4 = ac4 * (unsigned long)(x3 + 32768) >> 15; |
spiridion | 0:9a0671b6009f | 206 | b7 = ((unsigned long)up - b3)* (50000 >> m_oss); |
spiridion | 0:9a0671b6009f | 207 | if (b7 < 0x80000000) |
spiridion | 0:9a0671b6009f | 208 | p = (b7 << 1) / b4; |
spiridion | 0:9a0671b6009f | 209 | else |
spiridion | 0:9a0671b6009f | 210 | p = (b7 / b4) << 1; |
spiridion | 0:9a0671b6009f | 211 | x1 = (p >> 8) * (p >> 8); |
spiridion | 0:9a0671b6009f | 212 | x1 = (x1 * 3038) >> 16; |
spiridion | 0:9a0671b6009f | 213 | x2 = (-7357 * p) >> 16; |
spiridion | 0:9a0671b6009f | 214 | p = p + ((x1 + x2 + 3791) >> 4); |
spiridion | 0:9a0671b6009f | 215 | |
spiridion | 0:9a0671b6009f | 216 | // convert to hPa and, if altitude has been initialized, to sea level pressure |
spiridion | 0:9a0671b6009f | 217 | if (m_altitude == 0.F) |
spiridion | 0:9a0671b6009f | 218 | return p / 100.F; |
spiridion | 0:9a0671b6009f | 219 | else |
spiridion | 0:9a0671b6009f | 220 | return p / (100.F * pow((1.F - m_altitude / 44330.0L), 5.255L)); |
spiridion | 0:9a0671b6009f | 221 | } |