mmmm
Fork of BMP085_lib by
BMP085.cpp@6:2c0e7ee70b8b, 2012-11-09 (annotated)
- Committer:
- newk8600
- Date:
- Fri Nov 09 20:05:44 2012 +0000
- Revision:
- 6:2c0e7ee70b8b
- Child:
- 7:2f1b74312474
fixed botched revisions
Who changed what in which revision?
User | Revision | Line number | New 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 | } |