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