diff --git a/Sensors.cpp b/Sensors.cpp index 88ea67a2..04dbaef3 100644 --- a/Sensors.cpp +++ b/Sensors.cpp @@ -471,6 +471,155 @@ uint8_t Baro_update() { // first UT conversion is started in i } #endif +// ************************************************************************************************************ +// I2C Barometer BOSCH BMP280 +// ************************************************************************************************************ +// I2C adress: 0x76 or 0x77 !!!Please make sure you set the correct address (BMP280_ADDR) +// ************************************************************************************************************ + +#if defined(BMP280) + +#define BMP280_ADDR 0x76 +#define i2c_read(ack) (ack) ? i2c_readAck() : i2c_readNak(); + +#define BMP280_CAL_REG_FIRST 0x88 +#define BMP280_CAL_REG_LAST 0xA1 +#define BMP280_CAL_DATA_SIZE (BMP280_CAL_REG_LAST+1 - BMP280_CAL_REG_FIRST) + +#define BMP280_STATUS_REG 0xF3 +#define BMP280_CONTROL_REG 0xF4 +#define BMP280_CONFIG_REG 0xF5 + +#define BMP280_PRES_REG 0xF7 +#define BMP280_TEMP_REG 0xFA +#define BMP280_RAWDATA_BYTES 6 // 3 bytes pressure, 3 bytes temperature + +int64_t p; //temp variable for calculating pressure +uint32_t deadline; + +static union _bmp280_cal_union { + uint8_t bytes[BMP280_CAL_DATA_SIZE]; + struct { + uint16_t dig_t1; + int16_t dig_t2; + int16_t dig_t3; + uint16_t dig_p1; + int16_t dig_p2; + int16_t dig_p3; + int16_t dig_p4; + int16_t dig_p5; + int16_t dig_p6; + int16_t dig_p7; + int16_t dig_p8; + int16_t dig_p9; + }; +} bmp280_cal; + +/* + * read calibration registers + */ +static void bmp280_getcalibration(void) +{ + memset(bmp280_cal.bytes, 0, sizeof(bmp280_cal)); + + i2c_read_reg_to_buf(BMP280_ADDR, + BMP280_CAL_REG_FIRST, + bmp280_cal.bytes, + BMP280_CAL_DATA_SIZE + ); +} + +void bmp280_set_ctrl(uint8_t osrs_t, uint8_t osrs_p, uint8_t mode) +{ + i2c_writeReg(BMP280_ADDR, BMP280_CONTROL_REG, + ((osrs_t & 0x7) << 5) | ((osrs_p & 0x7) << 2) | (mode & 0x3)); +} + +void bmp280_set_config(uint8_t t_sb, uint8_t filter, uint8_t spi3w_en) +{ + i2c_writeReg(BMP280_ADDR, BMP280_CONFIG_REG, + ((t_sb & 0x7) << 5) | ((filter & 0x7) << 2) | (spi3w_en & 1)); +} + +#define bmp280_24bit_reg(b1, b2, b3) ( \ + ((int32_t)(b1) << 16) \ + | ((int32_t)(b2) << 8) \ + | ((int32_t)(b3) ) \ +) + +/* Measures and calculates pressure and temperature + * + * This function updates global variables baroPressure and baroTemperature + * + * baroTemperature unit is 0.01 deg C + * baroPressure unit is Pa + * + */ + +void bmp280_measure(void) +{ + uint8_t data[BMP280_RAWDATA_BYTES]; + int32_t temp_raw, pres_raw, t_fine; + int64_t var1, var2; + + i2c_read_reg_to_buf(BMP280_ADDR, BMP280_PRES_REG, data, BMP280_RAWDATA_BYTES); + pres_raw = bmp280_24bit_reg(data[0], data[1], data[2]); + temp_raw = bmp280_24bit_reg(data[3], data[4], data[5]); + + temp_raw >>= 4; + pres_raw >>= 4; + + var1 = ((((temp_raw >> 3) - ((int32_t)bmp280_cal.dig_t1 << 1))) * + ((int32_t)bmp280_cal.dig_t2)) >> 11; + + var2 = (((((temp_raw >> 4) - ((int32_t)bmp280_cal.dig_t1)) * + ((temp_raw >> 4) - ((int32_t)bmp280_cal.dig_t1))) >>12) * + ((int32_t)bmp280_cal.dig_t3)) >> 14; + + t_fine = var1 + var2; + + baroTemperature = (t_fine * 5 + 128) >> 8; + + var1 = ((int64_t)t_fine) - 128000; + var2 = var1 * var1 * (int64_t)bmp280_cal.dig_p6; + var2 = var2 + ((var1 * (int64_t)bmp280_cal.dig_p5) << 17); + var2 = var2 + (((int64_t)bmp280_cal.dig_p4) << 35); + var1 = ((var1 * var1 * (int64_t)bmp280_cal.dig_p3) >> 8) + + ((var1 * (int64_t)bmp280_cal.dig_p2) << 12); + var1 = (((((int64_t)1) << 47) + var1)) * ((int64_t)bmp280_cal.dig_p1) >> 33; + + if (var1 == 0) { + return 0; // avoid exception caused by division by zero + } + p = 1048576 - pres_raw; + p = (((p << 31) - var2) * 3125) / var1; + var1 = (((int64_t)bmp280_cal.dig_p9) * (p >> 13) * (p >> 13)) >> 25; + var2 = (((int64_t)bmp280_cal.dig_p8) * p) >> 19; + + p = ((p + var1 + var2) >> 8) + (((int64_t)bmp280_cal.dig_p7) << 4); + baroPressure = p >> 8 ; //baroPressure in Pa + +} + +void Baro_init() { + bmp280_getcalibration(); + bmp280_set_config(0, 4, 0); // 0.5 ms standby time, 16x filter, no 3-wire SPI + bmp280_set_ctrl(2, 5, 3); // T oversample x2, P over sample x16, normal mode + deadline = currentTime+5000; +} + +//return 0: no data available, no computation ; 1: new value available and computation ; + uint8_t Baro_update() { + if (currentTime < deadline) return 0; + deadline = currentTime+3000; + + Baro_Common(); + bmp280_measure(); + + return 1; +} +#endif + // ************************************************************************************************************ // I2C Barometer MS561101BA // ************************************************************************************************************ @@ -1536,4 +1685,4 @@ void initSensors() { initS(); if (i2c_errors_count == 0) break; // no error during init => init ok } -} +} diff --git a/config.h b/config.h index dffdfa1e..43e48902 100644 --- a/config.h +++ b/config.h @@ -184,6 +184,7 @@ /* I2C barometer */ //#define BMP085 + //#define BMP280 //#define MS561101BA /* I2C magnetometer */ @@ -1228,4 +1229,4 @@ Also note, that maqgnetic declination changes with time, so recheck your value e /*************************************************************************************************/ #endif /* CONFIG_H_ */ - + diff --git a/def.h b/def.h index 04a93dcb..012da7af 100644 --- a/def.h +++ b/def.h @@ -1686,7 +1686,7 @@ #define GYRO 0 #endif -#if defined(BMP085) || defined(MS561101BA) +#if defined(BMP085) || defined(BMP280) || defined(MS561101BA) #define BARO 1 #else #define BARO 0 @@ -2029,4 +2029,4 @@ #error "you use one feature that is no longer supported or has undergone a name change" #endif -#endif /* DEF_H_ */ +#endif /* DEF_H_ */