From 001d98a5186bb6b66cbef50beacdbe0041202e9c Mon Sep 17 00:00:00 2001 From: Ladyada Date: Thu, 7 Jul 2011 16:07:06 -0400 Subject: [PATCH] Commit of working code --- BMP085.cpp | 246 +++++++++++++++++++++++++++++++++++++++++++++++++++++ BMP085.h | 55 ++++++++++++ 2 files changed, 301 insertions(+) create mode 100644 BMP085.cpp create mode 100644 BMP085.h diff --git a/BMP085.cpp b/BMP085.cpp new file mode 100644 index 0000000..1623d7f --- /dev/null +++ b/BMP085.cpp @@ -0,0 +1,246 @@ +// This is a simple but accurate BMP085 sensor library that doesn't suck +// Does high res temperature, pressure and altitude calculations based on +// the datasheet documentation +// (c) adafruit - MIT license - https://github.com/adafruit/BMP085-Library + +#include "BMP085.h" +#include + +BMP085::BMP085() { +} + + +void BMP085::begin(uint8_t mode) { + if (mode > BMP085_ULTRAHIGHRES) + mode = BMP085_ULTRAHIGHRES; + oversampling = mode; + + Wire.begin(); + + /* read calibration data */ + ac1 = read16(BMP085_CAL_AC1); + ac2 = read16(BMP085_CAL_AC2); + ac3 = read16(BMP085_CAL_AC3); + ac4 = read16(BMP085_CAL_AC4); + ac5 = read16(BMP085_CAL_AC5); + ac6 = read16(BMP085_CAL_AC6); + + b1 = read16(BMP085_CAL_B1); + b2 = read16(BMP085_CAL_B2); + + mb = read16(BMP085_CAL_MB); + mc = read16(BMP085_CAL_MC); + md = read16(BMP085_CAL_MD); +#if (BMP085_DEBUG == 1) + Serial.print("ac1 = "); Serial.println(ac1, DEC); + Serial.print("ac2 = "); Serial.println(ac2, DEC); + Serial.print("ac3 = "); Serial.println(ac3, DEC); + Serial.print("ac4 = "); Serial.println(ac4, DEC); + Serial.print("ac5 = "); Serial.println(ac5, DEC); + Serial.print("ac6 = "); Serial.println(ac6, DEC); + + Serial.print("b1 = "); Serial.println(b1, DEC); + Serial.print("b2 = "); Serial.println(b2, DEC); + + Serial.print("mb = "); Serial.println(mb, DEC); + Serial.print("mc = "); Serial.println(mc, DEC); + Serial.print("md = "); Serial.println(md, DEC); +#endif +} + +uint16_t BMP085::readRawTemperature(void) { + write8(BMP085_CONTROL, BMP085_READTEMPCMD); + _delay_ms(5); +#if BMP085_DEBUG == 1 + Serial.print("Raw temp: "); Serial.println(read16(BMP085_TEMPDATA)); +#endif + return read16(BMP085_TEMPDATA); +} + +uint32_t BMP085::readRawPressure(void) { + uint32_t raw; + + write8(BMP085_CONTROL, BMP085_READPRESSURECMD + (oversampling << 6)); + + if (oversampling == BMP085_ULTRALOWPOWER) + _delay_ms(5); + else if (oversampling == BMP085_STANDARD) + _delay_ms(8); + else if (oversampling == BMP085_HIGHRES) + _delay_ms(14); + else + _delay_ms(26); + + raw = read16(BMP085_PRESSUREDATA); + raw <<= 8; + raw |= read8(BMP085_PRESSUREDATA+2); + raw >>= (8 - oversampling); +#if BMP085_DEBUG == 1 + Serial.print("Raw pressure: "); Serial.println(raw); +#endif + return raw; +} + + +int32_t BMP085::readPressure(void) { + int32_t UT, UP, B3, B5, B6, X1, X2, X3, p; + uint32_t B4, B7; + + UT = readRawTemperature(); + UP = readRawPressure(); + +#if BMP085_DEBUG == 1 + // use datasheet numbers! + UT = 27898; + UP = 23843; + ac6 = 23153; + ac5 = 32757; + mc = -8711; + md = 2868; + b1 = 6190; + b2 = 4; + ac3 = -14383; + ac2 = -72; + ac1 = 408; + ac4 = 32741; + oversampling = 0; +#endif + + // do temperature calculations + X1 = ((UT - (int32_t)ac6) * (int32_t)ac5) >> 15; + X2 = ((int32_t)mc << 11) - (X1 + md)/2; // round up + X2 /= (X1 + md); + B5 = X1 + X2; + +#if BMP085_DEBUG == 1 + Serial.print("X1 = "); Serial.println(X1); + Serial.print("X2 = "); Serial.println(X2); + Serial.print("B5 = "); Serial.println(B5); +#endif + + // do pressure calcs + B6 = B5 - 4000; + X1 = ((int32_t)b2 * ( (B6 * B6)>>12 )) >> 11; + X2 = ((int32_t)ac2 * B6) >> 11; + X3 = X1 + X2; + B3 = ((((int32_t)ac1*4 + X3) << oversampling) + 2) / 4; + +#if BMP085_DEBUG == 1 + Serial.print("B6 = "); Serial.println(B6); + Serial.print("X1 = "); Serial.println(X1); + Serial.print("X2 = "); Serial.println(X2); + Serial.print("B3 = "); Serial.println(B3); +#endif + + X1 = ((int32_t)ac3 * B6) >> 13; + X2 = ((int32_t)b1 * ((B6 * B6) >> 12)) >> 16; + X3 = ((X1 + X2) + 2) >> 2; + B4 = ((uint32_t)ac4 * (uint32_t)(X3 + 32768)) >> 15; + B7 = ((uint32_t)UP - B3) * (uint32_t)( 50000UL >> oversampling ); + +#if BMP085_DEBUG == 1 + Serial.print("X1 = "); Serial.println(X1); + Serial.print("X2 = "); Serial.println(X2); + Serial.print("B4 = "); Serial.println(B4); + Serial.print("B7 = "); Serial.println(B7); +#endif + + if (B7 < 0x80000000) { + p = (B7 * 2) / B4; + } else { + p = (B7 * 2) / B3; + } + X1 = (p >> 8) * (p >> 8); + X1 = (X1 * 3038) >> 16; + X2 = (-7357 * p) >> 16; + +#if BMP085_DEBUG == 1 + Serial.print("p = "); Serial.println(p); + Serial.print("X1 = "); Serial.println(X1); + Serial.print("X2 = "); Serial.println(X2); +#endif + + p = p + ((X1 + X2 + (int32_t)3791)>>4); +#if BMP085_DEBUG == 1 + Serial.print("p = "); Serial.println(p); +#endif + return p; +} + + +float BMP085::readTemperature(void) { + int32_t UT, X1, X2, B5; // following ds convention + float temp; + + UT = readRawTemperature(); + +#if BMP085_DEBUG == 1 + // use datasheet numbers! + UT = 27898; + ac6 = 23153; + ac5 = 32757; + mc = -8711; + md = 2868; +#endif + + // step 1 + X1 = ((UT - (int32_t)ac6) * (int32_t)ac5) >> 15; + X2 = ((int32_t)mc << 11) / (X1 + (int32_t)md); + B5 = X1 + X2; + temp = (B5 + 8) >> 4; + temp /= 10; + + return temp; +} + +float BMP085::readAltitude(float sealevelPressure) { + float altitude; + + float pressure = readPressure(); + + altitude = 44330 * (1.0 - pow(pressure /sealevelPressure,0.1903)); + + return altitude; +} + + +/*********************************************************************/ + +uint8_t BMP085::read8(uint8_t a) { + uint8_t ret; + + Wire.beginTransmission(BMP085_I2CADDR); // start transmission to device + Wire.send(a); // sends register address to read from + Wire.endTransmission(); // end transmission + + Wire.beginTransmission(BMP085_I2CADDR); // start transmission to device + Wire.requestFrom(BMP085_I2CADDR, 1);// send data n-bytes read + ret = Wire.receive(); // receive DATA + Wire.endTransmission(); // end transmission + + return ret; +} + +uint16_t BMP085::read16(uint8_t a) { + uint16_t ret; + + Wire.beginTransmission(BMP085_I2CADDR); // start transmission to device + Wire.send(a); // sends register address to read from + Wire.endTransmission(); // end transmission + + Wire.beginTransmission(BMP085_I2CADDR); // start transmission to device + Wire.requestFrom(BMP085_I2CADDR, 2);// send data n-bytes read + ret = Wire.receive(); // receive DATA + ret <<= 8; + ret |= Wire.receive(); // receive DATA + Wire.endTransmission(); // end transmission + + return ret; +} + +void BMP085::write8(uint8_t a, uint8_t d) { + Wire.beginTransmission(BMP085_I2CADDR); // start transmission to device + Wire.send(a); // sends register address to read from + Wire.send(d); // write data + Wire.endTransmission(); // end transmission +} diff --git a/BMP085.h b/BMP085.h new file mode 100644 index 0000000..eb6f8c0 --- /dev/null +++ b/BMP085.h @@ -0,0 +1,55 @@ +// BMP085 Pressure/Temperature (Altimeter) sensor + +// MIT license + +#include +#include + +#define BMP085_DEBUG 0 + +#define BMP085_I2CADDR 0x77 + +#define BMP085_ULTRALOWPOWER 0 +#define BMP085_STANDARD 1 +#define BMP085_HIGHRES 2 +#define BMP085_ULTRAHIGHRES 3 +#define BMP085_CAL_AC1 0xAA // R Calibration data (16 bits) +#define BMP085_CAL_AC2 0xAC // R Calibration data (16 bits) +#define BMP085_CAL_AC3 0xAE // R Calibration data (16 bits) +#define BMP085_CAL_AC4 0xB0 // R Calibration data (16 bits) +#define BMP085_CAL_AC5 0xB2 // R Calibration data (16 bits) +#define BMP085_CAL_AC6 0xB4 // R Calibration data (16 bits) +#define BMP085_CAL_B1 0xB6 // R Calibration data (16 bits) +#define BMP085_CAL_B2 0xB8 // R Calibration data (16 bits) +#define BMP085_CAL_MB 0xBA // R Calibration data (16 bits) +#define BMP085_CAL_MC 0xBC // R Calibration data (16 bits) +#define BMP085_CAL_MD 0xBE // R Calibration data (16 bits) + +#define BMP085_CONTROL 0xF4 +#define BMP085_TEMPDATA 0xF6 +#define BMP085_PRESSUREDATA 0xF6 +#define BMP085_READTEMPCMD 0x2E +#define BMP085_READPRESSURECMD 0x34 + + +class BMP085 { + public: + BMP085(); + void begin(uint8_t mode = BMP085_ULTRAHIGHRES); // by default go highres + float readTemperature(void); + int32_t readPressure(void); + float readAltitude(float sealevelPressure = 101325); // std atmosphere + uint16_t readRawTemperature(void); + uint32_t readRawPressure(void); + + private: + uint8_t read8(uint8_t addr); + uint16_t read16(uint8_t addr); + void write8(uint8_t addr, uint8_t data); + + uint8_t oversampling; + + int16_t ac1, ac2, ac3, b1, b2, mb, mc, md; + uint16_t ac4, ac5, ac6; +}; +