From d2fcfc09067689d0b60a13b07b7ffcb39eb41e06 Mon Sep 17 00:00:00 2001 From: Richard Lehey Date: Tue, 2 Jun 2015 01:48:13 +0900 Subject: [PATCH 1/2] Add support for new BMP280 barometer --- src/main/drivers/barometer_bmp280.c | 212 ++++++++++++++++++++++++++++ src/main/drivers/barometer_bmp280.h | 21 +++ 2 files changed, 233 insertions(+) create mode 100644 src/main/drivers/barometer_bmp280.c create mode 100644 src/main/drivers/barometer_bmp280.h diff --git a/src/main/drivers/barometer_bmp280.c b/src/main/drivers/barometer_bmp280.c new file mode 100644 index 00000000000..3edb55c5f25 --- /dev/null +++ b/src/main/drivers/barometer_bmp280.c @@ -0,0 +1,212 @@ +/* + * This file is part of Cleanflight. + * + * Cleanflight is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Cleanflight is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Cleanflight. If not, see . + */ + +#include +#include + +#include + +#include "build_config.h" + +#include "barometer.h" + +#include "system.h" +#include "bus_i2c.h" + +#include "barometer_bmp280.h" + +#ifdef BARO + +// BMP280, address 0x76 + +#define BMP280_I2C_ADDR (0x76) +#define BMP280_DEFAULT_CHIP_ID (0x58) + +#define BMP280_CHIP_ID_REG (0xD0) /* Chip ID Register */ +#define BMP280_RST_REG (0xE0) /* Softreset Register */ +#define BMP280_STAT_REG (0xF3) /* Status Register */ +#define BMP280_CTRL_MEAS_REG (0xF4) /* Ctrl Measure Register */ +#define BMP280_CONFIG_REG (0xF5) /* Configuration Register */ +#define BMP280_PRESSURE_MSB_REG (0xF7) /* Pressure MSB Register */ +#define BMP280_PRESSURE_LSB_REG (0xF8) /* Pressure LSB Register */ +#define BMP280_PRESSURE_XLSB_REG (0xF9) /* Pressure XLSB Register */ +#define BMP280_TEMPERATURE_MSB_REG (0xFA) /* Temperature MSB Reg */ +#define BMP280_TEMPERATURE_LSB_REG (0xFB) /* Temperature LSB Reg */ +#define BMP280_TEMPERATURE_XLSB_REG (0xFC) /* Temperature XLSB Reg */ +#define BMP280_FORCED_MODE (0x01) + +#define BMP280_TEMPERATURE_CALIB_DIG_T1_LSB_REG (0x88) +#define BMP280_PRESSURE_TEMPERATURE_CALIB_DATA_LENGTH (24) +#define BMP280_DATA_FRAME_SIZE (6) + +#define BMP280_OVERSAMP_SKIPPED (0x00) +#define BMP280_OVERSAMP_1X (0x01) +#define BMP280_OVERSAMP_2X (0x02) +#define BMP280_OVERSAMP_4X (0x03) +#define BMP280_OVERSAMP_8X (0x04) +#define BMP280_OVERSAMP_16X (0x05) + +// configure pressure and temperature oversampling, forced sampling mode +#define BMP280_PRESSURE_OSR (BMP280_OVERSAMP_8X) +#define BMP280_TEMPERATURE_OSR (BMP280_OVERSAMP_1X) +#define BMP280_MODE (BMP280_PRESSURE_OSR << 2 | BMP280_TEMPERATURE_OSR << 5 | BMP280_FORCED_MODE) + +#define T_INIT_MAX (20) +// 20/16 = 1.25 ms +#define T_MEASURE_PER_OSRS_MAX (37) +// 37/16 = 2.3125 ms +#define T_SETUP_PRESSURE_MAX (10) +// 10/16 = 0.625 ms + +typedef struct bmp280_calib_param_t { + uint16_t dig_T1; /* calibration T1 data */ + int16_t dig_T2; /* calibration T2 data */ + int16_t dig_T3; /* calibration T3 data */ + uint16_t dig_P1; /* calibration P1 data */ + int16_t dig_P2; /* calibration P2 data */ + int16_t dig_P3; /* calibration P3 data */ + int16_t dig_P4; /* calibration P4 data */ + int16_t dig_P5; /* calibration P5 data */ + int16_t dig_P6; /* calibration P6 data */ + int16_t dig_P7; /* calibration P7 data */ + int16_t dig_P8; /* calibration P8 data */ + int16_t dig_P9; /* calibration P9 data */ + int32_t t_fine; /* calibration t_fine data */ +} bmp280_calib_param_t; + +static uint8_t bmp280_chip_id = 0; +static bool bmp280InitDone = false; +static bmp280_calib_param_t bmp280_cal; +// uncompensated pressure and temperature +static int32_t bmp280_up = 0; +static int32_t bmp280_ut = 0; + +static void bmp280_start_ut(void); +static void bmp280_get_ut(void); +static void bmp280_start_up(void); +static void bmp280_get_up(void); +static void bmp280_calculate(int32_t *pressure, int32_t *temperature); + +bool bmp280Detect(baro_t *baro) +{ + if (bmp280InitDone) + return true; + + delay(20); + + i2cRead(BMP280_I2C_ADDR, BMP280_CHIP_ID_REG, 1, &bmp280_chip_id); /* read Chip Id */ + if (bmp280_chip_id != BMP280_DEFAULT_CHIP_ID) + return false; + + // read calibration + i2cRead(BMP280_I2C_ADDR, BMP280_TEMPERATURE_CALIB_DIG_T1_LSB_REG, 24, (uint8_t *)&bmp280_cal); + // set oversampling + power mode (forced), and start sampling + i2cWrite(BMP280_I2C_ADDR, BMP280_CTRL_MEAS_REG, BMP280_MODE); + + bmp280InitDone = true; + + // these are dummy as temperature is measured as part of pressure + baro->ut_delay = 0; + baro->get_ut = bmp280_get_ut; + baro->start_ut = bmp280_start_ut; + + // only _up part is executed, and gets both temperature and pressure + baro->up_delay = ((T_INIT_MAX + T_MEASURE_PER_OSRS_MAX * (((1 << BMP280_TEMPERATURE_OSR) >> 1) + ((1 << BMP280_PRESSURE_OSR) >> 1)) + (BMP280_PRESSURE_OSR ? T_SETUP_PRESSURE_MAX : 0) + 15) / 16) * 1000; + baro->start_up = bmp280_start_up; + baro->get_up = bmp280_get_up; + baro->calculate = bmp280_calculate; + + return true; +} + +static void bmp280_start_ut(void) +{ + // dummy +} + +static void bmp280_get_ut(void) +{ + // dummy +} + +static void bmp280_start_up(void) +{ + // start measurement + // set oversampling + power mode (forced), and start sampling + i2cWrite(BMP280_I2C_ADDR, BMP280_CTRL_MEAS_REG, BMP280_MODE); +} + +static void bmp280_get_up(void) +{ + uint8_t data[BMP280_DATA_FRAME_SIZE]; + + // read data from sensor + i2cRead(BMP280_I2C_ADDR, BMP280_PRESSURE_MSB_REG, BMP280_DATA_FRAME_SIZE, data); + bmp280_up = (int32_t)((((uint32_t)(data[0])) << 12) | (((uint32_t)(data[1])) << 4) | ((uint32_t)data[2] >> 4)); + bmp280_ut = (int32_t)((((uint32_t)(data[3])) << 12) | (((uint32_t)(data[4])) << 4) | ((uint32_t)data[5] >> 4)); +} + +// Returns temperature in DegC, float precision. Output value of “51.23” equals 51.23 DegC. +// t_fine carries fine temperature as global value +float bmp280_compensate_T(int32_t adc_T) +{ + float var1, var2, T; + + var1 = (((float)adc_T) / 16384.0f - ((float)bmp280_cal.dig_T1) / 1024.0f) * ((float)bmp280_cal.dig_T2); + var2 = ((((float)adc_T) / 131072.0f - ((float)bmp280_cal.dig_T1) / 8192.0f) * (((float)adc_T) / 131072.0f - ((float)bmp280_cal.dig_T1) / 8192.0f)) * ((float)bmp280_cal.dig_T3); + bmp280_cal.t_fine = (int32_t)(var1 + var2); + T = (var1 + var2) / 5120.0f; + + return T; +} + +// Returns pressure in Pa as float. Output value of “96386.2” equals 96386.2 Pa = 963.862 hPa +float bmp280_compensate_P(int32_t adc_P) +{ + float var1, var2, p; + var1 = ((float)bmp280_cal.t_fine / 2.0f) - 64000.0f; + var2 = var1 * var1 * ((float)bmp280_cal.dig_P6) / 32768.0f; + var2 = var2 + var1 * ((float)bmp280_cal.dig_P5) * 2.0f; + var2 = (var2 / 4.0f) + (((float)bmp280_cal.dig_P4) * 65536.0f); + var1 = (((float)bmp280_cal.dig_P3) * var1 * var1 / 524288.0f + ((float)bmp280_cal.dig_P2) * var1) / 524288.0f; + var1 = (1.0f + var1 / 32768.0f) * ((float)bmp280_cal.dig_P1); + if (var1 == 0.0f) + return 0.0f; // avoid exception caused by division by zero + + p = 1048576.0f - (float)adc_P; + p = (p - (var2 / 4096.0f)) * 6250.0f / var1; + var1 = ((float)bmp280_cal.dig_P9) * p * p / 2147483648.0f; + var2 = p * ((float)bmp280_cal.dig_P8) / 32768.0f; + p = p + (var1 + var2 + ((float)bmp280_cal.dig_P7)) / 16.0f; + + return p; +} + +static void bmp280_calculate(int32_t *pressure, int32_t *temperature) +{ + // calculate + float t, p; + t = bmp280_compensate_T(bmp280_ut); + p = bmp280_compensate_P(bmp280_up); + + if (pressure) + *pressure = (int32_t)p; + if (temperature) + *temperature = (int32_t)t * 100; +} + +#endif diff --git a/src/main/drivers/barometer_bmp280.h b/src/main/drivers/barometer_bmp280.h new file mode 100644 index 00000000000..e6858ed10d0 --- /dev/null +++ b/src/main/drivers/barometer_bmp280.h @@ -0,0 +1,21 @@ +/* + * This file is part of Cleanflight. + * + * Cleanflight is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Cleanflight is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Cleanflight. If not, see . + */ + +#pragma once + +bool bmp280Detect(baro_t *baro); + From f267c527fd16d4b57599dfe072dc8f1c5507ff01 Mon Sep 17 00:00:00 2001 From: Richard Lehey Date: Tue, 2 Jun 2015 01:53:05 +0900 Subject: [PATCH 2/2] Add support for new BMP280 barometer, modified files --- Makefile | 7 +++++++ src/main/sensors/barometer.h | 3 ++- src/main/sensors/initialisation.c | 9 +++++++++ src/main/target/CC3D/target.h | 1 + src/main/target/CHEBUZZF3/target.h | 1 + src/main/target/EUSTM32F103RC/target.h | 1 + src/main/target/NAZE/target.h | 1 + src/main/target/OLIMEXINO/target.h | 1 + src/main/target/PORT103R/target.h | 1 + src/main/target/SPARKY/target.h | 1 + src/main/target/SPRACINGF3/target.h | 1 + 11 files changed, 26 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 3d06d4a1d25..8781de0cb2e 100644 --- a/Makefile +++ b/Makefile @@ -295,6 +295,7 @@ NAZE_SRC = startup_stm32f10x_md_gcc.S \ drivers/adc.c \ drivers/adc_stm32f10x.c \ drivers/barometer_bmp085.c \ + drivers/barometer_bmp280.c \ drivers/barometer_ms5611.c \ drivers/bus_spi.c \ drivers/bus_i2c_stm32f10x.c \ @@ -336,6 +337,7 @@ EUSTM32F103RC_SRC = startup_stm32f10x_hd_gcc.S \ drivers/adc.c \ drivers/adc_stm32f10x.c \ drivers/barometer_bmp085.c \ + drivers/barometer_bmp280.c \ drivers/barometer_ms5611.c \ drivers/bus_i2c_stm32f10x.c \ drivers/bus_spi.c \ @@ -368,6 +370,7 @@ OLIMEXINO_SRC = startup_stm32f10x_md_gcc.S \ drivers/adc.c \ drivers/adc_stm32f10x.c \ drivers/barometer_bmp085.c \ + drivers/barometer_bmp280.c \ drivers/bus_i2c_stm32f10x.c \ drivers/bus_spi.c \ drivers/compass_hmc5883l.c \ @@ -428,6 +431,7 @@ CC3D_SRC = \ drivers/adc.c \ drivers/adc_stm32f10x.c \ drivers/barometer_bmp085.c \ + drivers/barometer_bmp280.c \ drivers/barometer_ms5611.c \ drivers/bus_spi.c \ drivers/bus_i2c_stm32f10x.c \ @@ -498,6 +502,7 @@ STM32F3DISCOVERY_SRC = \ drivers/accgyro_mpu6050.c \ drivers/accgyro_l3g4200d.c \ drivers/barometer_ms5611.c \ + drivers/barometer_bmp280.c \ drivers/compass_ak8975.c \ $(HIGHEND_SRC) \ $(COMMON_SRC) @@ -512,6 +517,7 @@ SPARKY_SRC = \ drivers/display_ug2864hsweg01.c \ drivers/accgyro_mpu6050.c \ drivers/barometer_ms5611.c \ + drivers/barometer_bmp280.c \ drivers/compass_ak8975.c \ drivers/serial_usb_vcp.c \ $(HIGHEND_SRC) \ @@ -524,6 +530,7 @@ SPRACINGF3_SRC = \ $(STM32F30x_COMMON_SRC) \ drivers/accgyro_mpu6050.c \ drivers/barometer_ms5611.c \ + drivers/barometer_bmp280.c \ drivers/compass_hmc5883l.c \ drivers/display_ug2864hsweg01.h \ drivers/flash_m25p16.c \ diff --git a/src/main/sensors/barometer.h b/src/main/sensors/barometer.h index 685f6b84343..9e107283d09 100644 --- a/src/main/sensors/barometer.h +++ b/src/main/sensors/barometer.h @@ -21,7 +21,8 @@ typedef enum { BARO_NONE = 0, BARO_DEFAULT = 1, BARO_BMP085 = 2, - BARO_MS5611 = 3 + BARO_MS5611 = 3, + BARO_BMP280 = 4 } baroSensor_e; #define BARO_SAMPLE_COUNT_MAX 48 diff --git a/src/main/sensors/initialisation.c b/src/main/sensors/initialisation.c index 9f61b732697..f337eb6ecc5 100644 --- a/src/main/sensors/initialisation.c +++ b/src/main/sensors/initialisation.c @@ -41,6 +41,7 @@ #include "drivers/barometer.h" #include "drivers/barometer_bmp085.h" +#include "drivers/barometer_bmp280.h" #include "drivers/barometer_ms5611.h" #include "drivers/compass.h" @@ -450,6 +451,14 @@ static void detectBaro() baroHardware = BARO_BMP085; break; } +#endif + ; // fallthough + case BARO_BMP280: +#ifdef USE_BARO_BMP280 + if (bmp280Detect(&baro)) { + baroHardware = BARO_BMP280; + break; + } #endif case BARO_NONE: baroHardware = BARO_NONE; diff --git a/src/main/target/CC3D/target.h b/src/main/target/CC3D/target.h index 2504bde7aa6..ea773afbd5f 100644 --- a/src/main/target/CC3D/target.h +++ b/src/main/target/CC3D/target.h @@ -58,6 +58,7 @@ #define BARO #define USE_BARO_MS5611 #define USE_BARO_BMP085 +#define USE_BARO_BMP280 // External I2C MAG #define MAG diff --git a/src/main/target/CHEBUZZF3/target.h b/src/main/target/CHEBUZZF3/target.h index 8bca64d8d2d..19480d65e08 100644 --- a/src/main/target/CHEBUZZF3/target.h +++ b/src/main/target/CHEBUZZF3/target.h @@ -58,6 +58,7 @@ #define BARO #define USE_BARO_MS5611 +#define USE_BARO_BMP280 #define MAG #define USE_MAG_AK8975 diff --git a/src/main/target/EUSTM32F103RC/target.h b/src/main/target/EUSTM32F103RC/target.h index 8a873282ec7..8d883d1b0ef 100644 --- a/src/main/target/EUSTM32F103RC/target.h +++ b/src/main/target/EUSTM32F103RC/target.h @@ -64,6 +64,7 @@ #define BARO #define USE_BARO_MS5611 #define USE_BARO_BMP085 +#define USE_BARO_BMP280 #define MAG #define USE_MAG_HMC5883 diff --git a/src/main/target/NAZE/target.h b/src/main/target/NAZE/target.h index 533a94f1083..ec5fa0f2515 100644 --- a/src/main/target/NAZE/target.h +++ b/src/main/target/NAZE/target.h @@ -104,6 +104,7 @@ #define BARO #define USE_BARO_MS5611 #define USE_BARO_BMP085 +#define USE_BARO_BMP280 #define MAG #define USE_MAG_HMC5883 diff --git a/src/main/target/OLIMEXINO/target.h b/src/main/target/OLIMEXINO/target.h index 3a2adb0c709..65581cd7601 100644 --- a/src/main/target/OLIMEXINO/target.h +++ b/src/main/target/OLIMEXINO/target.h @@ -59,6 +59,7 @@ #define BARO //#define USE_BARO_MS5611 #define USE_BARO_BMP085 +#define USE_BARO_BMP280 #define MAG #define USE_MAG_HMC5883 diff --git a/src/main/target/PORT103R/target.h b/src/main/target/PORT103R/target.h index f87be5a22e5..20b6bb6c98d 100644 --- a/src/main/target/PORT103R/target.h +++ b/src/main/target/PORT103R/target.h @@ -75,6 +75,7 @@ #define BARO #define USE_BARO_MS5611 #define USE_BARO_BMP085 +#define USE_BARO_BMP280 #define MAG #define USE_MAG_HMC5883 diff --git a/src/main/target/SPARKY/target.h b/src/main/target/SPARKY/target.h index 1c835d2b027..d054055a8c7 100644 --- a/src/main/target/SPARKY/target.h +++ b/src/main/target/SPARKY/target.h @@ -41,6 +41,7 @@ #define BARO #define USE_BARO_MS5611 +#define USE_BARO_BMP280 #define MAG #define USE_MAG_AK8975 diff --git a/src/main/target/SPRACINGF3/target.h b/src/main/target/SPRACINGF3/target.h index 64de123da92..4d1d4069f93 100644 --- a/src/main/target/SPRACINGF3/target.h +++ b/src/main/target/SPRACINGF3/target.h @@ -49,6 +49,7 @@ #define BARO #define USE_BARO_MS5611 +#define USE_BARO_BMP280 #define MAG #define USE_MAG_HMC5883