Go Down

Topic: Barometric Presure sensor BMP180 (Read 4864 times) previous topic - next topic

michinyon

Quote
The Adafruit library allows you to put in a base altitude for more accurate altitude above sea level readings as that library also provides an altitude calculation. It has zero effect on the accuracy of anything else.

It also is no good for compensating any weather effects, so is more for experimentation - it is better to use a sample "ground level at now" and then measure differences rather than ever try to somehow measure an absolute above sea level with just a pressure sensor alone.

Normally if "altitude matters" you want to measure how high something went, or how high above the ground you are in the real time space, not how high above some arbitrary (sea level) number you are. You can always factor in the arbitrary number at another non-realtime time later if need be - well, according to my two cents anyway.


That's all true,   but then this "provided altitude" is coming from you,  or it is written into the sketch somewhere.   It's not coming from the sensor.

My advice would be to implement a sketch which does two things and two things only.   Read the data registers from the chip.   Implement the conversion algorithm as defined by Bosch.     

If you want to "compensate" for the air pressure at the airport,  or the known reference altitude,   then do that later.

michinyon

Looking at the code I have here,   I seem to have two different versions of the temperature calculation,  which are different.   I had to "fix" it, for some reason, which I don't fully recall now. 

I am not 100% certain,  but it appears that the first calculation is the wrong one,    and the second one is correct.

Code: [Select]

  X1 = ((latest_raw_temp - (int32_t)ac6) * (int32_t)ac5) >> 15;
  X2 = ((int32_t)mc << 11) - (X1 + md)/2;     // round up
  X2 /= (X1 + md);
  B5 = X1 + X2;


Code: [Select]

  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


This algorithm may have been intended for a device with a 32 bit int type.


askjacob


