This is a BMP180 Library. Using "Timeout", so you do not need to use "wait".
Revision 0:6953e7630b84, committed 2018-07-20
- Comitter:
- Gaku0606
- Date:
- Fri Jul 20 22:26:15 2018 +0000
- Commit message:
- first edtion
Changed in this revision
BMP180.hpp | Show annotated file Show diff for this revision Revisions of this file |
diff -r 000000000000 -r 6953e7630b84 BMP180.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/BMP180.hpp Fri Jul 20 22:26:15 2018 +0000 @@ -0,0 +1,306 @@ +/** +* @file BMP180.hpp +* @brief This is a Library for BMP180 +* @author Matsumoto Gaku +* @date 2018/07/10 +*/ + +#pragma once +#include "mbed.h" + +#define BMP180_AC1_H 0xAA +#define BMP180_AC1_L 0xAB +#define BMP180_AC2_H 0xAC +#define BMP180_AC2_L 0xAD +#define BMP180_AC3_H 0xAE +#define BMP180_AC3_L 0xAF +#define BMP180_AC4_H 0xB0 +#define BMP180_AC4_L 0xB1 +#define BMP180_AC5_H 0xB2 +#define BMP180_AC5_L 0xB3 +#define BMP180_AC6_H 0xB4 +#define BMP180_AC6_L 0xB5 +#define BMP180_B1_H 0xB6 +#define BMP180_B1_L 0xB7 +#define BMP180_B2_H 0xB8 +#define BMP180_B2_L 0xB9 +#define BMP180_MB_H 0xBA +#define BMP180_MB_L 0xBB +#define BMP180_MC_H 0xBC +#define BMP180_MC_L 0xBD +#define BMP180_MD_H 0xBE +#define BMP180_MD_L 0xBF + +#define BMP180_SLAVEADDR 0b11101110 +//#define BMP180_SLAVEADDR_READ 0xEF + +#define BMP180_OUT_MSB 0xF6 +#define BMP180_OUT_LSB 0xF7 +#define BMP180_OUT_XLSB 0xF8 + +#define BMP180_CTRL_MEAS 0xF4 +#define BMP180_SOFT_REAST 0xE0 +#define BMP180_ID 0xD0 + + +/** +* @brief BMP180 class +*/ +class BMP180 { + + +public: + + /** + * @enum Enum + * hardware accuracy modes + * 測定モードの選択 + */ + enum MODE { + ULTRA_LOW_POWER = 0x34, + STANDARD = 0x74, + HIGH_RESOLUTION = 0xB4, + ULTRA_HIGH_RESOLUTION = 0xF4 + }; + + /** + * @brief BMP180 library's constructor + * @param Pointer of User I2C + */ + BMP180(I2C &i2c) : _i2c(i2c){ + ctrl_meas = ULTRA_HIGH_RESOLUTION; + convertion_time = 25500; + oss = 3; + + char coeff[22]; + readReg(BMP180_SLAVEADDR, BMP180_AC1_H, coeff, 22); + AC1 = ((uint16_t)coeff[0] << 8) | (uint16_t)coeff[1]; + AC2 = ((uint16_t)coeff[2] << 8) | (uint16_t)coeff[3]; + AC3 = ((uint16_t)coeff[4] << 8) | (uint16_t)coeff[5]; + AC4 = ((uint16_t)coeff[6] << 8) | (uint16_t)coeff[7]; + AC5 = ((uint16_t)coeff[8] << 8) | (uint16_t)coeff[9]; + AC6 = ((uint16_t)coeff[10] << 8) | (uint16_t)coeff[11]; + B1 = ((uint16_t)coeff[12] << 8) | (uint16_t)coeff[13]; + B2 = ((uint16_t)coeff[14] << 8) | (uint16_t)coeff[15]; + MB = ((uint16_t)coeff[16] << 8) | (uint16_t)coeff[17]; + MC = ((uint16_t)coeff[18] << 8) | (uint16_t)coeff[19]; + MD = ((uint16_t)coeff[20] << 8) | (uint16_t)coeff[21]; + + callFlag_press = 0; + callFlag_temp = 0; + pressure = 0.0f; + temperature = 0.0f; + }; + + /** + * @brief Set hardware accurary modes + * @param mode : ULTRA_HIGH_RESOLUTION etc. + * @return connection status. if senser's ID could not read, return false. + * @sa MODE + */ + bool begin(MODE mode) { + switch (mode) + { + case BMP180::ULTRA_LOW_POWER: + ctrl_meas = 0x34; + oss = 0; + convertion_time = 4500; + break; + case BMP180::STANDARD: + ctrl_meas = 0x74; + oss = 1; + convertion_time = 7500; + break; + case BMP180::HIGH_RESOLUTION: + ctrl_meas = 0xB4; + oss = 2; + convertion_time = 13500; + break; + case BMP180::ULTRA_HIGH_RESOLUTION: + ctrl_meas = 0xF4; + oss = 3; + convertion_time = 25500; + break; + default: + break; + } + + //センサーチェック + char result = readReg(BMP180_SLAVEADDR, BMP180_ID); + if (result == 0x55) { + return true; + } + else { + return false; + } + } + + /** + * @brief start measuring + * @detail you have to read data after you excute this. + */ + void measure() { + startTemperature(); + } + + /** + * @brief get pressure and temperature data + * @param *press float variable pointer for pressure data + * @param *temp float variable pointer for temperature data + */ + void readPressTemp(float *press, float *temp) { + *press = pressure; + *temp = temperature; + } + +private: + void startTemperature() { + //測定開始 + writeReg(BMP180_SLAVEADDR, BMP180_CTRL_MEAS, 0x2E); + if (callFlag_temp) { + callFlag_temp = 0; + tempTimer.detach(); + } + //測定終了後にデータを取得する + callFlag_temp = 1; + tempTimer.attach_us(this, &BMP180::readTemperature, 4500); + } + + void startPressure() { + writeReg(BMP180_SLAVEADDR, BMP180_CTRL_MEAS, ctrl_meas); + if (callFlag_press) { + callFlag_press = 0; + pressTimer.detach(); + } + callFlag_press = 1; + pressTimer.attach_us(this, &BMP180::readPressure, convertion_time); + + } + + void readTemperature() { + callFlag_temp = 0; + char buff[2]; + readReg(BMP180_SLAVEADDR, BMP180_OUT_MSB, buff,2); + UT = (uint16_t)buff[0] << 8 | (uint16_t)buff[1]; + + startPressure(); + } + + void readPressure() { + char buff[3]; + readReg(BMP180_SLAVEADDR, BMP180_OUT_MSB, buff, 3); + UP = ((uint32_t)buff[0] << 16) | ((uint32_t)buff[1] << 8) | (uint32_t)buff[2]; + UP = UP >> (8 - oss); + + //値更新 update pressure and tempsrature + temperature = CaluculateTrueTemperature(); + pressure = CaluculateTruePressure(); + } + + //生の温度データを校正係数で補正する + //raw temp data change to accurate data + float CaluculateTrueTemperature() { + + X1 = ((UT - AC6) * AC5) >> 15; + X2 = ((long)MC << 11) / (X1 + MD); + B5 = X1 + X2; + T = (B5 + 8) >> 4; + return T * 0.1f; + } + + //生の気圧データを校正係数で補正する + //raw press data change to accurate data + float CaluculateTruePressure() { + B6 = B5 - 4000; + X1 = (B2*((B6*B6) >> 12)) >> 11; + X2 = AC2 * B6 >> 11; + X3 = X1 + X2; + B3 = (((AC1 * 4 + X3) << oss) + 2) >> 2; + X1 = AC3 * B6 >> 13; + X2 = (B1 * (B6*B6 > 12)) >> 16; + X3 = ((X1 + X2) + 2) >> 2; + B4 = AC4 * (unsigned long)(X3 + 32768) >> 15; + B7 = ((unsigned long)UP - B3) * (50000 >> oss); + if (B7 < 0x80000000) { + P = (B7 << 1) / B4; + } + else { + P = (B7 / B4) << 1; + } + X1 = (P >> 8) * (P >> 8); + X1 = (X1 * 3038) >> 16; + X2 = (-7357 * P) >> 16; + P += (X1 + X2 + 3791) >> 4; + + return P * 0.01f;//to hPa + } + +public: + float pressure; + float temperature; + +private: + I2C _i2c; + Timeout tempTimer; + Timeout pressTimer; + int callFlag_temp; + int callFlag_press; + + //気圧取得時にctrl_measレジスタに設定する値 + char ctrl_meas; + //over sampling + int oss; + //変換にかかる時間[us] + int convertion_time; + short AC1; + short AC2; + short AC3; + unsigned short AC4; + unsigned short AC5; + unsigned short AC6; + short B1; + short B2; + short MB; + short MC; + short MD; + //ビット演算ができるようにintでなくlong + long UT; + long UP; + long X1; + long X2; + long B5; + long T; + + long X3; + long B3; + unsigned long B4; + long B6; + unsigned long B7; + long P; + + + inline void writeReg(char addr, char data) + { + _i2c.write(addr, &data, 1, false); + } + + inline void writeReg(char addr, char reg, char data) + { + char temp[2] = { reg, data }; + _i2c.write(addr, temp, 2, false); + } + + inline char readReg(char addr, char reg) + { + char buff[1]; + writeReg(addr, reg); + _i2c.read(addr | 1, buff, 1, true); + return buff[0]; + } + + inline void readReg(char addr, char start_reg, char* buff, char num) + { + writeReg(addr, start_reg); + _i2c.read(addr | 1, buff, num, true); + } +}; \ No newline at end of file