Use fixed point calculation for BMP280 barometer

Substitute the floating point calculation for the comparably much faster
64-bit calculation recommended for a Cortex-M3 (floating point is
recommended only in PC applications with FPU) [1]. Even if we have an
FPU, we round the temperature to the nearest 1/100th of a degree and the
pressure to the nearest 1 Pa, both of which are within the limits of the
fixed-point algorithm's accuracy.

Conflicts:
	src/main/drivers/barometer_bmp280.c
This commit is contained in:
Sean Vig 2015-09-17 01:54:43 -05:00 committed by Dominic Clifton
parent e5f3f1794f
commit 456396b25a
2 changed files with 32 additions and 32 deletions

View File

@ -160,53 +160,53 @@ static void bmp280_get_up(void)
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.
// Returns temperature in DegC, resolution is 0.01 DegC. Output value of "5123" equals 51.23 DegC
// t_fine carries fine temperature as global value
static float bmp280_compensate_T(int32_t adc_T)
static int32_t bmp280_compensate_T(int32_t adc_T)
{
float var1, var2, T;
int32_t 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;
var1 = ((((adc_T >> 3) - ((int32_t)bmp280_cal.dig_T1 << 1))) * ((int32_t)bmp280_cal.dig_T2)) >> 11;
var2 = (((((adc_T >> 4) - ((int32_t)bmp280_cal.dig_T1)) * ((adc_T >> 4) - ((int32_t)bmp280_cal.dig_T1))) >> 12) * ((int32_t)bmp280_cal.dig_T3)) >> 14;
bmp280_cal.t_fine = var1 + var2;
T = (bmp280_cal.t_fine * 5 + 128) >> 8;
return T;
}
// Returns pressure in Pa as float. Output value of "96386.2" equals 96386.2 Pa = 963.862 hPa
static float bmp280_compensate_P(int32_t adc_P)
// 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
static uint32_t 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;
int64_t var1, var2, p;
var1 = ((int64_t)bmp280_cal.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;
p = 1048576 - adc_P;
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);
return (uint32_t)p;
}
STATIC_UNIT_TESTED void bmp280_calculate(int32_t *pressure, int32_t *temperature)
{
// calculate
float t, p;
int32_t t;
uint32_t p;
t = bmp280_compensate_T(bmp280_ut);
p = bmp280_compensate_P(bmp280_up);
if (pressure)
*pressure = (int32_t)p;
*pressure = (int32_t)(p / 256);
if (temperature)
*temperature = (int32_t)t * 100;
*temperature = t;
}
#endif

View File

@ -73,7 +73,7 @@ TEST(baroBmp280Test, TestBmp280Calculate)
// then
EXPECT_EQ(100653, pressure); // 100653 Pa
EXPECT_EQ(2500, temperature); // 25.00 degC (data sheet says 25.08)
EXPECT_EQ(2508, temperature); // 25.08 degC
}
@ -104,7 +104,7 @@ TEST(baroBmp280Test, TestBmp280CalculateHighP)
// then
EXPECT_EQ(135382, pressure); // 135385 Pa
EXPECT_EQ(2500, temperature); // 25.00 degC (data sheet says 25.08)
EXPECT_EQ(2508, temperature); // 25.08 degC
}
@ -135,7 +135,7 @@ TEST(baroBmp280Test, TestBmp280CalculateZeroP)
// then
EXPECT_EQ(0, pressure); // P1=0 trips pressure to 0 Pa, avoiding division by zero
EXPECT_EQ(2500, temperature); // 25.00 degC (data sheet says 25.08)
EXPECT_EQ(2508, temperature); // 25.08 degC
}