This is a BMP180 Library. Using "Timeout", so you do not need to use "wait".

Committer:
Gaku0606
Date:
Fri Jul 20 22:26:15 2018 +0000
Revision:
0:6953e7630b84
first edtion

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Gaku0606 0:6953e7630b84 1 /**
Gaku0606 0:6953e7630b84 2 * @file BMP180.hpp
Gaku0606 0:6953e7630b84 3 * @brief This is a Library for BMP180
Gaku0606 0:6953e7630b84 4 * @author Matsumoto Gaku
Gaku0606 0:6953e7630b84 5 * @date 2018/07/10
Gaku0606 0:6953e7630b84 6 */
Gaku0606 0:6953e7630b84 7
Gaku0606 0:6953e7630b84 8 #pragma once
Gaku0606 0:6953e7630b84 9 #include "mbed.h"
Gaku0606 0:6953e7630b84 10
Gaku0606 0:6953e7630b84 11 #define BMP180_AC1_H 0xAA
Gaku0606 0:6953e7630b84 12 #define BMP180_AC1_L 0xAB
Gaku0606 0:6953e7630b84 13 #define BMP180_AC2_H 0xAC
Gaku0606 0:6953e7630b84 14 #define BMP180_AC2_L 0xAD
Gaku0606 0:6953e7630b84 15 #define BMP180_AC3_H 0xAE
Gaku0606 0:6953e7630b84 16 #define BMP180_AC3_L 0xAF
Gaku0606 0:6953e7630b84 17 #define BMP180_AC4_H 0xB0
Gaku0606 0:6953e7630b84 18 #define BMP180_AC4_L 0xB1
Gaku0606 0:6953e7630b84 19 #define BMP180_AC5_H 0xB2
Gaku0606 0:6953e7630b84 20 #define BMP180_AC5_L 0xB3
Gaku0606 0:6953e7630b84 21 #define BMP180_AC6_H 0xB4
Gaku0606 0:6953e7630b84 22 #define BMP180_AC6_L 0xB5
Gaku0606 0:6953e7630b84 23 #define BMP180_B1_H 0xB6
Gaku0606 0:6953e7630b84 24 #define BMP180_B1_L 0xB7
Gaku0606 0:6953e7630b84 25 #define BMP180_B2_H 0xB8
Gaku0606 0:6953e7630b84 26 #define BMP180_B2_L 0xB9
Gaku0606 0:6953e7630b84 27 #define BMP180_MB_H 0xBA
Gaku0606 0:6953e7630b84 28 #define BMP180_MB_L 0xBB
Gaku0606 0:6953e7630b84 29 #define BMP180_MC_H 0xBC
Gaku0606 0:6953e7630b84 30 #define BMP180_MC_L 0xBD
Gaku0606 0:6953e7630b84 31 #define BMP180_MD_H 0xBE
Gaku0606 0:6953e7630b84 32 #define BMP180_MD_L 0xBF
Gaku0606 0:6953e7630b84 33
Gaku0606 0:6953e7630b84 34 #define BMP180_SLAVEADDR 0b11101110
Gaku0606 0:6953e7630b84 35 //#define BMP180_SLAVEADDR_READ 0xEF
Gaku0606 0:6953e7630b84 36
Gaku0606 0:6953e7630b84 37 #define BMP180_OUT_MSB 0xF6
Gaku0606 0:6953e7630b84 38 #define BMP180_OUT_LSB 0xF7
Gaku0606 0:6953e7630b84 39 #define BMP180_OUT_XLSB 0xF8
Gaku0606 0:6953e7630b84 40
Gaku0606 0:6953e7630b84 41 #define BMP180_CTRL_MEAS 0xF4
Gaku0606 0:6953e7630b84 42 #define BMP180_SOFT_REAST 0xE0
Gaku0606 0:6953e7630b84 43 #define BMP180_ID 0xD0
Gaku0606 0:6953e7630b84 44
Gaku0606 0:6953e7630b84 45
Gaku0606 0:6953e7630b84 46 /**
Gaku0606 0:6953e7630b84 47 * @brief BMP180 class
Gaku0606 0:6953e7630b84 48 */
Gaku0606 0:6953e7630b84 49 class BMP180 {
Gaku0606 0:6953e7630b84 50
Gaku0606 0:6953e7630b84 51
Gaku0606 0:6953e7630b84 52 public:
Gaku0606 0:6953e7630b84 53
Gaku0606 0:6953e7630b84 54 /**
Gaku0606 0:6953e7630b84 55 * @enum Enum
Gaku0606 0:6953e7630b84 56 * hardware accuracy modes
Gaku0606 0:6953e7630b84 57 * 測定モードの選択
Gaku0606 0:6953e7630b84 58 */
Gaku0606 0:6953e7630b84 59 enum MODE {
Gaku0606 0:6953e7630b84 60 ULTRA_LOW_POWER = 0x34,
Gaku0606 0:6953e7630b84 61 STANDARD = 0x74,
Gaku0606 0:6953e7630b84 62 HIGH_RESOLUTION = 0xB4,
Gaku0606 0:6953e7630b84 63 ULTRA_HIGH_RESOLUTION = 0xF4
Gaku0606 0:6953e7630b84 64 };
Gaku0606 0:6953e7630b84 65
Gaku0606 0:6953e7630b84 66 /**
Gaku0606 0:6953e7630b84 67 * @brief BMP180 library's constructor
Gaku0606 0:6953e7630b84 68 * @param Pointer of User I2C
Gaku0606 0:6953e7630b84 69 */
Gaku0606 0:6953e7630b84 70 BMP180(I2C &i2c) : _i2c(i2c){
Gaku0606 0:6953e7630b84 71 ctrl_meas = ULTRA_HIGH_RESOLUTION;
Gaku0606 0:6953e7630b84 72 convertion_time = 25500;
Gaku0606 0:6953e7630b84 73 oss = 3;
Gaku0606 0:6953e7630b84 74
Gaku0606 0:6953e7630b84 75 char coeff[22];
Gaku0606 0:6953e7630b84 76 readReg(BMP180_SLAVEADDR, BMP180_AC1_H, coeff, 22);
Gaku0606 0:6953e7630b84 77 AC1 = ((uint16_t)coeff[0] << 8) | (uint16_t)coeff[1];
Gaku0606 0:6953e7630b84 78 AC2 = ((uint16_t)coeff[2] << 8) | (uint16_t)coeff[3];
Gaku0606 0:6953e7630b84 79 AC3 = ((uint16_t)coeff[4] << 8) | (uint16_t)coeff[5];
Gaku0606 0:6953e7630b84 80 AC4 = ((uint16_t)coeff[6] << 8) | (uint16_t)coeff[7];
Gaku0606 0:6953e7630b84 81 AC5 = ((uint16_t)coeff[8] << 8) | (uint16_t)coeff[9];
Gaku0606 0:6953e7630b84 82 AC6 = ((uint16_t)coeff[10] << 8) | (uint16_t)coeff[11];
Gaku0606 0:6953e7630b84 83 B1 = ((uint16_t)coeff[12] << 8) | (uint16_t)coeff[13];
Gaku0606 0:6953e7630b84 84 B2 = ((uint16_t)coeff[14] << 8) | (uint16_t)coeff[15];
Gaku0606 0:6953e7630b84 85 MB = ((uint16_t)coeff[16] << 8) | (uint16_t)coeff[17];
Gaku0606 0:6953e7630b84 86 MC = ((uint16_t)coeff[18] << 8) | (uint16_t)coeff[19];
Gaku0606 0:6953e7630b84 87 MD = ((uint16_t)coeff[20] << 8) | (uint16_t)coeff[21];
Gaku0606 0:6953e7630b84 88
Gaku0606 0:6953e7630b84 89 callFlag_press = 0;
Gaku0606 0:6953e7630b84 90 callFlag_temp = 0;
Gaku0606 0:6953e7630b84 91 pressure = 0.0f;
Gaku0606 0:6953e7630b84 92 temperature = 0.0f;
Gaku0606 0:6953e7630b84 93 };
Gaku0606 0:6953e7630b84 94
Gaku0606 0:6953e7630b84 95 /**
Gaku0606 0:6953e7630b84 96 * @brief Set hardware accurary modes
Gaku0606 0:6953e7630b84 97 * @param mode : ULTRA_HIGH_RESOLUTION etc.
Gaku0606 0:6953e7630b84 98 * @return connection status. if senser's ID could not read, return false.
Gaku0606 0:6953e7630b84 99 * @sa MODE
Gaku0606 0:6953e7630b84 100 */
Gaku0606 0:6953e7630b84 101 bool begin(MODE mode) {
Gaku0606 0:6953e7630b84 102 switch (mode)
Gaku0606 0:6953e7630b84 103 {
Gaku0606 0:6953e7630b84 104 case BMP180::ULTRA_LOW_POWER:
Gaku0606 0:6953e7630b84 105 ctrl_meas = 0x34;
Gaku0606 0:6953e7630b84 106 oss = 0;
Gaku0606 0:6953e7630b84 107 convertion_time = 4500;
Gaku0606 0:6953e7630b84 108 break;
Gaku0606 0:6953e7630b84 109 case BMP180::STANDARD:
Gaku0606 0:6953e7630b84 110 ctrl_meas = 0x74;
Gaku0606 0:6953e7630b84 111 oss = 1;
Gaku0606 0:6953e7630b84 112 convertion_time = 7500;
Gaku0606 0:6953e7630b84 113 break;
Gaku0606 0:6953e7630b84 114 case BMP180::HIGH_RESOLUTION:
Gaku0606 0:6953e7630b84 115 ctrl_meas = 0xB4;
Gaku0606 0:6953e7630b84 116 oss = 2;
Gaku0606 0:6953e7630b84 117 convertion_time = 13500;
Gaku0606 0:6953e7630b84 118 break;
Gaku0606 0:6953e7630b84 119 case BMP180::ULTRA_HIGH_RESOLUTION:
Gaku0606 0:6953e7630b84 120 ctrl_meas = 0xF4;
Gaku0606 0:6953e7630b84 121 oss = 3;
Gaku0606 0:6953e7630b84 122 convertion_time = 25500;
Gaku0606 0:6953e7630b84 123 break;
Gaku0606 0:6953e7630b84 124 default:
Gaku0606 0:6953e7630b84 125 break;
Gaku0606 0:6953e7630b84 126 }
Gaku0606 0:6953e7630b84 127
Gaku0606 0:6953e7630b84 128 //センサーチェック
Gaku0606 0:6953e7630b84 129 char result = readReg(BMP180_SLAVEADDR, BMP180_ID);
Gaku0606 0:6953e7630b84 130 if (result == 0x55) {
Gaku0606 0:6953e7630b84 131 return true;
Gaku0606 0:6953e7630b84 132 }
Gaku0606 0:6953e7630b84 133 else {
Gaku0606 0:6953e7630b84 134 return false;
Gaku0606 0:6953e7630b84 135 }
Gaku0606 0:6953e7630b84 136 }
Gaku0606 0:6953e7630b84 137
Gaku0606 0:6953e7630b84 138 /**
Gaku0606 0:6953e7630b84 139 * @brief start measuring
Gaku0606 0:6953e7630b84 140 * @detail you have to read data after you excute this.
Gaku0606 0:6953e7630b84 141 */
Gaku0606 0:6953e7630b84 142 void measure() {
Gaku0606 0:6953e7630b84 143 startTemperature();
Gaku0606 0:6953e7630b84 144 }
Gaku0606 0:6953e7630b84 145
Gaku0606 0:6953e7630b84 146 /**
Gaku0606 0:6953e7630b84 147 * @brief get pressure and temperature data
Gaku0606 0:6953e7630b84 148 * @param *press float variable pointer for pressure data
Gaku0606 0:6953e7630b84 149 * @param *temp float variable pointer for temperature data
Gaku0606 0:6953e7630b84 150 */
Gaku0606 0:6953e7630b84 151 void readPressTemp(float *press, float *temp) {
Gaku0606 0:6953e7630b84 152 *press = pressure;
Gaku0606 0:6953e7630b84 153 *temp = temperature;
Gaku0606 0:6953e7630b84 154 }
Gaku0606 0:6953e7630b84 155
Gaku0606 0:6953e7630b84 156 private:
Gaku0606 0:6953e7630b84 157 void startTemperature() {
Gaku0606 0:6953e7630b84 158 //測定開始
Gaku0606 0:6953e7630b84 159 writeReg(BMP180_SLAVEADDR, BMP180_CTRL_MEAS, 0x2E);
Gaku0606 0:6953e7630b84 160 if (callFlag_temp) {
Gaku0606 0:6953e7630b84 161 callFlag_temp = 0;
Gaku0606 0:6953e7630b84 162 tempTimer.detach();
Gaku0606 0:6953e7630b84 163 }
Gaku0606 0:6953e7630b84 164 //測定終了後にデータを取得する
Gaku0606 0:6953e7630b84 165 callFlag_temp = 1;
Gaku0606 0:6953e7630b84 166 tempTimer.attach_us(this, &BMP180::readTemperature, 4500);
Gaku0606 0:6953e7630b84 167 }
Gaku0606 0:6953e7630b84 168
Gaku0606 0:6953e7630b84 169 void startPressure() {
Gaku0606 0:6953e7630b84 170 writeReg(BMP180_SLAVEADDR, BMP180_CTRL_MEAS, ctrl_meas);
Gaku0606 0:6953e7630b84 171 if (callFlag_press) {
Gaku0606 0:6953e7630b84 172 callFlag_press = 0;
Gaku0606 0:6953e7630b84 173 pressTimer.detach();
Gaku0606 0:6953e7630b84 174 }
Gaku0606 0:6953e7630b84 175 callFlag_press = 1;
Gaku0606 0:6953e7630b84 176 pressTimer.attach_us(this, &BMP180::readPressure, convertion_time);
Gaku0606 0:6953e7630b84 177
Gaku0606 0:6953e7630b84 178 }
Gaku0606 0:6953e7630b84 179
Gaku0606 0:6953e7630b84 180 void readTemperature() {
Gaku0606 0:6953e7630b84 181 callFlag_temp = 0;
Gaku0606 0:6953e7630b84 182 char buff[2];
Gaku0606 0:6953e7630b84 183 readReg(BMP180_SLAVEADDR, BMP180_OUT_MSB, buff,2);
Gaku0606 0:6953e7630b84 184 UT = (uint16_t)buff[0] << 8 | (uint16_t)buff[1];
Gaku0606 0:6953e7630b84 185
Gaku0606 0:6953e7630b84 186 startPressure();
Gaku0606 0:6953e7630b84 187 }
Gaku0606 0:6953e7630b84 188
Gaku0606 0:6953e7630b84 189 void readPressure() {
Gaku0606 0:6953e7630b84 190 char buff[3];
Gaku0606 0:6953e7630b84 191 readReg(BMP180_SLAVEADDR, BMP180_OUT_MSB, buff, 3);
Gaku0606 0:6953e7630b84 192 UP = ((uint32_t)buff[0] << 16) | ((uint32_t)buff[1] << 8) | (uint32_t)buff[2];
Gaku0606 0:6953e7630b84 193 UP = UP >> (8 - oss);
Gaku0606 0:6953e7630b84 194
Gaku0606 0:6953e7630b84 195 //値更新 update pressure and tempsrature
Gaku0606 0:6953e7630b84 196 temperature = CaluculateTrueTemperature();
Gaku0606 0:6953e7630b84 197 pressure = CaluculateTruePressure();
Gaku0606 0:6953e7630b84 198 }
Gaku0606 0:6953e7630b84 199
Gaku0606 0:6953e7630b84 200 //生の温度データを校正係数で補正する
Gaku0606 0:6953e7630b84 201 //raw temp data change to accurate data
Gaku0606 0:6953e7630b84 202 float CaluculateTrueTemperature() {
Gaku0606 0:6953e7630b84 203
Gaku0606 0:6953e7630b84 204 X1 = ((UT - AC6) * AC5) >> 15;
Gaku0606 0:6953e7630b84 205 X2 = ((long)MC << 11) / (X1 + MD);
Gaku0606 0:6953e7630b84 206 B5 = X1 + X2;
Gaku0606 0:6953e7630b84 207 T = (B5 + 8) >> 4;
Gaku0606 0:6953e7630b84 208 return T * 0.1f;
Gaku0606 0:6953e7630b84 209 }
Gaku0606 0:6953e7630b84 210
Gaku0606 0:6953e7630b84 211 //生の気圧データを校正係数で補正する
Gaku0606 0:6953e7630b84 212 //raw press data change to accurate data
Gaku0606 0:6953e7630b84 213 float CaluculateTruePressure() {
Gaku0606 0:6953e7630b84 214 B6 = B5 - 4000;
Gaku0606 0:6953e7630b84 215 X1 = (B2*((B6*B6) >> 12)) >> 11;
Gaku0606 0:6953e7630b84 216 X2 = AC2 * B6 >> 11;
Gaku0606 0:6953e7630b84 217 X3 = X1 + X2;
Gaku0606 0:6953e7630b84 218 B3 = (((AC1 * 4 + X3) << oss) + 2) >> 2;
Gaku0606 0:6953e7630b84 219 X1 = AC3 * B6 >> 13;
Gaku0606 0:6953e7630b84 220 X2 = (B1 * (B6*B6 > 12)) >> 16;
Gaku0606 0:6953e7630b84 221 X3 = ((X1 + X2) + 2) >> 2;
Gaku0606 0:6953e7630b84 222 B4 = AC4 * (unsigned long)(X3 + 32768) >> 15;
Gaku0606 0:6953e7630b84 223 B7 = ((unsigned long)UP - B3) * (50000 >> oss);
Gaku0606 0:6953e7630b84 224 if (B7 < 0x80000000) {
Gaku0606 0:6953e7630b84 225 P = (B7 << 1) / B4;
Gaku0606 0:6953e7630b84 226 }
Gaku0606 0:6953e7630b84 227 else {
Gaku0606 0:6953e7630b84 228 P = (B7 / B4) << 1;
Gaku0606 0:6953e7630b84 229 }
Gaku0606 0:6953e7630b84 230 X1 = (P >> 8) * (P >> 8);
Gaku0606 0:6953e7630b84 231 X1 = (X1 * 3038) >> 16;
Gaku0606 0:6953e7630b84 232 X2 = (-7357 * P) >> 16;
Gaku0606 0:6953e7630b84 233 P += (X1 + X2 + 3791) >> 4;
Gaku0606 0:6953e7630b84 234
Gaku0606 0:6953e7630b84 235 return P * 0.01f;//to hPa
Gaku0606 0:6953e7630b84 236 }
Gaku0606 0:6953e7630b84 237
Gaku0606 0:6953e7630b84 238 public:
Gaku0606 0:6953e7630b84 239 float pressure;
Gaku0606 0:6953e7630b84 240 float temperature;
Gaku0606 0:6953e7630b84 241
Gaku0606 0:6953e7630b84 242 private:
Gaku0606 0:6953e7630b84 243 I2C _i2c;
Gaku0606 0:6953e7630b84 244 Timeout tempTimer;
Gaku0606 0:6953e7630b84 245 Timeout pressTimer;
Gaku0606 0:6953e7630b84 246 int callFlag_temp;
Gaku0606 0:6953e7630b84 247 int callFlag_press;
Gaku0606 0:6953e7630b84 248
Gaku0606 0:6953e7630b84 249 //気圧取得時にctrl_measレジスタに設定する値
Gaku0606 0:6953e7630b84 250 char ctrl_meas;
Gaku0606 0:6953e7630b84 251 //over sampling
Gaku0606 0:6953e7630b84 252 int oss;
Gaku0606 0:6953e7630b84 253 //変換にかかる時間[us]
Gaku0606 0:6953e7630b84 254 int convertion_time;
Gaku0606 0:6953e7630b84 255 short AC1;
Gaku0606 0:6953e7630b84 256 short AC2;
Gaku0606 0:6953e7630b84 257 short AC3;
Gaku0606 0:6953e7630b84 258 unsigned short AC4;
Gaku0606 0:6953e7630b84 259 unsigned short AC5;
Gaku0606 0:6953e7630b84 260 unsigned short AC6;
Gaku0606 0:6953e7630b84 261 short B1;
Gaku0606 0:6953e7630b84 262 short B2;
Gaku0606 0:6953e7630b84 263 short MB;
Gaku0606 0:6953e7630b84 264 short MC;
Gaku0606 0:6953e7630b84 265 short MD;
Gaku0606 0:6953e7630b84 266 //ビット演算ができるようにintでなくlong
Gaku0606 0:6953e7630b84 267 long UT;
Gaku0606 0:6953e7630b84 268 long UP;
Gaku0606 0:6953e7630b84 269 long X1;
Gaku0606 0:6953e7630b84 270 long X2;
Gaku0606 0:6953e7630b84 271 long B5;
Gaku0606 0:6953e7630b84 272 long T;
Gaku0606 0:6953e7630b84 273
Gaku0606 0:6953e7630b84 274 long X3;
Gaku0606 0:6953e7630b84 275 long B3;
Gaku0606 0:6953e7630b84 276 unsigned long B4;
Gaku0606 0:6953e7630b84 277 long B6;
Gaku0606 0:6953e7630b84 278 unsigned long B7;
Gaku0606 0:6953e7630b84 279 long P;
Gaku0606 0:6953e7630b84 280
Gaku0606 0:6953e7630b84 281
Gaku0606 0:6953e7630b84 282 inline void writeReg(char addr, char data)
Gaku0606 0:6953e7630b84 283 {
Gaku0606 0:6953e7630b84 284 _i2c.write(addr, &data, 1, false);
Gaku0606 0:6953e7630b84 285 }
Gaku0606 0:6953e7630b84 286
Gaku0606 0:6953e7630b84 287 inline void writeReg(char addr, char reg, char data)
Gaku0606 0:6953e7630b84 288 {
Gaku0606 0:6953e7630b84 289 char temp[2] = { reg, data };
Gaku0606 0:6953e7630b84 290 _i2c.write(addr, temp, 2, false);
Gaku0606 0:6953e7630b84 291 }
Gaku0606 0:6953e7630b84 292
Gaku0606 0:6953e7630b84 293 inline char readReg(char addr, char reg)
Gaku0606 0:6953e7630b84 294 {
Gaku0606 0:6953e7630b84 295 char buff[1];
Gaku0606 0:6953e7630b84 296 writeReg(addr, reg);
Gaku0606 0:6953e7630b84 297 _i2c.read(addr | 1, buff, 1, true);
Gaku0606 0:6953e7630b84 298 return buff[0];
Gaku0606 0:6953e7630b84 299 }
Gaku0606 0:6953e7630b84 300
Gaku0606 0:6953e7630b84 301 inline void readReg(char addr, char start_reg, char* buff, char num)
Gaku0606 0:6953e7630b84 302 {
Gaku0606 0:6953e7630b84 303 writeReg(addr, start_reg);
Gaku0606 0:6953e7630b84 304 _i2c.read(addr | 1, buff, num, true);
Gaku0606 0:6953e7630b84 305 }
Gaku0606 0:6953e7630b84 306 };