BMP180 Pressure/Temperature Sensor library

Dependents:   LinkNode_TemperatureAdvertising

Fork of BMP180 by Spiridion Mbed

Revision:
2:5b3e84563dcb
Parent:
1:072073c79cfd
--- a/BMP180.cpp	Mon Mar 17 20:42:23 2014 +0000
+++ b/BMP180.cpp	Wed Mar 02 05:45:36 2016 +0000
@@ -1,226 +1,268 @@
-/*
-  @file BMP180.cpp
-
-  @brief Barometric Pressure and Temperature Sensor BMP180 Breakout I2C Library
-
-  @Author spiridion (http://mailme.spiridion.net)
-
-  Tested on LPC1768 and FRDM-KL25Z
-
-  Copyright (c) 2014 spiridion
-  Released under the MIT License (see http://mbed.org/license/mit)
-
-  Documentation regarding the BMP180 can be found here:
-  http://mbed.org/media/uploads/spiridion/bst-bmp180-ds000-09.pdf
-*/
+/*******************************************************************************
+ * Copyright (C) 2015 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
 
 #include "BMP180.h"
-#include "mbed.h"
+
+/***** Definitions *****/
+#define I2C_ADDR            (0xEE) // 1110111x
 
-// Uncomment to test the documentation algorithm against the documentation example 
-// Result should be 699.64 hPa and 15°C
-// #define BMP180_TEST_FORMULA 
+#define REG_ADDR_RESET      (0xE0)
+#define REG_ADDR_ID         (0xD0)
+#define REG_ADDR_CTRL       (0xF4)
+#define REG_ADDR_DATA       (0xF6)
+#define REG_ADDR_AC1        (0xAA)
 
-BMP180::BMP180(PinName sda, PinName scl, int address)
-   : m_i2c(sda,scl), m_addr(address)
+#define CTRL_REG_TEMP       (0x2E)
+#define CTRL_REG_PRESS_0    (0x34)
+#define CTRL_REG_PRESS_1    (0x74)
+#define CTRL_REG_PRESS_2    (0xB4)
+#define CTRL_REG_PRESS_3    (0xF4)
+
+//******************************************************************************
+BMP180::BMP180(PinName sda, PinName scl)
 {
-    m_altitude = 0;
-    m_oss = BMP180_OSS_NORMAL; 
-    m_temperature = UNSET_BMP180_TEMPERATURE_VALUE;
-    m_pressure = UNSET_BMP180_PRESSURE_VALUE;  
-}
+    i2c_ = new I2C(sda, scl);
+    i2c_owner = true;
 
-BMP180::BMP180(I2C& i2c, int address)
-   : m_i2c(i2c), m_addr(address)
-{
-    m_altitude = 0;
-    m_oss = BMP180_OSS_NORMAL; 
-    m_temperature = UNSET_BMP180_TEMPERATURE_VALUE;
-    m_pressure = UNSET_BMP180_PRESSURE_VALUE;  
+    i2c_->frequency(400000);  //400000
 }
 
-int  BMP180::Initialize(float altitude, int overSamplingSetting)
+//******************************************************************************
+BMP180::BMP180(I2C *i2c) :
+    i2c_(i2c)
 {
-    char data[22];
-    int errors = 0;
-        
-    m_altitude = altitude;
-    m_oss = overSamplingSetting; 
-    m_temperature = UNSET_BMP180_TEMPERATURE_VALUE;
-    m_pressure = UNSET_BMP180_PRESSURE_VALUE;  
-    
-    // read calibration data
-    data[0]=0xAA;
-    errors = m_i2c.write(m_addr, data, 1);  // set the eeprom pointer position to 0xAA
-    errors += m_i2c.read(m_addr, data, 22); // read 11 x 16 bits at this position 
-    wait_ms(10);
-    
-    // store calibration data for further calculus  
-    ac1 = data[0]  << 8 | data[1];
-    ac2 = data[2]  << 8 | data[3];
-    ac3 = data[4]  << 8 | data[5];
-    ac4 = data[6]  << 8 | data[7];
-    ac5 = data[8]  << 8 | data[9];
-    ac6 = data[10] << 8 | data[11];
-    b1  = data[12] << 8 | data[13];
-    b2  = data[14] << 8 | data[15];
-    mb  = data[16] << 8 | data[17];
-    mc  = data[18] << 8 | data[19];
-    md  = data[20] << 8 | data[21];
+    i2c_owner = false;
+}
 
