BMP180 Pressure/Temperature Sensor library

Dependents:   frdm_mikroklimat Weather_Station WMG Sample_BMP180 ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers BMP180.cpp Source File

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 }