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).
Revision 0:9a0671b6009f, committed 2014-03-08
- 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