-#ifdef BMP180_TEST_FORMULA
-    ac1 = 408;
-    ac2 = -72;
-    ac3 = -14383;
-    ac4 = 32741;
-    ac5 = 32757;
-    ac6 = 23153;
-    b1 = 6190;
-    b2 = 4;
-    mb = -32768;
-    mc = -8711;
-    md = 2868;
-    m_oss = 0;
-    errors = 0;
-#endif // #ifdef BMP180_TEST_FORMULA
-
-    return errors? 0 : 1;
+//******************************************************************************
+BMP180::~BMP180()
+{
+    if(i2c_owner) {
+        delete i2c_;
+    }
 }
 
-int BMP180::ReadData(float* pTemperature, float* pPressure)
+//******************************************************************************
+int BMP180::init(void)
 {
-    long t, p;
+    char addr;
+    char data[22];
+    int i;
 
-    if (!ReadRawTemperature(&t) || !ReadRawPressure(&p))
-    {
-        m_temperature = UNSET_BMP180_TEMPERATURE_VALUE;
-        m_pressure = UNSET_BMP180_PRESSURE_VALUE;  
-        return 0;
+    if (checkId() != 0) {
+        return -1;
+    }
+
+    addr = REG_ADDR_AC1;
+    if (i2c_->write(I2C_ADDR, &addr, 1) != 0) {
+        return -1;
+    }
+
+    if (i2c_->read(I2C_ADDR, data, 22) != 0) {
+        return -1;
     }
 
-    m_temperature = TrueTemperature(t);
-    m_pressure = TruePressure(p);
+    for (i = 0; i < 11; i++) {
+        calib.value[i] = (data[2*i] << 8) | data[(2*i)+1];
+    }
+
+    return 0;
+}
+
+//******************************************************************************
+int BMP180::reset(void)
+{
+    char data;
 
-    if (pPressure)
-        *pPressure = m_pressure;
-    if (pTemperature)
-        *pTemperature = m_temperature;
+    data = REG_ADDR_RESET;
+    if (i2c_->write(I2C_ADDR, &data, 1) != 0) {
+        return -1;
+    }
 
-    return 1;
+    data = 0xB6;
+    if (i2c_->write(I2C_ADDR, &data, 1) != 0) {
+        return -1;
+    }
+
+    return 0;
 }
 
-int BMP180::ReadRawTemperature(long* pUt)
+//******************************************************************************
+int BMP180::checkId(void)
 {
-    int errors = 0;
-    char data[2];
-    
-    // request temperature measurement
-    data[0] = 0xF4;
-    data[1] = 0x2E;
-    errors = m_i2c.write(m_addr, data, 2); // write 0XF2 into reg 0XF4
-
-    wait_ms(4.5F);
+    char addr;
+    char data;
 
-    // read raw temperature data
-    data[0] = 0xF6;
-    errors += m_i2c.write(m_addr, data, 2); // set eeprom pointer position to 0XF6
-    errors += m_i2c.read(m_addr, data, 2);  // get 16 bits at this position 
-    
-#ifdef BMP180_TEST_FORMULA
-    errors = 0;
-#endif // #ifdef BMP180_TEST_FORMULA
+    addr = REG_ADDR_ID;
+    if (i2c_->write(I2C_ADDR, &addr, 1) != 0) {
+        return -1;
+    }
 
-    if (errors)
-        return 0;
-    else
-        *pUt = data[0] << 8 | data[1];
+    if (i2c_->read(I2C_ADDR, &data, 1) != 0) {
+        return -1;
+    }
 
-#ifdef BMP180_TEST_FORMULA
-    *pUt = 27898;
-#endif // #ifdef BMP180_TEST_FORMULA
-    
-    return 1;
+    if (data != 0x55) {
+        return -1;
+    }
+
+    return 0;
 }
 
-int BMP180::ReadRawPressure(long* pUp)
+//******************************************************************************
+int BMP180::startPressure(BMP180::oversampling_t oss)
 {
-    int errors = 0;
     char data[2];
-    
-    // request pressure measurement
-    data[0] = 0xF4;
-    data[1] = 0x34 + (m_oss << 6);
-    errors = m_i2c.write(m_addr, data, 2); // write 0x34 + (m_oss << 6) into reg 0XF4
+
+    data[0] = REG_ADDR_CTRL;
+    data[1] = CTRL_REG_PRESS_0 | ((oss & 0x3) << 6);
+    oss_ = oss;
+
+    if (i2c_->write(I2C_ADDR, data, 2) != 0) {
+        return -1;
+    }
+
+    return 0;
+}
 
-    switch (m_oss)
-    {
-        case BMP180_OSS_ULTRA_LOW_POWER:        wait_ms(4.5); break;
-        case BMP180_OSS_NORMAL:                 wait_ms(7.5); break;
-        case BMP180_OSS_HIGH_RESOLUTION:        wait_ms(13.5); break;
-        case BMP180_OSS_ULTRA_HIGH_RESOLUTION:  wait_ms(25.5); break;
+//******************************************************************************
+int BMP180::getPressure(int *pressure)
+{
+    char addr, byte[3];
+    uint32_t up;
+    int32_t b6, x1, x2, x3, b3, p;
+    uint32_t b4, b7;
+
+    addr = REG_ADDR_DATA;
+    if (i2c_->write(I2C_ADDR, &addr, 1) != 0) {
+        return -1;
+    }
+
+    if (i2c_->read(I2C_ADDR, byte, 3) != 0) {
+        return -1;
     }
 
-    // read raw pressure data
-    data[0] = 0xF6;
-    errors += m_i2c.write(m_addr, data, 1); // set eeprom pointer position to 0XF6
-    errors += m_i2c.read(m_addr, data, 2);  // get 16 bits at this position     
-    
-#ifdef BMP180_TEST_FORMULA
-    errors = 0;
-#endif // #ifdef BMP180_TEST_FORMULA
+    up = ((byte[0] << 16) | (byte[1] << 8) | byte[2]) >> (8 - oss_);
+
+    b6 = b5 - 4000;
+    x1 = (b6 * b6) >> 12;
+    x1 *= calib.b2;
+    x1 >>= 11;
+    x2 = calib.ac2 * b6;
+    x2 >>= 11;
+    x3 = x1 + x2;
+    b3 = (((((int32_t)calib.ac1) * 4 + x3) << oss_) + 2);
+    b3 >>= 2;
 
-    if (errors)
-        return 0;
-    else
-        *pUp = (data[0] << 16 | data[1] << 8) >> (8 - m_oss);
-#ifdef BMP180_TEST_FORMULA
-        *pUp = 23843;
-#endif // #ifdef BMP180_TEST_FORMULA
+    x1 = (calib.ac3 * b6) >> 13;
+    x2 = (calib.b1 * ((b6 * b6) >> 12)) >> 16;
+    x3 = (x1 + x2 + 2) >> 2;
+    b4 = (calib.ac4 * (uint32_t)(x3 + 32768)) >> 15;
+    b7 = ((uint32_t)up - b3) * (50000 >> oss_);
+    p = ((b7 < 0x80000000) ? ((b7 << 1) / b4) : ((b7 / b4) * 2));
+    x1 = p >> 8;
+    x1 *= x1;
+    x1 = (x1 * 3038) >> 16;
+    x2 = (-7357 * p) >> 16;
+    p += (x1 + x2 + 3791) >> 4;
+
+    *pressure = p;
 
-    return 1;
+    return 0;
+}
+
+//******************************************************************************
+int BMP180::startTemperature(void)
+{
+    char data[2] = { REG_ADDR_CTRL, CTRL_REG_TEMP };
+
+    if (i2c_->write(I2C_ADDR, data, 2) != 0) {
+        return -1;
+    }
+
+    return 0;
 }
 
-float BMP180::TrueTemperature(long ut)
+//******************************************************************************
+int BMP180::getTemperature(float *tempC)
 {
-    long t;
-    
-    // straight out from the documentation
-    x1 = ((ut - ac6) * ac5) >> 15;
-    x2 = ((long)mc << 11) / (x1 + md);
+    char addr, byte[2];
+    uint16_t ut;
+    int32_t x1, x2;
+
+    addr = REG_ADDR_DATA;
+    if (i2c_->write(I2C_ADDR, &addr, 1) != 0) {
+        return -1;
+    }
+
+    if (i2c_->read(I2C_ADDR, byte, 2) != 0) {
+        return -1;
+    }
+
+    ut = (byte[0] << 8) | byte[1];
+
+    x1 = ((ut - calib.ac6) * calib.ac5) >> 15;
+    x2 = (calib.mc << 11) / (x1 + calib.md);
     b5 = x1 + x2;
-    t = (b5 + 8) >> 4;
 
-    // convert to celcius
-    return t / 10.F;
+    *tempC = (float)(b5 + 8) / 160;
+
+    return 0;
 }
 
-float BMP180::TruePressure(long up)
+//******************************************************************************
+int BMP180::getTemperature(int16_t *tempCx10)
 {
-    long p;
-    
-    // straight out from the documentation
-    b6 = b5 - 4000;
-    x1 = (b2 * (b6 * b6 >> 12)) >> 11;
-    x2 = ac2 * b6 >> 11;
-    x3 = x1 + x2;
-    b3 = (((ac1 * 4 + x3) << m_oss) + 2) >> 2;
-    x1 = (ac3 * b6) >> 13;
-    x2 = (b1 * ((b6 * b6) >> 12)) >> 16;
-    x3 = ((x1 + x2) + 2) >> 2;
-    b4 = ac4 * (unsigned long)(x3 + 32768) >> 15;
-    b7 = ((unsigned long)up - b3)* (50000 >> m_oss);
-    if (b7 < 0x80000000)
-        p = (b7 << 1) / b4;
-    else
-        p = (b7 / b4) << 1;
-    x1 = (p >> 8) * (p >> 8);
-    x1 = (x1 * 3038) >> 16;
-    x2 = (-7357 * p) >> 16;
-    p = p + ((x1 + x2 + 3791) >> 4);
+    char addr, byte[2];
+    uint16_t ut;
+    int32_t x1, x2;
+
+    addr = REG_ADDR_DATA;
+    if (i2c_->write(I2C_ADDR, &addr, 1) != 0) {
+        return -1;
+    }
 
-    // convert to hPa and, if altitude has been initialized, to sea level pressure  
-    if (m_altitude == 0.F)
-        return p / 100.F;
-    else
-        return  p / (100.F * pow((1.F - m_altitude / 44330.0L), 5.255L)); 
-}
\ No newline at end of file
+    if (i2c_->read(I2C_ADDR, byte, 2) != 0) {
+        return -1;
+    }
+
+    ut = (byte[0] << 8) | byte[1];
+
+    x1 = ((ut - calib.ac6) * calib.ac5) >> 15;
+    x2 = (calib.mc << 11) / (x1 + calib.md);
+    b5 = x1 + x2;
+
+    *tempCx10 = (b5 + 8) >> 4;
+
+    return 0;
+}