Library to control a BMP180 sensor.
Diff: BMP180.cpp
- Revision:
- 0:373de0f4d5cd
- Child:
- 1:608e890e88e7
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/BMP180.cpp Fri Aug 26 00:19:21 2016 +0000 @@ -0,0 +1,138 @@ +/* + @file BMP180.cpp + @brief Barometric Pressure and Temperature Sensor BMP180 Breakout I2C Library +*/ + +#include "BMP180.h" + +BMP180::BMP180(I2C& i2c) : m_i2c(i2c) { + m_altitude = 0; + m_oss = STANDARD; +} + +int BMP180::initialize(float altitude, OverSamplingSetting oss) { + char data[22]; + int errors = 0; + + m_altitude = altitude; + m_oss = oss; + + // read calibration data + data[0]=0xAA; + errors = m_i2c.write(BMP180_I2C_ADDRESS, data, 1); // set the eeprom pointer position to 0xAA + errors += m_i2c.read(BMP180_I2C_ADDRESS, 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]; // Not used? + mc = data[18] << 8 | data[19]; + md = data[20] << 8 | data[21]; + + // Pre-calc + ac1 = ac1 << 2; + mc = mc << 11; + + return errors == 0; // 0 = ACK = success +} + +int BMP180::ReadData(float& pTemperature, float& pPressure) { + long t, p; + + if (!ReadRawTemperature(&t) || !ReadRawPressure(&p)) + return 0; // Error + + pTemperature = TrueTemperature(t); + pPressure = TruePressure(p); + + return 1; +} + +int BMP180::ReadRawTemperature(long* pUt) { + int errors = 0; + + // request temperature measurement + m_data[0] = 0xF4; + m_data[1] = 0x2E; + errors = m_i2c.write(BMP180_I2C_ADDRESS, m_data, 2); // write 0XF2 into reg 0XF4 + + wait_ms(5); + + // read raw temperature data + m_data[0] = 0xF6; + errors += m_i2c.write(BMP180_I2C_ADDRESS, m_data, 2); // set eeprom pointer position to 0XF6 + errors += m_i2c.read(BMP180_I2C_ADDRESS, m_data, 2); // get 16 bits at this position + + if (errors) return 0; + *pUt = m_data[0] << 8 | m_data[1]; + + return 1; +} + +int BMP180::ReadRawPressure(long* pUp) { + int errors = 0; + + // request pressure measurement + m_data[0] = 0xF4; + m_data[1] = 0x34 + (m_oss << 6); + errors = m_i2c.write(BMP180_I2C_ADDRESS, m_data, 2); // write 0x34 + (m_oss << 6) into reg 0XF4 + + switch (m_oss) { // Rounded up wait times to be safe + case ULTRA_LOW_POWER: wait_ms(5); break; + case STANDARD: wait_ms(8); break; + case HIGH_RESOLUTION: wait_ms(14); break; + case ULTRA_HIGH_RESOLUTION: wait_ms(26); break; + } + + // read raw pressure data + m_data[0] = 0xF6; + errors += m_i2c.write(BMP180_I2C_ADDRESS, m_data, 1); // set eeprom pointer position to 0XF6 + errors += m_i2c.read(BMP180_I2C_ADDRESS, m_data, 2); // get 16 bits at this position + + if (errors) return 0; + *pUp = (m_data[0] << 16 | m_data[1] << 8) >> (8 - m_oss); + + return 1; +} + +float BMP180::TrueTemperature(long ut) { + // straight out from the documentation + x1 = ((ut - ac6) * ac5) >> 15; + x2 = mc / (x1 + md); + b5 = x1 + x2; + + // convert to Celsius + return (long)((b5 + 8) >> 4) / 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; + b3 = (((ac1 + x1 + x2) << 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 + return (m_altitude == 0.F) ? p / 100.F + : p / (100.F * pow((1.F - m_altitude / 44330.0L), 5.255L)); +}