Library to control a BMP180 sensor.
BMP180.cpp
- Committer:
- Wosser1sProductions
- Date:
- 2016-08-28
- Revision:
- 1:608e890e88e7
- Parent:
- 0:373de0f4d5cd
File content as of revision 1:608e890e88e7:
/*
@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 = (0xFFFF0000 | mc) << 11; // D1F6 << 11 == 0xFE8FB000 niet 0X68FB000
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;
b5 = x1 + (mc / (x1 + md));
// convert to Celsius
return ((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));
}
William Thenaers