BMP180 Pressure/Temperature Sensor library

Dependents:   GliderFuncTest1 DropTest

Fork of BMP180 by Spiridion Mbed

Committer:
chasefarmer2808
Date:
Mon Apr 24 21:34:02 2017 +0000
Revision:
3:ae101ea7bd90
Parent:
2:1dad52218be5
accurat;

Who changed what in which revision?

UserRevisionLine numberNew 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 }