[

My advice would be to implement a sketch which does two things and two things only.   Read the data registers from the chip.   Implement the conversion algorithm as defined by Bosch.     


Yep, and the code from _Leo_ does just that - it is pretty much stock. The issue stems from the sample code from Bosch not being explicit with casting in the example, and how the Arduino environment handles it. The Bosch datasheet mentions the data types _returned_ for the registers, but not what is expected within the sample code itself - just that c++ handles it 'properly'... and it seems to for some people or most cases.

The Adafruit one is similar (but has nested if statements to handle the BMP085 as well as casting all over the place) so is much harder to to map back to the original algorithm.

So much fun for what I was hoping for a 'simple' datalogging application I am working on..

Cheers
JAcob

michinyon

The sensors which have a big value for AC1,  don't work,  because AC1 x 4 will overflow in the calculation of B3,   because it is performing a 16 bit calculation there,  unless you tell it otherwise.

But if the sensor happens to have small value of AC1,  you don't get this problem,  because it still fits in 16 bits.

You will observe that in Bosch's calculation,  AC1 is 408  and Leo's example ha 408 also,   but Jacob and Erhja  have 8000  and 9000 there,   which will overflow when multiplied by 4.

michinyon

This is the code which I was using

Code: [Select]

B6 = latest_B5 - 4000;
  X1 = ((int32_t)b2 * ( (B6 * B6)>>12 )) >> 11;
  X2 = ((int32_t)ac2 * B6) >> 11;
  X3 = X1 + X2;
  B3 = ((((int32_t)ac1*4 + X3) << oversampling) + 2) / 4;

  X1 = ((int32_t)ac3 * B6) >> 13;
  X2 = ((int32_t)b1 * ((B6 * B6) >> 12)) >> 16;
  X3 = ((X1 + X2) + 2) >> 2;
  B4 = ((uint32_t)ac4 * (uint32_t)(X3 + 32768)) >> 15;
  B7 = ((uint32_t)latest_raw_pressure - B3) * (uint32_t)( 50000UL >> oversampling );


michinyon

Quote
Oh, and they all read MB = -32768


If you look at the code,   MB is not even actually used !

michinyon

Quote
**
Karma: 58
Posts: 2794
View Profile
Email
Personal Message (Offline)
   
   
Re: Barometric Presure sensor BMP180
« Reply #31 on: Today at 01:29:29 am »
   Bigger Bigger Smaller Smaller Reset Reset Reply with quoteQuote Modify messageModify Remove messageRemove
Looking at the code I have here,   I seem to have two different versions of the temperature calculation,  which are different.   I had to "fix" it, for some reason, which I don't fully recall now.

I am not 100% certain,  but it appears that the first calculation is the wrong one,    and the second one is correct.

Code:

  X1 = ((latest_raw_temp - (int32_t)ac6) * (int32_t)ac5) >> 15;
  X2 = ((int32_t)mc << 11) - (X1 + md)/2;     // round up
  X2 /= (X1 + md);
  B5 = X1 + X2;


Code:

  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


This algorithm may have been intended for a device with a 32 bit int type.


Two further comments on this.

The mc<<11  will also potentially overflow if it is done as a 16 bit calculation.   It is important to have the cast in this line to ensure this happens.

The apparent big difference between the two calculations of X2 is not what it seems.  The result will actually the almost the same.    By subtracting half of the amount you are going to divide by,  before doing the division,   this has the effect of correcting the rounding of the least significant bit in the result of the division. 

askjacob


The sensors which have a big value for AC1,  don't work,  because AC1 x 4 will overflow in the calculation of B3,   because it is performing a 16 bit calculation there,  unless you tell it otherwise.

But if the sensor happens to have small value of AC1,  you don't get this problem,  because it still fits in 16 bits.

You will observe that in Bosch's calculation,  AC1 is 408  and Leo's example ha 408 also,   but Jacob and Erhja  have 8000  and 9000 there,   which will overflow when multiplied by 4.


Thanks for looking into that - I had a suspicion that the 'default' calculation depth is 16 bit, but did not know where to find out. Hard to work out, when it is a 8 bit platform, but may or may not be signed etc. Hence the stressing of needing to cast stuff - if even I am using the right terminology - I am new to "C/C++" (I come from other language backgrounds - ones very strict on fiddling like this - both a pain and godsend).

I will merge yours with what I have (basically Leo's) to ensure all of possibilities of overflow are caught, in the case of these ebay wonders :)

heers

askjacob


Quote
Oh, and they all read MB = -32768


If you look at the code,   MB is not even actually used !


Well, we can save a  one wire read and 2 bytes of ram potentially, although it may still be needed to initialise the device correctly, used externally or not...

Cheers
Jacob

michinyon

It appears (supposedly) as a constant in the code,   perhaps it was intended to be a configurable number.

In the actual code,  it's use is related to least-significant-bit rounding,    and not as an actual numerical context at all.  If you add -32768,  and then right shift 15 bits,   that is what it does.

askjacob

Ah, then perhaps it was used - for the BMP085, which was a less accurate device. Unprofessional Guess...

_Leo_


 ac1 =  8240;
 ac2 = -1128;
 ac3 = -1433;
 ac4 = 33630;
 ac5 = 25458 ;
 ac6 = 18542 ;
 b1  = 6515;
 b2  = 42 ;
 mb  =-32768 ;
 mc  = -11786;
 md  = 2541;

UP= 85170
UT=26199
OK, my values ADDED IN ABOVE
....
Cheers
Jacob


I've taken the above values and come up with the following:

b3 = -8020 (ac1 * 4 + x3)
Pressure: 217.55 mbar, 6.42 inHg
Pressure sensor reading out of range!!!!

b3 = 1073733804 (uint32_t)(ac1 * 4 + x3)
Pressure: 217.55 mbar, 6.42 inHg
Pressure sensor reading out of range!!!!

b3 = 8364 ((int32_t)ac1 * 4 + x3)
Pressure: 2249.15 mbar, 66.42 inHg
Pressure sensor reading out of range!!!!

Leo

Project "ALTDuino" - A homemade altimeter for model rockets.
http://www.altduino.de

_Leo_

#42
Jul 27, 2014, 09:46 am Last Edit: Jul 27, 2014, 09:56 am by _Leo_ Reason: 1

here:
Code: [Select]

Sensor calibration data:
AC1 = 9060
AC2 = -1244
AC3 = -14867
AC4 = 33491
AC5 = 25092
AC6 = 15143
B1 = 6515
B2 = 52
MB = -32768
MC = -11786
MD = 2764
----------------------------------
Temperature: 34.00 C, 93.20 F
Pressure: 1014.22 mbar, 29.95 inHg

UT: 42153
UP: 337220


regards


b3 = -9321 (ac1 * 4 + x3)
Pressure: 107.73 mbar, 3.18 inHg
Pressure sensor reading out of range!!!!

b3 = 1073732503 (uint32_t)(ac1 * 4 + x3)
Pressure: 107.73 mbar, 3.18 inHg
Pressure sensor reading out of range!!!!

b3 = 7063 ((int32_t)ac1 * 4 + x3)
Pressure: 2584.11 mbar, 76.31 inHg
Pressure sensor reading out of range!!!!

With both examples I'm unable to produce valid pressure readings.
Leo

Project "ALTDuino" - A homemade altimeter for model rockets.
http://www.altduino.de

_Leo_

Please ignore my last 2 posts.

I have found something interesting concerning the Oversampling settings. I need to look into that in more detail.
Leo

Project "ALTDuino" - A homemade altimeter for model rockets.
http://www.altduino.de

jimLee

Keep at it! This pressure sensor is next on my list of hardware I need to get working. Just reading through the stuff you've been doing & working on is getting me tired!

Thanks for listing all of this.

-jim lee

Go Up