Library for getting temperature and pressure values from Bosch BMP180 barometer.
Fork of BMP180 by
Diff: BMP180.cpp
- Revision:
- 0:70d1d5ec30c8
- Child:
- 2:79d0d565c3af
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/BMP180.cpp Sun Mar 08 16:11:49 2015 +0000 @@ -0,0 +1,183 @@ +/** +@file BMP180.cpp + +@brief Member functions implementations + +*/ +#include "mbed.h" +#include "BMP180.h" + +BMP180::BMP180(PinName sdaPin, PinName sclPin) +{ + i2c = new I2C(sdaPin,sclPin); // create new I2C instance and initialise + i2c->frequency(400000); // I2C Fast Mode - 400kHz + leds = new BusOut(LED4,LED3,LED2,LED1); +} + +Measurement BMP180::readValues() +{ + // algorithm for taking measurement is taken from datasheet + int UT = readUncompensatedTemperatureValue(); + int UP = readUncompensatedPressureValue(); + // once you have the uncompensated T and P, you can calculate the true T and P + // using the equations from the datasheet + int T = calcTrueTemperature(UT); + int P = calcTruePressure(UP); + + Measurement measurement; + measurement.temperature = T*0.1; // scaled by 0.1 C + measurement.pressure = P*0.01; // Put pressure in mb + + return measurement; +} + +int BMP180::readUncompensatedTemperatureValue() +{ + // from algorithm in datasheet - p15 + sendByteToRegister(0x2E,0xF4); + wait_ms(5); // 4.5 ms delay for OSS = 1 + char MSB = readByteFromRegister(0xF6); + char LSB = readByteFromRegister(0xF7); + // combine in 16-bit value + int UT = (MSB << 8) | LSB; + return UT; + +} + +int BMP180::readUncompensatedPressureValue() +{ + // from datasheet + char byte = 0x34 + (oss << 6); + sendByteToRegister(byte,0xF4); + wait_ms(8); // 7.5 ms delay for OSS = 1 + + char MSB = readByteFromRegister(0xF6); + char LSB = readByteFromRegister(0xF7); + // just do 16-bit, not 19-bit + int UP = (MSB << 16 | LSB << 8) >> (8 - oss); + return UP; +} + +int BMP180::calcTrueTemperature(int UT) +{ + // equations from data sheet + X1 = (UT - calibration.AC6) * calibration.AC5/32768; + X2 = calibration.MC * 2048 / (X1 + calibration.MD); + B5 = X1 + X2; + int T = (B5 + 8)/16; + return T; +} + +int BMP180::calcTruePressure(int UP) +{ + // equations from data sheet + B6 = B5 - 4000; + X1 = (calibration.B2 * (B6*B6/4096))/2048; + X2 = calibration.AC2*B6/2048; + X3 = X1 + X2; + B3 = (((4*calibration.AC1 + X3) << oss)+2)/4; + X1 = calibration.AC3*B6/8192; + X2 = (calibration.B1*(B6*B6/4096))/65536; + X3 = ((X1+X2)+2)/4; + B4 = calibration.AC4*(unsigned int)(X3+32768)/32768; + B7 = ((unsigned int)UP - B3)*(50000>>oss); + int P; + if (B7 < 0x80000000) + P = (B7*2)/B4; + else + P = (B7/B4)*2; + X1 = (P/256)*(P/256); + X1 = (X1*3038)/65536; + X2 = (-7357*P)/65536; + P = P + (X1+X2+3791)/16; + + return P; + +} + +// configure the barometer +void BMP180::init() +{ + i2c->frequency(400000); // set Fast Mode I2C frequency + + char data = readByteFromRegister(ID_REG); // Section 4 - datasheet + if (data != 0x55) { // if correct ID not found, hang and flash error message + error(); + } + + readCalibrationData(); + oss = 1; // standard oversampling setting + +} + +// Reads factory calibrated data +void BMP180::readCalibrationData() +{ + char eeprom[22]; + readBytesFromRegister(EEPROM_REG_ADD,22,eeprom); + // store calibration data in structure + calibration.AC1 = (int16_t) (eeprom[0] << 8) | eeprom[1]; + calibration.AC2 = (int16_t) (eeprom[2] << 8) | eeprom[3]; + calibration.AC3 = (int16_t) (eeprom[4] << 8) | eeprom[5]; + calibration.AC4 = (uint16_t) (eeprom[6] << 8) | eeprom[7]; + calibration.AC5 = (uint16_t) (eeprom[8] << 8) | eeprom[9]; + calibration.AC6 = (uint16_t) (eeprom[10] << 8) | eeprom[11]; + calibration.B1 = (int16_t) (eeprom[12] << 8) | eeprom[13]; + calibration.B2 = (int16_t) (eeprom[14] << 8) | eeprom[15]; + calibration.MB = (int16_t) (eeprom[16] << 8) | eeprom[17]; + calibration.MC = (int16_t) (eeprom[18] << 8) | eeprom[19]; + calibration.MD = (int16_t) (eeprom[20] << 8) | eeprom[21]; +} + + +// reads a byte from a specific register +char BMP180::readByteFromRegister(char reg) +{ + int nack = i2c->write(BMP180_W_ADDRESS,®,1,true); // send the register address to the slave + if (nack) + error(); // if we don't receive acknowledgement, flash error message + + char rx; + nack = i2c->read(BMP180_W_ADDRESS,&rx,1); // read a byte from the register and store in buffer + if (nack) + error(); // if we don't receive acknowledgement, flash error message + + return rx; +} + +// reads a series of bytes, starting from a specific register +void BMP180::readBytesFromRegister(char reg,int numberOfBytes,char bytes[]) +{ + int nack = i2c->write(BMP180_W_ADDRESS,®,1,true); // send the slave write address and the configuration register address + + if (nack) + error(); // if we don't receive acknowledgement, flash error message + + nack = i2c->read(BMP180_W_ADDRESS,bytes,numberOfBytes); // read bytes + if (nack) + error(); // if we don't receive acknowledgement, flash error message + +} + +// sends a byte to a specific register +void BMP180::sendByteToRegister(char byte,char reg) +{ + char data[2]; + data[0] = reg; + data[1] = byte; + // send the register address, followed by the data + int nack = i2c->write(BMP180_W_ADDRESS,data,2); + if (nack) + error(); // if we don't receive acknowledgement, flash error message + +} + +void BMP180::error() +{ + while(1) { + leds->write(15); + wait(0.1); + leds->write(0); + wait(0.1); + } +} \ No newline at end of file