BMP085 wrong temperature measurments

Hi
I have hooked up this cool sensor and used calculation as suggested by the datasheet. But the result is way off . I suppose problem has to be in type of the variables , but cannot find the cause… pls help

readout of the calibration values dec/hex:
ac5 = 25186 / 0x6262
ac6 = 17528 / 0x4478
mc = -11075 / 0xD4BD
md = 9 / 0x0009

long x1, x2, b5;
unsigned int ac5, ac6;
int mc, md, temperature;

x1 = ((ut - ac6) * ac5) >> 15;
x2 = ((long)mc << 11)/(x1 + md);
b5 = x1 + x2;
temperature = ((b5 + 8 )>>4);

ut=25343/0x62FF
x1=6006/0x00001776
x2=-3770/0xFFFFF146
b5=2236/0x000008BC
temperature = 140/0x008C (this means 14.0°C ? )

Real temperature is 20,7°C at this moment

tnx for your help
Janez


Perhaps you have seen the Adafruit BMP085 Unified driver? It's a really solid driver, I've been using it for a while and always get readings within +/-3*C. I posted the link to the github repo below. You might want to look over the code and compare it with your implementation, although I recommend not reinventing the wheel (it's an anti-pattern).

Just put it in your sketches folder. If you need anyhelp understanding the code, I'd be more than willing to help :).

Please post your whole code so we can reproduce the problem.

Sparkfun has a demo sketch here - https://www.sparkfun.com/products/retired/9694 - don't know if it works.

code is writen in c
https://dl.dropboxusercontent.com/u/14031284/bmp085/BMP085.c
in my first post there is everything needed for temperature calc.
hope it helps

That is no arduino code and a possible cause could be that an int is 32 bit on that platform.

So try to make all variables long (32 bit on arduino) and give your code a try.

hi, changed to long and u_long where necesary
but the results stays exactly the same

jabi78:
hi, changed to long and u_long where necesary
but the results stays exactly the same

Did you take a look at the Adafruit driver like I posted above? I almost guarnatee it will reflect where your code is going wrong.

i was going once again through the code, taking special attention to the variables type, with no success though. I must have been missing something obvious :confused:

this is the code copied from the

UT = 27898;
_bmp085_coeffs.ac6 = 23153;
_bmp085_coeffs.ac5 = 32757;
_bmp085_coeffs.mc = -8711;
_bmp085_coeffs.md = 2868;
#endif

// step 1
X1 = (UT - (int32_t)_bmp085_coeffs.ac6) * ((int32_t)_bmp085_coeffs.ac5) / pow(2,15); // my result = 4743
X2 = ((int32_t)_bmp085_coeffs.mc * pow(2,11)) / (X1+(int32_t)_bmp085_coeffs.md); // my result = -2343
B5 = X1 + X2; // = 2400
t = (B5+8)/pow(2,4); // = 150
t /= 10;

could someone calculate X1, X2, B5 and t variables , so i can compare and find the couse of the problem ?

The only difference that I see between your code and the driver posted by Adafruit is that you have declared the variable temperature to be an int, whereas Adafruit declared the t variable (analogous to your temperature variable) a float. Those arithmetic operations won't always produce an integer value, so I would recommend changing that variable to a float. More than likely you are truncating the decimal value, which is why it is rounding down by one.

Give that a try! :wink:

You have an error in the last line!

It should be t = t * 10;

Also, here are some values from my sensor for you to play with:

ac6: 20562
ac5: 24469
mc: -11075
md: 2432
UT: 28705

x1: 6080
x2: -2664
b5: 3416
T: 214
T: 2140

Using a float variable devide by 100 to get the temperature = 21.40°C

what is that pow(2,15) crap ?

Not sure if you realise, you have to read those calibration constants from the device that YOU have. Don't use the ones which appear in any example code.

This is the code I use, I think

  int32_t  X1 = ((latest_raw_temp - (int32_t)ac6) * (int32_t)ac5) >> 15;
  int32_t  X2 = ((int32_t)mc << 11) / (X1 + (int32_t)md);
  int32_t  B5 = X1 + X2;
  float    temp = (float)((B5 + 8) >> 4);
  temp /= 10;                                   // divide by 10

md = 9 / 0x0009

I think that it is impossible for this value for the "md" constant in the equation/model, to be correct.

The reason why your value for "md" is no good, is because in your ridiculous code, you read the calibration bytes 0 through 19, and then byte 21. You don't read byte 20 at all.

michinyon:
This is the code I use, I think

  int32_t  X1 = ((latest_raw_temp - (int32_t)ac6) * (int32_t)ac5) >> 15;

int32_t  X2 = ((int32_t)mc << 11) / (X1 + (int32_t)md);
  int32_t  B5 = X1 + X2;
  float    temp = (float)((B5 + 8) >> 4);
  temp /= 10;                                   // divide by 10

That works as well. In my example I’m returning T as an int and then converting it to float / 100 for °C.

michinyon thanks for pointing that out
i have missed byte 20, changed i from 20 → 21
for(i=0;i<21;i++)
{
buff_BMPCAL = i2c_read(1); // Get memory

  • }*
  • buff_BMPCAL[21] = i2c_read(0); // Get last calibration byte*
    works ok now