Added mag calibration and interrupt-based data ready
Dependencies: BLE_API mbed-src nRF51822
Diff: BMP280.h
- Revision:
- 4:8d11bfc7cac0
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/BMP280.h Thu Sep 22 01:21:24 2016 +0000 @@ -0,0 +1,199 @@ +#ifndef BMP280_H +#define BMP280_H + +//#include "mbed.h" + +// BMP280 registers +#define BMP280_TEMP_XLSB 0xFC +#define BMP280_TEMP_LSB 0xFB +#define BMP280_TEMP_MSB 0xFA +#define BMP280_PRESS_XLSB 0xF9 +#define BMP280_PRESS_LSB 0xF8 +#define BMP280_PRESS_MSB 0xF7 +#define BMP280_CONFIG 0xF5 +#define BMP280_CTRL_MEAS 0xF4 +#define BMP280_STATUS 0xF3 +#define BMP280_RESET 0xE0 +#define BMP280_ID 0xD0 // should be 0x58 +#define BMP280_CALIB00 0x88 +#define BMP280_ADDRESS 0x77<<1 + +// Set initial input parameters + +enum Posr { + P_OSR_00 = 0, // no op + P_OSR_01, + P_OSR_02, + P_OSR_04, + P_OSR_08, + P_OSR_16 +}; + +enum Tosr { + T_OSR_00 = 0, // no op + T_OSR_01, + T_OSR_02, + T_OSR_04, + T_OSR_08, + T_OSR_16 +}; + +enum IIRFilter { + full = 0, // bandwidth at full sample rate + BW0_223ODR, + BW0_092ODR, + BW0_042ODR, + BW0_021ODR // bandwidth at 0.021 x sample rate +}; + +enum Mode { + BMP280Sleep = 0, + forced, + forced2, + normal +}; + +enum SBy { + t_00_5ms = 0, + t_62_5ms, + t_125ms, + t_250ms, + t_500ms, + t_1000ms, + t_2000ms, + t_4000ms, +}; + +// Specify BMP280 configuration +uint8_t Posr = P_OSR_16, Tosr = T_OSR_02, Mode = normal, IIRFilter = BW0_042ODR, SBy = t_62_5ms; // set pressure amd temperature output data rate +// t_fine carries fine temperature as global value for BMP280 +int32_t t_fine; + +//Set up I2C, (SDA,SCL) +//I2C i2c(P0_0, P0_1); + +// BMP280 compensation parameters +uint16_t dig_T1, dig_P1; +int16_t dig_T2, dig_T3, dig_P2, dig_P3, dig_P4, dig_P5, dig_P6, dig_P7, dig_P8, dig_P9; + +class BMP280 { + + protected: + + public: + //=================================================================================================================== +//====== Set of useful function to access pressure and temperature data +//=================================================================================================================== + + + void writeByte(uint8_t address, uint8_t subAddress, uint8_t data) +{ + char data_write[2]; + data_write[0] = subAddress; + data_write[1] = data; + i2c.write(address, data_write, 2, 0); +} + + char readByte(uint8_t address, uint8_t subAddress) +{ + char data[1]; // `data` will store the register data + char data_write[1]; + data_write[0] = subAddress; + i2c.write(address, data_write, 1, 1); // no stop + i2c.read(address, data, 1, 0); + return data[0]; +} + + void readBytes(uint8_t address, uint8_t subAddress, uint8_t count, uint8_t * dest) +{ + char data[24]; + char data_write[1]; + data_write[0] = subAddress; + i2c.write(address, data_write, 1, 1); // no stop + i2c.read(address, data, count, 0); + for(int ii = 0; ii < count; ii++) { + dest[ii] = data[ii]; + } +} + + +int32_t readBMP280Temperature() +{ + uint8_t rawData[3]; // 20-bit pressure register data stored here + readBytes(BMP280_ADDRESS, BMP280_TEMP_MSB, 3, &rawData[0]); + return (int32_t) (((int32_t) rawData[0] << 16 | (int32_t) rawData[1] << 8 | rawData[2]) >> 4); +} + +int32_t readBMP280Pressure() +{ + uint8_t rawData[3]; // 20-bit pressure register data stored here + readBytes(BMP280_ADDRESS, BMP280_PRESS_MSB, 3, &rawData[0]); + return (int32_t) (((int32_t) rawData[0] << 16 | (int32_t) rawData[1] << 8 | rawData[2]) >> 4); +} + +void BMP280Init() +{ + // Configure the BMP280 + // Set T and P oversampling rates and sensor mode + writeByte(BMP280_ADDRESS, BMP280_CTRL_MEAS, Tosr << 5 | Posr << 2 | Mode); + // Set standby time interval in normal mode and bandwidth + writeByte(BMP280_ADDRESS, BMP280_CONFIG, SBy << 5 | IIRFilter << 2); + // Read and store calibration data + uint8_t calib[24]; + readBytes(BMP280_ADDRESS, BMP280_CALIB00, 24, &calib[0]); + dig_T1 = (uint16_t)(((uint16_t) calib[1] << 8) | calib[0]); + dig_T2 = ( int16_t)((( int16_t) calib[3] << 8) | calib[2]); + dig_T3 = ( int16_t)((( int16_t) calib[5] << 8) | calib[4]); + dig_P1 = (uint16_t)(((uint16_t) calib[7] << 8) | calib[6]); + dig_P2 = ( int16_t)((( int16_t) calib[9] << 8) | calib[8]); + dig_P3 = ( int16_t)((( int16_t) calib[11] << 8) | calib[10]); + dig_P4 = ( int16_t)((( int16_t) calib[13] << 8) | calib[12]); + dig_P5 = ( int16_t)((( int16_t) calib[15] << 8) | calib[14]); + dig_P6 = ( int16_t)((( int16_t) calib[17] << 8) | calib[16]); + dig_P7 = ( int16_t)((( int16_t) calib[19] << 8) | calib[18]); + dig_P8 = ( int16_t)((( int16_t) calib[21] << 8) | calib[20]); + dig_P9 = ( int16_t)((( int16_t) calib[23] << 8) | calib[22]); +} + +// Returns temperature in DegC, resolution is 0.01 DegC. Output value of +// “5123” equals 51.23 DegC. +int32_t bmp280_compensate_T(int32_t adc_T) +{ + int32_t var1, var2, T; + var1 = ((((adc_T >> 3) - ((int32_t)dig_T1 << 1))) * ((int32_t)dig_T2)) >> 11; + var2 = (((((adc_T >> 4) - ((int32_t)dig_T1)) * ((adc_T >> 4) - ((int32_t)dig_T1))) >> 12) * ((int32_t)dig_T3)) >> 14; + t_fine = var1 + var2; + T = (t_fine * 5 + 128) >> 8; + return T; +} + +// Returns pressure in Pa as unsigned 32 bit integer in Q24.8 format (24 integer bits and 8 +//fractional bits). +//Output value of “24674867” represents 24674867/256 = 96386.2 Pa = 963.862 hPa +uint32_t bmp280_compensate_P(int32_t adc_P) +{ + long long var1, var2, p; + var1 = ((long long)t_fine) - 128000; + var2 = var1 * var1 * (long long)dig_P6; + var2 = var2 + ((var1*(long long)dig_P5)<<17); + var2 = var2 + (((long long)dig_P4)<<35); + var1 = ((var1 * var1 * (long long)dig_P3)>>8) + ((var1 * (long long)dig_P2)<<12); + var1 = (((((long long)1)<<47)+var1))*((long long)dig_P1)>>33; + if(var1 == 0) + { + return 0; + // avoid exception caused by division by zero + } + p = 1048576 - adc_P; + p = (((p<<31) - var2)*3125)/var1; + var1 = (((long long)dig_P9) * (p>>13) * (p>>13)) >> 25; + var2 = (((long long)dig_P8) * p)>> 19; + p = ((p + var1 + var2) >> 8) + (((long long)dig_P7)<<4); + return (uint32_t)p; +} + + + + + }; +#endif \ No newline at end of file