demo program of BMP085 pressure sensor

Dependencies:   mbed

Committer:
newk8600
Date:
Fri Nov 09 20:05:44 2012 +0000
Revision:
6:2c0e7ee70b8b
fixed botched revisions

Who changed what in which revision?

UserRevisionLine numberNew contents of line
newk8600 6:2c0e7ee70b8b 1 /*
newk8600 6:2c0e7ee70b8b 2 * @file BMP085.cpp
newk8600 6:2c0e7ee70b8b 3 * @author Tyler Weaver
newk8600 6:2c0e7ee70b8b 4 * @author Kory Hill
newk8600 6:2c0e7ee70b8b 5 *
newk8600 6:2c0e7ee70b8b 6 * @section LICENSE
newk8600 6:2c0e7ee70b8b 7 *
newk8600 6:2c0e7ee70b8b 8 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
newk8600 6:2c0e7ee70b8b 9 * and associated documentation files (the "Software"), to deal in the Software without restriction,
newk8600 6:2c0e7ee70b8b 10 * including without limitation the rights to use, copy, modify, merge, publish, distribute,
newk8600 6:2c0e7ee70b8b 11 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
newk8600 6:2c0e7ee70b8b 12 * furnished to do so, subject to the following conditions:
newk8600 6:2c0e7ee70b8b 13 *
newk8600 6:2c0e7ee70b8b 14 * The above copyright notice and this permission notice shall be included in all copies or
newk8600 6:2c0e7ee70b8b 15 * substantial portions of the Software.
newk8600 6:2c0e7ee70b8b 16 *
newk8600 6:2c0e7ee70b8b 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
newk8600 6:2c0e7ee70b8b 18 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
newk8600 6:2c0e7ee70b8b 19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
newk8600 6:2c0e7ee70b8b 20 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
newk8600 6:2c0e7ee70b8b 21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
newk8600 6:2c0e7ee70b8b 22 *
newk8600 6:2c0e7ee70b8b 23 * @section DESCRIPTION
newk8600 6:2c0e7ee70b8b 24 *
newk8600 6:2c0e7ee70b8b 25 * BMP085 I2C Temperature/Pressure/Altitude Sensor
newk8600 6:2c0e7ee70b8b 26 *
newk8600 6:2c0e7ee70b8b 27 * Datasheet:
newk8600 6:2c0e7ee70b8b 28 *
newk8600 6:2c0e7ee70b8b 29 * http://dlnmh9ip6v2uc.cloudfront.net/datasheets/Sensors/Pressure/BST-BMP085-DS000-06.pdf
newk8600 6:2c0e7ee70b8b 30 */
newk8600 6:2c0e7ee70b8b 31
newk8600 6:2c0e7ee70b8b 32 #include "BMP085.h"
newk8600 6:2c0e7ee70b8b 33 #include <new>
newk8600 6:2c0e7ee70b8b 34
newk8600 6:2c0e7ee70b8b 35 BMP085::BMP085(PinName sda, PinName scl) : i2c_(*reinterpret_cast<I2C*>(i2cRaw))
newk8600 6:2c0e7ee70b8b 36 {
newk8600 6:2c0e7ee70b8b 37 // Placement new to avoid additional heap memory allocation.
newk8600 6:2c0e7ee70b8b 38 new(i2cRaw) I2C(sda, scl);
newk8600 6:2c0e7ee70b8b 39
newk8600 6:2c0e7ee70b8b 40 init();
newk8600 6:2c0e7ee70b8b 41 }
newk8600 6:2c0e7ee70b8b 42
newk8600 6:2c0e7ee70b8b 43 BMP085::~BMP085()
newk8600 6:2c0e7ee70b8b 44 {
newk8600 6:2c0e7ee70b8b 45 // If the I2C object is initialized in the buffer in this object, call destructor of it.
newk8600 6:2c0e7ee70b8b 46 if(&i2c_ == reinterpret_cast<I2C*>(&i2cRaw))
newk8600 6:2c0e7ee70b8b 47 reinterpret_cast<I2C*>(&i2cRaw)->~I2C();
newk8600 6:2c0e7ee70b8b 48 }
newk8600 6:2c0e7ee70b8b 49
newk8600 6:2c0e7ee70b8b 50 void BMP085::init()
newk8600 6:2c0e7ee70b8b 51 {
newk8600 6:2c0e7ee70b8b 52 get_cal_param();
newk8600 6:2c0e7ee70b8b 53 set_oss(8); // standard over sampling (2 samples)
newk8600 6:2c0e7ee70b8b 54 get_ut(); // initalize values
newk8600 6:2c0e7ee70b8b 55 get_up();
newk8600 6:2c0e7ee70b8b 56 }
newk8600 6:2c0e7ee70b8b 57
newk8600 6:2c0e7ee70b8b 58 void BMP085::get_cal_param()
newk8600 6:2c0e7ee70b8b 59 {
newk8600 6:2c0e7ee70b8b 60 // get calibration values
newk8600 6:2c0e7ee70b8b 61 AC1 = read_int16(0xAA);
newk8600 6:2c0e7ee70b8b 62 AC2 = read_int16(0xAC);
newk8600 6:2c0e7ee70b8b 63 AC3 = read_int16(0xAE);
newk8600 6:2c0e7ee70b8b 64 AC4 = read_uint16(0xB0);
newk8600 6:2c0e7ee70b8b 65 AC5 = read_uint16(0xB2);
newk8600 6:2c0e7ee70b8b 66 AC6 = read_uint16(0xB4);
newk8600 6:2c0e7ee70b8b 67 B1 = read_int16(0xB6);
newk8600 6:2c0e7ee70b8b 68 B2 = read_int16(0xB8);
newk8600 6:2c0e7ee70b8b 69 MB = read_int16(0xBA);
newk8600 6:2c0e7ee70b8b 70 MC = read_int16(0xBC);
newk8600 6:2c0e7ee70b8b 71 MD = read_int16(0xBE);
newk8600 6:2c0e7ee70b8b 72 }
newk8600 6:2c0e7ee70b8b 73
newk8600 6:2c0e7ee70b8b 74 void BMP085::display_cal_param(Serial *pc)
newk8600 6:2c0e7ee70b8b 75 {
newk8600 6:2c0e7ee70b8b 76 pc->printf("AC1 %x\r\n", AC1);
newk8600 6:2c0e7ee70b8b 77 pc->printf("AC2 %x\r\n", AC2);
newk8600 6:2c0e7ee70b8b 78 pc->printf("AC3 %x\r\n", AC3);
newk8600 6:2c0e7ee70b8b 79 pc->printf("AC4 %x\r\n", AC4);
newk8600 6:2c0e7ee70b8b 80 pc->printf("AC5 %x\r\n", AC5);
newk8600 6:2c0e7ee70b8b 81 pc->printf("AC6 %x\r\n", AC6);
newk8600 6:2c0e7ee70b8b 82 pc->printf("B1 %x\r\n", B1);
newk8600 6:2c0e7ee70b8b 83 pc->printf("B2 %x\r\n", B2);
newk8600 6:2c0e7ee70b8b 84 pc->printf("MB %x\r\n", MB);
newk8600 6:2c0e7ee70b8b 85 pc->printf("MC %x\r\n", MC);
newk8600 6:2c0e7ee70b8b 86 pc->printf("MD %x\r\n", MD);
newk8600 6:2c0e7ee70b8b 87 }
newk8600 6:2c0e7ee70b8b 88
newk8600 6:2c0e7ee70b8b 89 void BMP085::get_ut()
newk8600 6:2c0e7ee70b8b 90 {
newk8600 6:2c0e7ee70b8b 91 write_char(0xF4,0x2E);
newk8600 6:2c0e7ee70b8b 92 wait(0.045);
newk8600 6:2c0e7ee70b8b 93 char buffer[3];
newk8600 6:2c0e7ee70b8b 94 read_multiple(0xF6, buffer, 2);
newk8600 6:2c0e7ee70b8b 95
newk8600 6:2c0e7ee70b8b 96 UT = (buffer[0]<<8) | buffer[1];
newk8600 6:2c0e7ee70b8b 97 }
newk8600 6:2c0e7ee70b8b 98
newk8600 6:2c0e7ee70b8b 99 void BMP085::get_up()
newk8600 6:2c0e7ee70b8b 100 {
newk8600 6:2c0e7ee70b8b 101 // set sample setting
newk8600 6:2c0e7ee70b8b 102 write_char(0xF4, oversampling_setting_);
newk8600 6:2c0e7ee70b8b 103
newk8600 6:2c0e7ee70b8b 104 // wait
newk8600 6:2c0e7ee70b8b 105 wait(conversion_time_);
newk8600 6:2c0e7ee70b8b 106
newk8600 6:2c0e7ee70b8b 107 // read the three bits
newk8600 6:2c0e7ee70b8b 108 char buffer[3];
newk8600 6:2c0e7ee70b8b 109 read_multiple(0xF6, buffer, 3);
newk8600 6:2c0e7ee70b8b 110
newk8600 6:2c0e7ee70b8b 111 UP = ((buffer[0]<<16) | (buffer[1]<<8) | (buffer[2])) >> (8 - oss_bit_);
newk8600 6:2c0e7ee70b8b 112 }
newk8600 6:2c0e7ee70b8b 113
newk8600 6:2c0e7ee70b8b 114 void BMP085::set_oss(int oss)
newk8600 6:2c0e7ee70b8b 115 {
newk8600 6:2c0e7ee70b8b 116 switch(oss) {
newk8600 6:2c0e7ee70b8b 117 case 1: // low power
newk8600 6:2c0e7ee70b8b 118 oss_bit_ = 0;
newk8600 6:2c0e7ee70b8b 119 oversampling_setting_ = 0x34;
newk8600 6:2c0e7ee70b8b 120 conversion_time_ = 0.045;
newk8600 6:2c0e7ee70b8b 121 break;
newk8600 6:2c0e7ee70b8b 122 case 2: // standard
newk8600 6:2c0e7ee70b8b 123 oss_bit_ = 1;
newk8600 6:2c0e7ee70b8b 124 oversampling_setting_ = 0x74;
newk8600 6:2c0e7ee70b8b 125 conversion_time_ = 0.075;
newk8600 6:2c0e7ee70b8b 126 break;
newk8600 6:2c0e7ee70b8b 127 case 4: // high resolution
newk8600 6:2c0e7ee70b8b 128 oss_bit_ = 2;
newk8600 6:2c0e7ee70b8b 129 oversampling_setting_ = 0xB4;
newk8600 6:2c0e7ee70b8b 130 conversion_time_ = 0.135;
newk8600 6:2c0e7ee70b8b 131 break;
newk8600 6:2c0e7ee70b8b 132 case 8: // ultra high resolution
newk8600 6:2c0e7ee70b8b 133 oss_bit_ = 3;
newk8600 6:2c0e7ee70b8b 134 oversampling_setting_ = 0xF4;
newk8600 6:2c0e7ee70b8b 135 conversion_time_ = 0.255;
newk8600 6:2c0e7ee70b8b 136 break;
newk8600 6:2c0e7ee70b8b 137 default: // standard
newk8600 6:2c0e7ee70b8b 138 oss_bit_ = 1;
newk8600 6:2c0e7ee70b8b 139 oversampling_setting_ = 0x74;
newk8600 6:2c0e7ee70b8b 140 conversion_time_ = 0.075;
newk8600 6:2c0e7ee70b8b 141 }
newk8600 6:2c0e7ee70b8b 142 }
newk8600 6:2c0e7ee70b8b 143
newk8600 6:2c0e7ee70b8b 144 void BMP085::write_char(char address, char data)
newk8600 6:2c0e7ee70b8b 145 {
newk8600 6:2c0e7ee70b8b 146 char cmd[2];
newk8600 6:2c0e7ee70b8b 147 cmd[0] = address;
newk8600 6:2c0e7ee70b8b 148 cmd[1] = data;
newk8600 6:2c0e7ee70b8b 149 i2c_.write( I2C_ADDRESS , cmd, 2);
newk8600 6:2c0e7ee70b8b 150 }
newk8600 6:2c0e7ee70b8b 151
newk8600 6:2c0e7ee70b8b 152 int16_t BMP085::read_int16(char address)
newk8600 6:2c0e7ee70b8b 153 {
newk8600 6:2c0e7ee70b8b 154 char tx[2];
newk8600 6:2c0e7ee70b8b 155 tx[0] = address;
newk8600 6:2c0e7ee70b8b 156 i2c_.write(I2C_ADDRESS, tx, 1);
newk8600 6:2c0e7ee70b8b 157 i2c_.read(I2C_ADDRESS, tx, 2);
newk8600 6:2c0e7ee70b8b 158 int16_t value = ((tx[0] << 8) | tx[1]);
newk8600 6:2c0e7ee70b8b 159 return value;
newk8600 6:2c0e7ee70b8b 160 }
newk8600 6:2c0e7ee70b8b 161
newk8600 6:2c0e7ee70b8b 162 void BMP085::read_multiple(char address, char* buffer, int bits)
newk8600 6:2c0e7ee70b8b 163 {
newk8600 6:2c0e7ee70b8b 164 char cmd[2];
newk8600 6:2c0e7ee70b8b 165 cmd[0] = address;
newk8600 6:2c0e7ee70b8b 166 i2c_.write(I2C_ADDRESS, cmd, 1);
newk8600 6:2c0e7ee70b8b 167 i2c_.read(I2C_ADDRESS, buffer, bits);
newk8600 6:2c0e7ee70b8b 168 }
newk8600 6:2c0e7ee70b8b 169
newk8600 6:2c0e7ee70b8b 170 uint16_t BMP085::read_uint16(char address)
newk8600 6:2c0e7ee70b8b 171 {
newk8600 6:2c0e7ee70b8b 172 char tx[2];
newk8600 6:2c0e7ee70b8b 173 tx[0] = address;
newk8600 6:2c0e7ee70b8b 174 i2c_.write(I2C_ADDRESS, tx, 1);
newk8600 6:2c0e7ee70b8b 175 i2c_.read(I2C_ADDRESS, tx, 2);
newk8600 6:2c0e7ee70b8b 176 uint16_t value = ((tx[0] << 8) | tx[1]);
newk8600 6:2c0e7ee70b8b 177 return value;
newk8600 6:2c0e7ee70b8b 178 }
newk8600 6:2c0e7ee70b8b 179
newk8600 6:2c0e7ee70b8b 180 int32_t BMP085::get_temperature()
newk8600 6:2c0e7ee70b8b 181 {
newk8600 6:2c0e7ee70b8b 182 get_ut(); // uncompressed temperature
newk8600 6:2c0e7ee70b8b 183 get_up(); // uncompressed pressure
newk8600 6:2c0e7ee70b8b 184
newk8600 6:2c0e7ee70b8b 185 long x1,x2;
newk8600 6:2c0e7ee70b8b 186
newk8600 6:2c0e7ee70b8b 187 //Start temperature calculation
newk8600 6:2c0e7ee70b8b 188 x1 = ((UT - AC6) * AC5) >> 15;
newk8600 6:2c0e7ee70b8b 189 x2 = (MC << 11) / (x1 + MD);
newk8600 6:2c0e7ee70b8b 190 B5 = x1 + x2;
newk8600 6:2c0e7ee70b8b 191 temperature = ((B5 + 8) >> 4);
newk8600 6:2c0e7ee70b8b 192 return temperature;
newk8600 6:2c0e7ee70b8b 193 }
newk8600 6:2c0e7ee70b8b 194
newk8600 6:2c0e7ee70b8b 195 int32_t BMP085::get_pressure()
newk8600 6:2c0e7ee70b8b 196 {
newk8600 6:2c0e7ee70b8b 197 get_up(); // get uncompressed pressure (uncompressed temperature must be called recently)
newk8600 6:2c0e7ee70b8b 198
newk8600 6:2c0e7ee70b8b 199 B6 = B5 - 4000;
newk8600 6:2c0e7ee70b8b 200 X1 = (B2 * ((B6 * B6) >> 12)) >> 11;
newk8600 6:2c0e7ee70b8b 201 X2 = (AC2 * B6) >> 11;
newk8600 6:2c0e7ee70b8b 202 X3 = X1 + X2;
newk8600 6:2c0e7ee70b8b 203 B3 = ((((((long)(AC1) * 4) + X3) << oss_bit_) + 2) >> 2);
newk8600 6:2c0e7ee70b8b 204 X1 = (AC3 * B6) >> 13;
newk8600 6:2c0e7ee70b8b 205 X2 = (B1 * ((B6 * B6) >> 12)) >> 16;
newk8600 6:2c0e7ee70b8b 206 X3 = ((X1 + X2) + 2) >> 2;
newk8600 6:2c0e7ee70b8b 207 B4 = (AC4 * (unsigned long)(X3 + 32768)) >> 15;
newk8600 6:2c0e7ee70b8b 208 B7 = ((unsigned long)(UP - B3) * (50000 >> oss_bit_));
newk8600 6:2c0e7ee70b8b 209 if (B7 < 0x80000000)
newk8600 6:2c0e7ee70b8b 210 pressure = (B7 << 1) / B4;
newk8600 6:2c0e7ee70b8b 211 else
newk8600 6:2c0e7ee70b8b 212 pressure = (B7 / B4) << 1;
newk8600 6:2c0e7ee70b8b 213
newk8600 6:2c0e7ee70b8b 214 X1 = (pressure >> 8);
newk8600 6:2c0e7ee70b8b 215 X1 *= X1;
newk8600 6:2c0e7ee70b8b 216 X1 = (X1 * 3038) >>16;
newk8600 6:2c0e7ee70b8b 217 X2 = (-7357 * pressure) >>16;
newk8600 6:2c0e7ee70b8b 218 pressure += (X1 + X2 + 3791)>>4;
newk8600 6:2c0e7ee70b8b 219
newk8600 6:2c0e7ee70b8b 220 return pressure;
newk8600 6:2c0e7ee70b8b 221 }
newk8600 6:2c0e7ee70b8b 222
newk8600 6:2c0e7ee70b8b 223 double BMP085::get_altitude_m()
newk8600 6:2c0e7ee70b8b 224 {
newk8600 6:2c0e7ee70b8b 225 const double P0 = 1013.25; //pressure at sea level in hPa
newk8600 6:2c0e7ee70b8b 226 double pres_hpa = pressure / 100.0;
newk8600 6:2c0e7ee70b8b 227 altitude = 44330.0 * (1.0 - pow((pres_hpa/P0), 0.190295));
newk8600 6:2c0e7ee70b8b 228 return altitude;
newk8600 6:2c0e7ee70b8b 229 }
newk8600 6:2c0e7ee70b8b 230
newk8600 6:2c0e7ee70b8b 231 double BMP085::get_altitude_ft()
newk8600 6:2c0e7ee70b8b 232 {
newk8600 6:2c0e7ee70b8b 233 return get_altitude_m()*3.28084;
newk8600 6:2c0e7ee70b8b 234 }