BMP180 Pressure/Temperature Sensor library

Dependents:   frdm_mikroklimat Weather_Station WMG Sample_BMP180 ... more

Yet another BMP180 library!

Bosch BMP180 is a pressure and temperature sensor which can be addressed through an I2C interface.

This library is based on the Bosch documentation (/media/uploads/spiridion/bst-bmp180-ds000-09.pdf ) and has been tested on LPC1768 and FRM-KL25Z plateforms using the BMP180 Sparkfun breakout (https://www.sparkfun.com/products/11824).

Files at this revision

API Documentation at this revision

Comitter:
spiridion
Date:
Sat Mar 08 21:42:40 2014 +0000
Child:
1:072073c79cfd
Commit message:
first release

Changed in this revision

BMP180.cpp Show annotated file Show diff for this revision Revisions of this file
BMP180.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/BMP180.cpp	Sat Mar 08 21:42:40 2014 +0000
@@ -0,0 +1,221 @@
+/*
+  @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:
+                     ...............
+*/
+
+#include "BMP180.h"
+#include "mbed.h"
+
+// Uncomment to test the documentation algorithm against the documentation example 
+// Result should be 699.64 hPa and 15°C
+// #define BMP180_TEST_FORMULA 
+
+BMP180::BMP180(PinName sda, PinName scl, int address)
+   : m_i2c(sda,scl), m_addr(address)
+{
+    Initialize();
+}
+
+BMP180::BMP180(I2C& i2c, int address)
+   : m_i2c(i2c), m_addr(address)
+{
+    Initialize();
+}
+
+int  BMP180::Initialize(float altitude, int overSamplingSetting)
+{
+    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];
+
+#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;
+}
+
+int BMP180::ReadData(float* pTemperature, float* pPressure)
+{
+    long t, p;
+
+    if (!ReadRawTemperature(&t) || !ReadRawPressure(&p))
+    {
+        m_temperature = UNSET_BMP180_TEMPERATURE_VALUE;
+        m_pressure = UNSET_BMP180_PRESSURE_VALUE;  
+        return 0;
+    }
+
+    m_temperature = TrueTemperature(t);
+    m_pressure = TruePressure(p);
+
+    if (pPressure)
+        *pPressure = m_pressure;
+    if (pTemperature)
+        *pTemperature = m_temperature;
+
+    return 1;
+}
+
+int BMP180::ReadRawTemperature(long* pUt)
+{
+    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);
+
+    // 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
+
+    if (errors)
+        return 0;
+    else
+        *pUt = data[0] << 8 | data[1];
+
+#ifdef BMP180_TEST_FORMULA
+    *pUt = 27898;
+#endif // #ifdef BMP180_TEST_FORMULA
+    
+    return 1;
+}
+
+int BMP180::ReadRawPressure(long* pUp)
+{
+    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
+
+    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;
+    }
+
+    // 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
+
+    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
+
+    return 1;
+}
+
+float BMP180::TrueTemperature(long ut)
+{
+    long t;
+    
+    // straight out from the documentation
+    x1 = ((ut - ac6) * ac5) >> 15;
+    x2 = ((long)mc << 11) / (x1 + md);
+    b5 = x1 + x2;
+    t = (b5 + 8) >> 4;
+
+    // convert to celcius
+    return t / 10.F;
+}
+
+float BMP180::TruePressure(long up)
+{
+    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);
+
+    // 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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/BMP180.h	Sat Mar 08 21:42:40 2014 +0000
@@ -0,0 +1,154 @@
+/*
+  @file BMP180.h
+  
+  @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: 
+                     ...............
+*/
+
+#ifndef BMP180_H
+#define BMP180_H
+
+#include "mbed.h"
+
+///  default address is 0xEF 
+#define BMP180_I2C_ADDRESS 0xEF 
+
+// Oversampling settings
+#define BMP180_OSS_ULTRA_LOW_POWER 0        // 1 sample  and  4.5ms for conversion
+#define BMP180_OSS_NORMAL          1        // 2 samples and  7.5ms for conversion
+#define BMP180_OSS_HIGH_RESOLUTION 2        // 4 samples and 13.5ms for conversion
+#define BMP180_OSS_ULTRA_HIGH_RESOLUTION 3  // 8 samples and 25.5ms for conversion
+
+#define UNSET_BMP180_PRESSURE_VALUE 0.F
+#define UNSET_BMP180_TEMPERATURE_VALUE -273.15F // absolute zero
+
+/** BMP180 class.
+ *  Read Pressure and temperature from the BMP180 Breakout I2C sensor
+ *
+ * Example:
+ * @code
+ * #include "mbed.h"
+ * #include "BMP180.h"
+ * 
+ * #if defined(TARGET_LPC1768)
+ *     #define PIN_SDA p9
+ *     #define PIN_SCL p10
+ * #elif defined(TARGET_KL25Z) // watch out for the PTE0/PTE1 mixed up in the KL25Z doc 
+ *     #define PIN_SDA PTE0
+ *     #define PIN_SCL PTE1
+ * #endif
+ * 
+ * int main() 
+ * {    
+ *     BMP180 bmp180(PIN_SDA, PIN_SCL);
+ *     float pressure, temperature;
+ *     
+ *     bmp180.Initialize(64, BMP180_OSS_NORMAL); // 64m altitude compensation and normal oversampling
+ *     
+ *     while(1) {        
+ *         if (bmp180.ReadData(&pressure, &temperature))
+ *             printf("Pressure(hPa): %8.2f \t Temperature(C): %8.2f\n", pressure, temperature);  
+ *         wait(1);
+ *     }
+ * }
+ * @endcode
+ */
+class BMP180 
+{
+
+public:
+
+    /** Create a BMP180 instance
+     * @param sda pin 
+     * @param scl pin 
+     * @param address: I2C slave address 
+     */
+    BMP180(PinName sda, PinName scl, int address = BMP180_I2C_ADDRESS); 
+
+    /** Create a BMP180 instance
+     * @param i2c object
+     * @param address: I2C slave address 
+     */
+    BMP180(I2C& i2c, int address = BMP180_I2C_ADDRESS); 
+
+    /** Initialization: set member values and read BMP180 calibration parameters
+     * @param altitude (in meter)
+     * @param overSamplingSetting 
+     */
+    int Initialize(float altitude = 0.F, int overSamplingSetting = BMP180_OSS_NORMAL);
+
+    /** Read pressure and temperature from the BMP180.
+     * @param pressure (hPa) 
+     * @param temperature (C) 
+     * @returns
+     *   1 on success,
+     *   0 on error
+     */    
+    int ReadData(float* pTemperature = NULL, float* pPressure = NULL);
+
+    /** Get temperature from a previous measurement 
+     *  
+     * @returns
+     *   temperature (C)
+     */    
+    float GetTemperature() {return m_temperature;};
+
+     /** Get pressure from a previous measurement 
+     *  
+     * @returns
+     *   pressure (hPa)
+     */    
+   float GetPressure() {return m_pressure;};
+
+protected:
+
+    /** Perform temperature measurement
+     *  
+     * @returns
+     *   temperature (C)
+     */    
+    int ReadRawTemperature(long* pUt);
+
+    /** Perform pressure measurement 
+     *  
+     * @returns
+     *   temperature (C)
+     */    
+    int ReadRawPressure(long* pUp);
+
+    /** Calculation of the temperature from the digital output
+     */    
+    float TrueTemperature(long ut);
+
+    /** Calculation of the pressure from the digital output
+     */    
+    float TruePressure(long up);
+
+    int m_oss;
+    float m_temperature;     
+    float m_pressure;
+    float m_altitude;
+
+    I2C m_i2c;   
+    int m_addr;
+    char m_data[4];    
+
+    short ac1, ac2, ac3; 
+    unsigned short ac4, ac5, ac6;
+    short b1, b2;
+    short mb, mc, md;
+    long x1, x2, x3, b3, b5, b6;
+    unsigned long b4, b7;
+
+};
+
+#endif
\ No newline at end of file