Monday, December 19, 2011

BMP085 Code Revisited Floating Point Version

Previously I posted a correction to the Bosch BMP085 calculation.
Today I found this paper, BMP085-Calcs.pdf but was unable to find C code to go with the paper.

This code results in more refined altitude increments and uses the whole accuracy.  The old integer code rounds of some bits and makes altitude increments more chunky.

(Very important in some altitude based feedback systems and others)

So I dug in and implemented it...

My variables, then the constant calcs, then the calc, then the test code.


int Baro_ac1, Baro_ac2, Baro_ac3, Baro_b1, Baro_b2, Baro_mb, Baro_mc, Baro_md;
unsigned int Baro_ac4, Baro_ac5, Baro_ac6;

float Baro_fc3;
float Baro_fc4;
float Baro_fb1;
float Baro_fc5;
float Baro_fc6;
float Baro_fmc;
float Baro_fmd;
float Baro_fx0;
float Baro_fx1;
float Baro_fx2;
float Baro_fy0;
float Baro_fy1;
float Baro_fy2;
float Baro_fp0;
float Baro_fp1;
float Baro_fp2;

...

// And calculate derrived constants used by BaroCalcFloat()
// from http://wmrx00.sourceforge.net/Arduino/BMP085-Calcs.pdf
Baro_fc3 = 160.0f * powf(2.0f, -15.0) * Baro_ac3;
Baro_fc4 = 0.001f * powf(2.0f, -15.0) * Baro_ac4;
Baro_fb1 = (160.0f * 160.0f) * powf(2.0f, -30.0) * Baro_b1;

Baro_fc5 = Baro_ac5 * powf(2.0f, -15.0) / 160.0f;
Baro_fc6 = Baro_ac6;
Baro_fmc = Baro_mc * powf(2.0f, 11.0) / (160.0f * 160.0f);
Baro_fmd = Baro_md / 160.0f;

Baro_fx0 = Baro_ac1;
Baro_fx1 = 160.0f * powf(2.0f, -13.0) * Baro_ac2;
Baro_fx2 = (160.0f * 160.0f) * powf(2.0f, -25.0) * Baro_b2;

Baro_fy0 = Baro_fc4 * powf(2.0f, 15.0);
Baro_fy1 = Baro_fc4 * Baro_fc3;
Baro_fy2 = Baro_fc4 * Baro_fb1;

Baro_fp0 = (3791.0f - 8.0f)/1600.0f;
Baro_fp1 = 1.0f - 7357.0f * powf(2.0f, -20.0);
Baro_fp2 = 3038.0f * 100.0f * powf(2.0f, -36.0);

...

float tu = BaroState.rawTemperature;
// Assumes Baro_oss highest precision BARO_OSS_MODE_ULTRA_HIGH_RES.
float pu = BaroState.rawPressure / 256.0f;

float alpha = Baro_fc5 * (tu - Baro_fc6);
float Tc = alpha + Baro_fmc / (alpha + Baro_fmd);
BaroState.temperatureC = Tc;

float s = Tc - 25.0f;
float x = Baro_fx2 * (s * s) + Baro_fx1 * s + Baro_fx0;
float y = Baro_fy2 * (s * s) + Baro_fy1 * s + Baro_fy0;
float z = (pu - x) / y;
BaroState.pressurePa = Baro_fp2 * (z * z) + Baro_fp1 * z + Baro_fp0;

...

void BaroTestMathFloat()
{
mainMessagePrint(ROUTE_DEBUG, "Baro Test Math (float)\r\n");

Baro_ac1 =7911;
Baro_ac2 = -934;
Baro_ac3 = -14306;
Baro_ac4 = 31567;
Baro_ac5 = 25671;
Baro_ac6 = 18974;
Baro_b1 = 5498;
Baro_b2 = 46;
Baro_mb = -32768;
Baro_mc = -11075;
Baro_md = 2432;

Baro_fc3 = 160.0f * powf(2.0f, -15.0) * Baro_ac3;
Baro_fc4 = 0.001f * powf(2.0f, -15.0) * Baro_ac4;
Baro_fb1 = (160.0f * 160.0f) * powf(2.0f, -30.0) * Baro_b1;
mainMessagePrint(ROUTE_DEBUG, "fc3 %f fc4 %f fb1 %f", Baro_fc3, Baro_fc4, Baro_fb1);

Baro_fc5 = Baro_ac5 * powf(2.0f, -15.0) / 160.0f;
Baro_fc6 = Baro_ac6;
Baro_fmc = Baro_mc * powf(2.0f, 11.0) / (160.0f * 160.0f);
Baro_fmd = Baro_md / 160.0f;
mainMessagePrint(ROUTE_DEBUG, "fc5 %f fc6 %f fmc %f fmd %f",
Baro_fc5, Baro_fc6, Baro_fmc, Baro_fmd);

Baro_fx0 = Baro_ac1;
Baro_fx1 = 160.0f * powf(2.0f, -13.0) * Baro_ac2;
Baro_fx2 = (160.0f * 160.0f) * powf(2.0f, -25.0) * Baro_b2;
mainMessagePrint(ROUTE_DEBUG, "x %f %f %f",
Baro_fx0, Baro_fx1, Baro_fx2);

Baro_fy0 = Baro_fc4 * powf(2.0f, 15.0);
Baro_fy1 = Baro_fc4 * Baro_fc3;
Baro_fy2 = Baro_fc4 * Baro_fb1;
mainMessagePrint(ROUTE_DEBUG, "y %f %f %f",
Baro_fy0, Baro_fy1, Baro_fy2);

Baro_fp0 = (3791.0f - 8.0f)/1600.0f;
Baro_fp1 = 1.0f - 7357.0f * powf(2.0f, -20.0);
Baro_fp2 = 3038.0f * 100.0f * powf(2.0f, -36.0);
mainMessagePrint(ROUTE_DEBUG, "p %f %f %f",
Baro_fp0, Baro_fp1, Baro_fp2);

BaroState.rawTemperature = 0x69EC;
BaroState.rawPressure = 0x982FC0;
Baro_oss = BARO_OSS_MODE_ULTRA_HIGH_RES;

float tu = BaroState.rawTemperature;
// Assumes Baro_oss highest precision BARO_OSS_MODE_ULTRA_HIGH_RES.
float pu = BaroState.rawPressure / 256.0f;

mainMessagePrint(ROUTE_DEBUG, "rt %f rp %f", tu, pu);

float alpha = Baro_fc5 * (tu - Baro_fc6);
float Tc = alpha + Baro_fmc / (alpha + Baro_fmd);
BaroState.temperatureC = Tc;
mainMessagePrint(ROUTE_DEBUG, "a %f Tc %f", alpha, Tc);

float s = Tc - 25.0f;
float x = Baro_fx2 * (s * s) + Baro_fx1 * s + Baro_fx0;
float y = Baro_fy2 * (s * s) + Baro_fy1 * s + Baro_fy0;
float z = (pu - x) / y;
BaroState.pressurePa = Baro_fp2 * (z * z) + Baro_fp1 * z + Baro_fp0;
mainMessagePrint(ROUTE_DEBUG, "s %f x %f y %f z %f p %f", s, x, y, z, BaroState.pressurePa);
}



TF

No comments: