Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

I have added new BMP280 barometer support in cleanflight #975

Closed
wants to merge 9 commits into from
7 changes: 7 additions & 0 deletions Makefile
Expand Up @@ -296,6 +296,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 \
Expand Down Expand Up @@ -337,6 +338,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 \
Expand Down Expand Up @@ -371,6 +373,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 \
Expand Down Expand Up @@ -431,6 +434,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 \
Expand Down Expand Up @@ -501,6 +505,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)
Expand All @@ -527,6 +532,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) \
Expand All @@ -539,6 +545,7 @@ SPRACINGF3_SRC = \
$(STM32F30x_COMMON_SRC) \
drivers/accgyro_mpu6050.c \
drivers/barometer_ms5611.c \
drivers/barometer_bmp280.c \
drivers/compass_ak8975.c \
drivers/compass_hmc5883l.c \
drivers/display_ug2864hsweg01.h \
Expand Down
212 changes: 212 additions & 0 deletions 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 <http://www.gnu.org/licenses/>.
*/

#include <stdbool.h>
#include <stdint.h>

#include <platform.h>

#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
21 changes: 21 additions & 0 deletions 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 <http://www.gnu.org/licenses/>.
*/

#pragma once

bool bmp280Detect(baro_t *baro);

3 changes: 2 additions & 1 deletion src/main/sensors/barometer.h
Expand Up @@ -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
Expand Down
9 changes: 9 additions & 0 deletions src/main/sensors/initialisation.c
Expand Up @@ -42,6 +42,7 @@

#include "drivers/barometer.h"
#include "drivers/barometer_bmp085.h"
#include "drivers/barometer_bmp280.h"
#include "drivers/barometer_ms5611.h"

#include "drivers/compass.h"
Expand Down Expand Up @@ -456,6 +457,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;
Expand Down
1 change: 1 addition & 0 deletions src/main/target/CC3D/target.h
Expand Up @@ -58,6 +58,7 @@
#define BARO
#define USE_BARO_MS5611
#define USE_BARO_BMP085
#define USE_BARO_BMP280

// External I2C MAG
#define MAG
Expand Down
1 change: 1 addition & 0 deletions src/main/target/CHEBUZZF3/target.h
Expand Up @@ -58,6 +58,7 @@

#define BARO
#define USE_BARO_MS5611
#define USE_BARO_BMP280

#define MAG
#define USE_MAG_AK8975
Expand Down
1 change: 1 addition & 0 deletions src/main/target/EUSTM32F103RC/target.h
Expand Up @@ -65,6 +65,7 @@
#define BARO
#define USE_BARO_MS5611
#define USE_BARO_BMP085
#define USE_BARO_BMP280

#define MAG
#define USE_MAG_HMC5883
Expand Down
1 change: 1 addition & 0 deletions src/main/target/NAZE/target.h
Expand Up @@ -107,6 +107,7 @@
#define BARO
#define USE_BARO_MS5611
#define USE_BARO_BMP085
#define USE_BARO_BMP280

#define MAG
#define USE_MAG_HMC5883
Expand Down
1 change: 1 addition & 0 deletions src/main/target/OLIMEXINO/target.h
Expand Up @@ -59,6 +59,7 @@
#define BARO
//#define USE_BARO_MS5611
#define USE_BARO_BMP085
#define USE_BARO_BMP280

#define MAG
#define USE_MAG_HMC5883
Expand Down
1 change: 1 addition & 0 deletions src/main/target/PORT103R/target.h
Expand Up @@ -88,6 +88,7 @@
#define BARO
#define USE_BARO_MS5611
#define USE_BARO_BMP085
#define USE_BARO_BMP280

#define MAG
#define USE_MAG_HMC5883
Expand Down
1 change: 1 addition & 0 deletions src/main/target/SPARKY/target.h
Expand Up @@ -41,6 +41,7 @@

#define BARO
#define USE_BARO_MS5611
#define USE_BARO_BMP280

#define MAG
#define USE_MAG_AK8975
Expand Down
1 change: 1 addition & 0 deletions src/main/target/SPRACINGF3/target.h
Expand Up @@ -49,6 +49,7 @@

#define BARO
#define USE_BARO_MS5611
#define USE_BARO_BMP280

#define MAG
#define USE_MAG_AK8975
Expand Down