BMP180 is a digital barometric pressure sensor made by Bosch Sensortec (I2C Interface)
Dependents: LPC1114_data_logger ProjectIOT Wether_Meter LPC1114_barometer_with_data_logging
Diff: BMP180.cpp
- Revision:
- 0:9c1a7a1f0d97
- Child:
- 1:23942d7b7023
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/BMP180.cpp Sun Jun 15 03:28:26 2014 +0000 @@ -0,0 +1,210 @@ +/* + * mbed library program + * Control BMP180(Bosch) Pressure Sensor + * + * Copyright (c) 2014 Kenji Arai / JH1PJL + * http://www.page.sannet.ne.jp/kenjia/index.html + * http://mbed.org/users/kenjiArai/ + * Created: August 14th, 2013 for STM32L152 + * Changed: May 21st, 2014 mbed LPC1114 + * Revised: June 14th, 2014 + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE + * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +/* + *---------------- REFERENCE ---------------------------------------------------------------------- + * Bosch Sensortec BMP180 Datasheet : BST-BMP180-DS000-09 Revision: 2.5 Date: 5 April 2013 + */ + +#include "mbed.h" +#include "BMP180.h" + +// Barometer I2C ADDDRESS +// 7bit address = 0b1110111(0x77) -> 8bit = 0b11101110(0xee) -> 0xef(Read) or 0xee(Write) +#define BMP180ADDR 0xee // No other choice + +// Bosch barmeter ID +#define BMP180_CHIP_ID 0x55 +#define UNKNOWN_ID 0 + +// register address +#define BARO_PROM_ADDR 0xaa +#define BARO_CHIP_ID_REG 0xd0 +#define BARO_VERSION_REG 0xd1 +#define BARO_CTRL_MEAS_REG 0xf4 +#define BARO_ADC_OUT_MSB_REG 0xf6 +#define BARO_ADC_OUT_LSB_REG 0xf7 +#define BARO_SOFT_RESET_REG 0xe0 + +// Calibration coefficients address +#define B_AC1 0xaa +#define B_AC2 0xac +#define B_AC3 0xae +#define B_AC4 0xb0 +#define B_AC5 0xb2 +#define B_AC6 0xb4 +#define B_B1 0xb6 +#define B_B2 0xb8 +#define B_MB 0xba +#define B_MC 0xbc +#define B_MD 0xbe + +#define CONST_MG 3038 +#define CONST_MH 7357 +#define CONST_MI 3791 + +// Control data +#define BARO_PROM_DATA__LEN 22 +#define B_TEMP_MEASURE 0x2e // temperature measurent +#define B_PRES_MEASURE 0x34 // pressure measurement +#define B_PRES_MEASURE_OSS3 0xf4 // pressure /over sampling #3 +#define B_RESET_CMD 0xb6 // Reset chip command + +BMP180::BMP180 (PinName p_sda, PinName p_scl) : i2c(p_sda, p_scl) { + init(); +} + +BMP180::BMP180 (I2C& p_i2c) : i2c(p_i2c) { + init(); +} + +float BMP180::read_temperature() { + return temperature; +} + +float BMP180::read_pressure() { + return pressure; +} + +uint8_t BMP180::read_baro_id() { + return id_number; +} + +/* + * Pressure Nomailzation + * Reference: Bosch Sensortec BMP180 Datasheet=BST-BMP180-DS000-09 + * Revision: 2.5 Date: 5 April 2013 Page15 + * http://www.bosch-sensortec.com/homepage/products_3/environmental_sensors_1/bmp180_1/bmp180 + */ +void BMP180::normalize() { +int32_t raw_pres, raw_temp; +int32_t dt_x1 = 0, dt_x2 = 0, dt_x3, dt_b3, dt_b5 = 0, dt_b6; +uint32_t dt_b4, dt_b7, dx; +long long int d; + + // start temprerature measurment + baro_dt[0] = BARO_CTRL_MEAS_REG; + baro_dt[1] = B_TEMP_MEASURE; + i2c_write_n_bytes(BMP180_addr, baro_dt, 2); + wait(0.3); // wait for convertion +#if 0 + printf("type:0x%x\r\nac1:0x%x,ac2:0x%x,ac3:0x%x,ac4:0x%x,ac5:0x%x,ac6:0x%x\n\r", + id_number,eep_ac1,eep_ac2,eep_ac3,eep_ac4,eep_ac5,eep_ac6); + printf("b1:0x%x,b2:0x%x,mb:0x%x,mc:0x%x,md:0x%x\n\r",eep_b1,eep_b2,eep_mb,eep_mc,eep_md); +#endif + // read temp. + baro_dt[0] = BARO_ADC_OUT_MSB_REG; + i2c_write_n_bytes(BMP180_addr, baro_dt, 1); + i2c_read_n_bytes(BMP180_addr,baro_dt,2); // not 3 but 2 (June 14th/Debug) + raw_temp = baro_dt[0] << 8 | baro_dt[1]; +#if 0 + printf("temp_raw:0x%x\n\r",raw_temp); +#endif + // start pressure measurement + baro_dt[0] = BARO_CTRL_MEAS_REG; + baro_dt[1] = B_PRES_MEASURE_OSS3; + i2c_write_n_bytes(BMP180_addr, baro_dt, 2); + wait(0.3); // wait for convertion + // read pressure + baro_dt[0] = BARO_ADC_OUT_MSB_REG; + i2c_write_n_bytes(BMP180_addr, baro_dt, 1); + i2c_read_n_bytes(BMP180_addr,baro_dt,3); + raw_pres = ( baro_dt[0] << 16 | baro_dt[1] << 8 | baro_dt[2] ) >> (8 - 3 ); +#if 0 + printf("pres_raw:0x%x\n\r",raw_pres); +#endif + // Normarization + // temperature + if ( id_number == BMP180_CHIP_ID ){ + dt_x1 = ( ( raw_temp - (int32_t)eep_ac6 ) * (int32_t)eep_ac5 ) >> 15; + dt_x2 = ( (int32_t)eep_mc << 11 ) / ( dt_x1 + (int32_t)eep_md ); + dt_b5 = dt_x1 + dt_x2; + } + temperature = (float)( ( dt_b5 + 8 ) >> 4 )/10.0; // temperature in 0.1 degC + // Pressure + dt_b6 = dt_b5 - 4000; + dt_x1 = ( dt_b6 * dt_b6 ) >> 12; + dt_x1 *= eep_b2; + dt_x1 >>= 11; + dt_x2 = ( eep_ac2 * dt_b6 ); + dt_x2 >>= 11; + dt_x3 = dt_x1 + dt_x2; + dt_b3 = ( ((((long)eep_ac1) * 4 + dt_x3 ) << 3 ) + 2 ) >> 2; + dt_x1 = ( eep_ac3 * dt_b6 ) >> 13; + dt_x2 = ( eep_b1 * ( ( dt_b6 * dt_b6 ) >> 12 ) ) >> 16; + dt_x3 = ( ( dt_x1 + dt_x2 ) + 2 ) >> 2; + dt_b4 = ( eep_ac4 * (uint32_t)(dt_x3 + 32768)) >> 15; + dt_b7 = ( (uint32_t)( raw_pres - dt_b3 ) * ( 50000>> 3 ) ); + if (dt_b7 < 0x80000000){ + dx = (dt_b7 << 1) / dt_b4; + } else { + dx = (dt_b7 / dt_b4) << 1; + } + d = (long long int)dx; + d *= d; + dt_x1 = (int32_t)( d / 65536 ); + dt_x1 = ( dt_x1 * CONST_MG ) >> 16; + dt_x2 = ( CONST_MH * dx ) >> 16; + dt_x2 *= -1; + // pressure in Pa + dx += ( dt_x1 + dt_x2 + CONST_MI ) >> 4; + pressure = (float)dx / 100.0; +} + +void BMP180::init () { + BMP180_addr = BMP180ADDR; + // parameters AC1-AC6 + baro_dt[0] = BARO_PROM_ADDR; + i2c_write_n_bytes(BMP180_addr, baro_dt, 1); + i2c_read_n_bytes(BMP180_addr,baro_dt,2); + eep_ac1 = (baro_dt[0] << 8) | baro_dt[1]; + i2c_read_n_bytes(BMP180_addr,baro_dt,2); + eep_ac2 = (baro_dt[0] << 8) | baro_dt[1]; + i2c_read_n_bytes(BMP180_addr,baro_dt,2); + eep_ac3 = (baro_dt[0] << 8) | baro_dt[1]; + i2c_read_n_bytes(BMP180_addr,baro_dt,2); + eep_ac4 = (baro_dt[0] << 8) | baro_dt[1]; + i2c_read_n_bytes(BMP180_addr,baro_dt,2); + eep_ac5 = (baro_dt[0] << 8) | baro_dt[1]; + i2c_read_n_bytes(BMP180_addr,baro_dt,2); + eep_ac6 = (baro_dt[0] << 8) | baro_dt[1]; + // parameters B1,B2 + i2c_read_n_bytes(BMP180_addr,baro_dt,2); + eep_b1 = (baro_dt[0] << 8) | baro_dt[1]; + i2c_read_n_bytes(BMP180_addr,baro_dt,2); + eep_b2 = (baro_dt[0] << 8) | baro_dt[1]; + // parameters MB,MC,MD + i2c_read_n_bytes(BMP180_addr,baro_dt,2); + eep_mb = (baro_dt[0] << 8) | baro_dt[1]; + i2c_read_n_bytes(BMP180_addr,baro_dt,2); + eep_mc = (baro_dt[0] << 8) | baro_dt[1]; + i2c_read_n_bytes(BMP180_addr,baro_dt,2); + eep_md = (baro_dt[0] << 8) | baro_dt[1]; + // Read ID + baro_dt[0] = BARO_CHIP_ID_REG; + i2c_write_n_bytes(BMP180_addr, baro_dt, 1); + i2c_read_n_bytes(BMP180_addr,baro_dt,1); + id_number = baro_dt[0]; +} + +void BMP180::i2c_read_n_bytes (int addr, char* dt, int n) { + i2c.read(addr, dt, 2); +} + +void BMP180::i2c_write_n_bytes (int addr, char* dt, int n) { + i2c.write(addr, dt, 2); +}