William Thenaers / BMP180
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers BMP180.cpp Source File

BMP180.cpp

00001 /*
00002   @file BMP180.cpp
00003   @brief Barometric Pressure and Temperature Sensor BMP180 Breakout I2C Library
00004 */
00005 
00006 #include "BMP180.h"
00007 
00008 BMP180::BMP180(I2C& i2c) : m_i2c(i2c) {
00009     m_altitude      = 0;
00010     m_oss           = STANDARD;
00011 }
00012 
00013 int BMP180::initialize(float altitude, OverSamplingSetting oss) {
00014     char data[22];
00015     int errors = 0;
00016 
00017     m_altitude      = altitude;
00018     m_oss           = oss;
00019 
00020     // read calibration data
00021     data[0]=0xAA;
00022     errors = m_i2c.write(BMP180_I2C_ADDRESS, data, 1);  // set the eeprom pointer position to 0xAA
00023     errors += m_i2c.read(BMP180_I2C_ADDRESS, data, 22); // read 11 x 16 bits at this position
00024     wait_ms(10);
00025 
00026     // store calibration data for further calculus
00027     ac1 = data[0]  << 8 | data[1];
00028     ac2 = data[2]  << 8 | data[3];
00029     ac3 = data[4]  << 8 | data[5];
00030     ac4 = data[6]  << 8 | data[7];
00031     ac5 = data[8]  << 8 | data[9];
00032     ac6 = data[10] << 8 | data[11];
00033     b1  = data[12] << 8 | data[13];
00034     b2  = data[14] << 8 | data[15];
00035     //mb  = data[16] << 8 | data[17];   // Not used?
00036     mc  = data[18] << 8 | data[19];
00037     md  = data[20] << 8 | data[21];
00038 
00039     // Pre-calc
00040     ac1 = ac1 << 2;
00041     mc  = (0xFFFF0000 | mc) << 11; // D1F6 << 11 == 0xFE8FB000 niet 0X68FB000
00042 
00043     return errors == 0; // 0 = ACK = success
00044 }
00045 
00046 int BMP180::readData(float& pTemperature, float& pPressure) {
00047     long t, p;
00048 
00049     if (!ReadRawTemperature(&t) || !ReadRawPressure(&p))
00050         return 0;   // Error
00051 
00052     pTemperature    = TrueTemperature(t);
00053     pPressure       = TruePressure(p);
00054 
00055     return 1;
00056 }
00057 
00058 int BMP180::ReadRawTemperature(long* pUt) {
00059     int errors = 0;
00060 
00061     // request temperature measurement
00062     m_data[0] = 0xF4;
00063     m_data[1] = 0x2E;
00064     errors = m_i2c.write(BMP180_I2C_ADDRESS, m_data, 2); // write 0XF2 into reg 0XF4
00065 
00066     wait_ms(5);
00067 
00068     // read raw temperature data
00069     m_data[0] = 0xF6;
00070     errors += m_i2c.write(BMP180_I2C_ADDRESS, m_data, 2); // set eeprom pointer position to 0XF6
00071     errors += m_i2c.read(BMP180_I2C_ADDRESS, m_data, 2);  // get 16 bits at this position
00072 
00073     if (errors) return 0;
00074     *pUt = m_data[0] << 8 | m_data[1];
00075 
00076     return 1;
00077 }
00078 
00079 int BMP180::ReadRawPressure(long* pUp) {
00080     int errors = 0;
00081 
00082     // request pressure measurement
00083     m_data[0] = 0xF4;
00084     m_data[1] = 0x34 + (m_oss << 6);
00085     errors = m_i2c.write(BMP180_I2C_ADDRESS, m_data, 2); // write 0x34 + (m_oss << 6) into reg 0XF4
00086 
00087     switch (m_oss) {    // Rounded up wait times to be safe
00088         case ULTRA_LOW_POWER:        wait_ms(5); break;
00089         case STANDARD:               wait_ms(8); break;
00090         case HIGH_RESOLUTION:        wait_ms(14); break;
00091         case ULTRA_HIGH_RESOLUTION:  wait_ms(26); break;
00092     }
00093 
00094     // read raw pressure data
00095     m_data[0] = 0xF6;
00096     errors += m_i2c.write(BMP180_I2C_ADDRESS, m_data, 1); // set eeprom pointer position to 0XF6
00097     errors += m_i2c.read(BMP180_I2C_ADDRESS, m_data, 2);  // get 16 bits at this position
00098 
00099     if (errors) return 0;
00100     *pUp = (m_data[0] << 16 | m_data[1] << 8) >> (8 - m_oss);
00101 
00102     return 1;
00103 }
00104 
00105 float BMP180::TrueTemperature(long ut) {
00106     // straight out from the documentation
00107 
00108     x1 = ((ut - ac6) * ac5) >> 15;
00109     b5 = x1 + (mc / (x1 + md));
00110 
00111     // convert to Celsius
00112     return ((b5 + 8) >> 4) / 10.F;
00113 }
00114 
00115 float BMP180::TruePressure(long up) {
00116     long p;
00117 
00118     // straight out from the documentation
00119     b6 = b5 - 4000;
00120     x1 = (b2 * (b6 * b6 >> 12)) >> 11;
00121     x2 = ac2 * b6 >> 11;
00122     b3 = (((ac1 + x1 + x2) << m_oss) + 2) >> 2;
00123     x1 = (ac3 * b6) >> 13;
00124     x2 = (b1 * ((b6 * b6) >> 12)) >> 16;
00125     x3 = (x1 + x2 + 2) >> 2;
00126     b4 = ac4 * (unsigned long)(x3 + 32768) >> 15;
00127     b7 = ((unsigned long)up - b3)* (50000 >> m_oss);
00128     if (b7 < 0x80000000) p = (b7 << 1) / b4;
00129     else                 p = (b7 / b4) << 1;
00130     x1 = (p >> 8) * (p >> 8);
00131     x1 = (x1 * 3038) >> 16;
00132     x2 = (-7357 * p) >> 16;
00133     p = p + ((x1 + x2 + 3791) >> 4);
00134 
00135     // convert to hPa and, if altitude has been initialized, to sea level pressure
00136     return (m_altitude == 0.F) ? p / 100.F
00137                                : p / (100.F * pow((1.F - m_altitude / 44330.0L), 5.255L));
00138 }