Home
JAQForum Ver 24.01
Log In or Join  
Active Topics
Local Time 15:18 25 Nov 2024 Privacy Policy
Jump to

Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.

Forum Index : Microcontroller and PC projects : Bosch BMP085 Barometer FP Pres. Cal.

Author Message
DuinoMiteMegaAn
Senior Member

Joined: 17/11/2011
Location: Australia
Posts: 231
Posted: 02:08pm 06 Mar 2012
Copy link to clipboard 
Print this post

This sensor provides barometric pressure and temperature. It can also be used to calculate altitude. Both Sparkfun and Adafruit vendors have this precision sensor. ($20 USD) This BMP085 is an excellant choice for use in a weather station for predicting weather. I just might add it to my Outback Dot Clock project!

The BMP085 I2C 3.3v barometric sensor mates well with the MaxiMite.
The complex floating point (instead of integer math) can be easily done in MMBasic.

Below is the precision floating point "test" code I converted to MMBasic.
The I2C communicating code will be posted later after my BMP085 hardware arrives.

Ref. Doc.

2012-03-07_000021_BMP085-Calcs.pdf


'File: BMP085R1.bas
'Project: Outback Dot Clock Rev. 1.0b
'Author: Hacker - DuinoMiteMegaAndy
'Date: 3/6/2012
'App. Version: Rev. 1.0b
'MMBasic Firmware: 3.1 MaxiMite CGMMStick1
'Platform: Win XP/SP3
'===========================================================
'Bosch BMP085 Barometer Floating Point Pressure Calculations
'April 25, 2011
'===========================================================

'==========================================
' BMP085 Calibration Data - device specific
'==========================================
BMP085_AC1 = 7911
BMP085_AC2 = -934
BMP085_AC3 = -14306
BMP085_AC4 = 31567
BMP085_AC5 = 25671
BMP085_AC6 = 18974
BMP085_B1 = 5498
BMP085_B2 = 46
BMP085_MB = -32768
BMP085_MC = -11075
BMP085_MD = 2432

'===============================
'BMP085 Derived Calibration Data
'===============================

'This data remains constant for any given sensor and need not be read and
'computed every time the sensor is powered on. Once all values are computed,
'it is not necessary to retain the values of BMP085_c3, BMP085_c4, BMP085_b1.

'The first three values are only used
'in computing the final constants below and can be discarded afterwards.

BMP085_c3 = 160*2^-15*BMP085_AC3
? "BMP085_c3 = ", BMP085_c3
BMP085_c4 = 10^-3*2^-15*BMP085_AC4
? "BMP085_c4 = ", BMP085_c4
BMP085_b1 = 160^2*2^-30*BMP085_B1
? "BMP085_b1 = ", BMP085_b1

'The next four constants are used in the computation of temperature.

BMP085_c5 = 2^-15/160*BMP085_AC5
? "BMP085_c5 = ", BMP085_c5
BMP085_c6 = BMP085_AC6
? "BMP085_c6 = ", BMP085_c6
BMP085_mc = 2^11/160^2*BMP085_MC
? "BMP085_mc = ", BMP085_mc
BMP085_md = BMP085_MD/160
? "BMP085_md = ", BMP085_md

'Three second order polynomials are used to compute pressure, and they
'require another nine constants (three for each polynomial).

BMP085_x0 = BMP085_AC1
? "BMP085_x0 = ", BMP085_x0
BMP085_x1 = 160*2^-13*BMP085_AC2
? "BMP085_x1 = ", BMP085_x1
BMP085_x2 = 160^2*2^-25*BMP085_B2
? "BMP085_x2 = ", BMP085_x2

BMP085_y0 = BMP085_c4*2^15
? "BMP085_y0 = ", BMP085_y0
BMP085_y1 = BMP085_c4*BMP085_c3
? "BMP085_y1 = ", BMP085_y1
BMP085_y2 = BMP085_c4*BMP085_b1
? "BMP085_y2 = ", BMP085_y2

BMP085_p0 = (3791-8)/1600
? "BMP085_p0 = ", BMP085_p0
BMP085_p1 = 1-(7357*2^-20)
? "BMP085_p1 = ", BMP085_p1
BMP085_p2 = 3038*100*2^-36 ' This constant is wrong in the PDF !!!!
? "BMP085_p2 = ", BMP085_p2

'The coefficients above have been scaled so that the final results will be
'temperature (BMP085_T) in degrees Celsius, and pressure (BMP085_P) in millibars (a.k.a hecto-
'Pascals)

'This wraps up the calculation of floating point constants that are used for
'converting the raw, integer temperature and pressure data into degrees Celsius
'and millibars.

'================
' BMP085 Formulas
'================

'The real-time data from the BMP085 will be represented by tu for temperature
'and pu for pressure. The temperature value is just equal to the integer
'value that is read from the barometer. The pressure reading is formatted a bit
'different however; it is treated like a fixed point fraction with the radix point just
'to the right of the LSB. After these integer values are acquired, all remaining
'calculations below are floating point. These first two formulas treat the integer
'register values as unsigned quantities.

'0x69EC I2C Temperature
'BMP085_tu = 256 ·MSB + LSB
BMP085_tu = 256*&H69 + &hEC
? "BMP085_tu = ", BMP085_tu

'0x982FC0 I2C Pressure
'BMP085_pu = 256 ·MSB + LSB + XLSB/256
BMP085_pu = (256*&H98)+&H2F+(&HC0/256)
? "BMP085_pu = ", BMP085_pu

'Defining pu in this way alleviates the need to make any further adjustments
'for the over-sampling ratio (OSS). If OSS is zero, it is not necessary to read the
'XLSB register and its value can be set to zero.

'The temperature computation is quite simple. First we define a new value,
'and then compute temperature in terms of this new variable:

BMP085_a = BMP085_c5*(BMP085_tu - BMP085_c6)
BMP085_T = BMP085_a + (BMP085_mc / (BMP085_a + BMP085_md))
BMP085_Tc = BMP085_T
? "BMP085_Tc degrees C = ", BMP085_Tc

BMP085_Tf = 1.8 * BMP085_T + 32
? "BMP085_Tf degrees F = ", BMP085_Tf


'Computing pressure requires the temperature (BMP085_T) computed above, and uses
'three second-order polynomials. The first two generate offset (BMP085_x) and scaling
'factors (y) which are functions of the difference between the current temperature
'and 25C (which we’ll call BMP085_s).

BMP085_s = BMP085_T - 25
? "BMP085_s = ", BMP085_s

BMP085_x = BMP085_x2*BMP085_s^2 + BMP085_x1*BMP085_s + BMP085_x0
? "BMP085_x = ", BMP085_x

BMP085_y = BMP085_y2*BMP085_s^2 + BMP085_y1*BMP085_s + BMP085_y0
? "BMP085_y = ", BMP085_y

'These two factors are now used to compute an initial pressure value, BMP085_z:

BMP085_z = (BMP085_pu - BMP085_x) / BMP085_y
? "BMP085_z = ", BMP085_z

'A polynomial in BMP085_z gives the final corrected pressure value.

BMP085_P = BMP085_p2*BMP085_z^2 + BMP085_p1*BMP085_z + BMP085_p0
? "BMP085_P millibars = ", BMP085_P
End




Test results


BMP085_c3 = -69.8535
BMP085_c4 = 0.000963348
BMP085_b1 = 0.131083
BMP085_c5 = 0.00489635
BMP085_c6 = 18974
BMP085_mc = -886
BMP085_md = 15.2
BMP085_x0 = 7911
BMP085_x1 = -18.2422
BMP085_x2 = 0.0350952
BMP085_y0 = 31.567
BMP085_y1 = -0.0672933
BMP085_y2 = 0.000126278
BMP085_p0 = 2.36438
BMP085_p1 = 0.992984
BMP085_p2 = 4.42087e-06
BMP085_tu = 27116
BMP085_pu = 38959.8
BMP085_Tc degrees C = 23.7764
BMP085_Tf degrees F = 74.7975
BMP085_s = -1.22363
BMP085_x = 7933.37
BMP085_y = 31.6495
BMP085_z = 980.311
BMP085_P millibars = 980.045


Enjoy Edited by DuinoMiteMegaAn 2012-03-08
 
Juri74

Senior Member

Joined: 06/02/2012
Location: Italy
Posts: 162
Posted: 11:05am 09 Mar 2012
Copy link to clipboard 
Print this post

that's very useful! great work! Do you have some mathematical formula to calculate altitude too?
thank you
 
DuinoMiteMegaAn
Senior Member

Joined: 17/11/2011
Location: Australia
Posts: 231
Posted: 01:40pm 09 Mar 2012
Copy link to clipboard 
Print this post

Both Sparkfun and Adafruit provide detailed on-line tutorials for the complex Bosch BMP085. Both vendors also include the altitude calculation and weather prediction algorithms from the barometric pressure and temperature readiings. Edited by DuinoMiteMegaAn 2012-03-10
 
DuinoMiteMegaAn
Senior Member

Joined: 17/11/2011
Location: Australia
Posts: 231
Posted: 06:07pm 12 Mar 2012
Copy link to clipboard 
Print this post

MaxiMite application test code for the BMP085 Digital Pressure Sensor by Bosch Sensortec.

This code is still in the beta testing <------<<<<
Any calculation errors please report them on this board's topic link.

This code was made for testing the BMP085 on the MaxiMite and all algorithms
can be greatly reduced by the end user!

This code is "as is" No warranty implied. Use at your own risk! <------<<<<<

What's working:
#1. I2C reading/calculating constants from the BMP085
#2. I2C reading/calculating temperature from the BMP05
#3. I2C reading/calculating barometric pressure from the BMP085
with all oversampling modes working.
#4. Altitude calculation - needs work
#5. Weather prediction / calculation - needs work

What's not working - unknown?
More testing on-going.

Applications:
Model rocketry --> Launch a CGMMStick1 with the BMP085 and measure altitude.
Weather forcasting.
Pressure measurement
Temperature measurement

Usage
Hookup the BMP085 to the MaxiMite with proper pullups and power (+3 VDC ONLY!!!!)
load / run "bmp085R7.bas"
Check static FP calculation by calling subroutine "FP_BMP085_Test_R1" (Just type in this string)
Check all measurement by by calling subroutine "read_BMP085"
Check pressure oversampling modes by calling subroutine "check_BMP085_OSS_Modes"

Enjoy

Ref.
Links:

Sparkfun tutorial <----<<<< helpful
http://www.sparkfun.com/tutorials/253

Adafruit tutorial <----<<< helpfu
http://www.ladyada.net/learn/sensors/bmp085.html

Docs

Spec. sheet
bmp085_datasheet_rev.1.0_1July2008.pdf

2012-03-13_040342_BMP085_DataSheet_Rev.1.0_01July2008.pdf

Bosch BMP085 Barometer Floating Point Pressure Calculations ...and some analysis...April 25, 2011
BMP085-Calcs.pdf

2012-03-13_040302_BMP085-Calcs.pdf


Code

'--------- BMP085R7.bas --------------------
'Project:
'Author: Hacker - DuinoMiteMegaAndy
'Date: 3/12/2012
'App. Version: Rev. 1.0b
'MMBasic Firmware: 3.1 MaxiMite CGMMStick1
'Platform: Win XP/SP3
'
'Testing conditions:
'MaxiMite aka CGMMStick1
'I2C with 2.2K pullups @ 100 Khz
'
'Warning ... BMP085 is light sensitive - keep port shielded away from direct light
'
'There are two pullup resistors on the breakout module!
'I had to remove them because I had other pullups elsewhere.


OPTION BASE 0
DIM BMP085_buff(22)
BMP085_I2CADDR = &h77
BMP085_ULTRALOWPOWER = 0
BMP085_STANDARD = 1
BMP085_HIGHRES = 2
BMP085_ULTRAHIGHRES = 3
BMP085_CONTROL = &hF4
BMP085_TEMPDATA = &hF6
BMP085_PRESSUREDATA = &hF6
BMP085_READTEMPCMD = &h2E
BMP085_READPRESSURECMD = &h34

BMP085_altitude_M = 0 ' altitude in meters
BMP085_altitude_F = 0 ' altitude in feet
Raw_Pres = 0

'----------------------------------------------------------- --------------------
'----------------------------------------------------------- --------------------

SUB FP_BMP085_Test_R1
'
'Author: Hacker
'Date: 3/9/2012
'Rev: 1.0b
'Description: From PDF ---> "Bosch BMP085 Barometer Floating Point Pressure Calculations.PDF" April 25, 2011
'for the PIC32 MaxiMite - for reference only.
'This test does NOT include the I2C code for the BMP085.
'See other subroutines below for the I2C interface.
'
'This test shows the results from the complex floating point calculations
'for the Bosch BMP085 - see pdf - these calculations are "spot on" and matches
'this reference document.
'
'======================================================
' BMP085 Calibration Data - device specific - Test only
'======================================================
BMP085_AC1 = 7911
BMP085_AC2 = -934
BMP085_AC3 = -14306
BMP085_AC4 = 31567 'Unsigned?
BMP085_AC5 = 25671 'Unsigned?
BMP085_AC6 = 18974 'Unsigned?
BMP085_B1 = 5498
BMP085_B2 = 46
BMP085_MB = -32768
BMP085_MC = -11075
BMP085_MD = 2432

'===============================
'BMP085 Derived Calibration Data
'===============================

'This data remains constant for any given sensor and need not be read and
'computed every time the sensor is powered on. Once all values are computed,
'it is not necessary to retain the values of BMP085_c3, BMP085_c4, BMP085_b1.

'The first three values are only used
'in computing the final constants below and can be discarded afterwards.

BMP085_c3 = 160*2^-15*BMP085_AC3
? "BMP085_c3 = ", BMP085_c3
BMP085_c4 = 10^-3*2^-15*BMP085_AC4
? "BMP085_c4 = ", BMP085_c4
BMP085_b1 = 160^2*2^-30*BMP085_B1
? "BMP085_b1 = ", BMP085_b1

'The next four constants are used in the computation of temperature.

BMP085_c5 = 2^-15/160*BMP085_AC5
? "BMP085_c5 = ", BMP085_c5
BMP085_c6 = BMP085_AC6
? "BMP085_c6 = ", BMP085_c6
BMP085_mc = 2^11/160^2*BMP085_MC
? "BMP085_mc = ", BMP085_mc
BMP085_md = BMP085_MD/160
? "BMP085_md = ", BMP085_md

'Three second order polynomials are used to compute pressure, and they
'require another nine constants (three for each polynomial).

BMP085_x0 = BMP085_AC1
? "BMP085_x0 = ", BMP085_x0
BMP085_x1 = 160*2^-13*BMP085_AC2
? "BMP085_x1 = ", BMP085_x1
BMP085_x2 = 160^2*2^-25*BMP085_B2
? "BMP085_x2 = ", BMP085_x2

BMP085_y0 = BMP085_c4*2^15
? "BMP085_y0 = ", BMP085_y0
BMP085_y1 = BMP085_c4*BMP085_c3
? "BMP085_y1 = ", BMP085_y1
BMP085_y2 = BMP085_c4*BMP085_b1
? "BMP085_y2 = ", BMP085_y2

BMP085_p0 = (3791-8)/1600
? "BMP085_p0 = ", BMP085_p0
BMP085_p1 = 1-(7357*2^-20)
? "BMP085_p1 = ", BMP085_p1
BMP085_p2 = 3038*100*2^-36 ' This constant is wrong in the PDF !!!!
? "BMP085_p2 = ", BMP085_p2

'The coefficients above have been scaled so that the final results will be
'temperature (BMP085_T) in degrees Celsius, and pressure (BMP085_P) in millibars (a.k.a hecto-
'Pascals)

'This wraps up the calculation of floating point constants that are used for
'converting the raw, integer temperature and pressure data into degrees Celsius
'and millibars.

'================
' BMP085 Formulas
'================

'The real-time data from the BMP085 will be represented by BMP085_tu for temperature
'and BMP085_pu for pressure. The temperature value is just equal to the integer
'value that is read from the barometer. The pressure reading is formatted a bit
'different however; it is treated like a fixed point fraction with the radix point just
'to the right of the LSB. After these integer values are acquired, all remaining
'calculations below are floating point. These first two formulas treat the integer
'register values as unsigned quantities.

'0x69EC I2C Temperature
'BMP085_tu = 256 ·MSB + LSB
BMP085_tu = 256*&H69 + &hEC
? "BMP085_tu = ", BMP085_tu

'0x982FC0 I2C Pressure
'BMP085_pu = 256 ·MSB + LSB + XLSB/256
BMP085_pu = (256*&H98)+&H2F+(&HC0/256)
? "BMP085_pu = ", BMP085_pu

'Defining BMP085_pu in this way alleviates the need to make any further adjustments
'for the over-sampling ratio (OSS). If OSS is zero, it is not necessary to read the
'XLSB register and its value can be set to zero.

'The temperature computation is quite simple. First we define a new value,
'and then compute temperature in terms of this new variable:

BMP085_a = BMP085_c5*(BMP085_tu - BMP085_c6)
BMP085_T = BMP085_a + (BMP085_mc / (BMP085_a + BMP085_md))
BMP085_Tc = BMP085_T
? "BMP085_Tc degrees C = ", BMP085_Tc

BMP085_Tf = 1.8 * BMP085_T + 32
? "BMP085_Tf degrees F = ", BMP085_Tf


'Computing pressure requires the temperature (BMP085_T) computed above, and uses
'three second-order polynomials. The first two generate offset (BMP085_x) and scaling
'factors (y) which are functions of the difference between the current temperature
'and 25C (which we’ll call BMP085_s).

BMP085_s = BMP085_T - 25
? "BMP085_s = ", BMP085_s

BMP085_x = BMP085_x2*BMP085_s^2 + BMP085_x1*BMP085_s + BMP085_x0
? "BMP085_x = ", BMP085_x

BMP085_y = BMP085_y2*BMP085_s^2 + BMP085_y1*BMP085_s + BMP085_y0
? "BMP085_y = ", BMP085_y

'These two factors are now used to compute an initial pressure value, BMP085_z:

BMP085_z = (BMP085_pu - BMP085_x) / BMP085_y
? "BMP085_z = ", BMP085_z

'A polynomial in BMP085_z gives the final corrected pressure value.

BMP085_P = BMP085_p2*BMP085_z^2 + BMP085_p1*BMP085_z + BMP085_p0
? "BMP085_P millibars = ", BMP085_P
END SUB


'----------------------------------------------------------- --------------------
SUB read_BMP085_Raw_Temp
'BMP085_I2CADDR &h77
'BMP085_CONTROL &hF4
'BMP085_TEMPDATA &hF6
'BMP085_PRESSUREDATA &hF6
'BMP085_READTEMPCMD &h2E
'BMP085_READPRESSURECMD &h34
DIM temp_buff(2)
I2CEN 100,100 'Enable I2C 100 Khz 100 ms timeout
I2CSEND BMP085_I2CADDR,0,2,BMP085_CONTROL,BMP085_READTEMPCMD' write
I2CDIS
Pause 5
'
I2CEN 100,100 ' Enable I2C 100 Khz 100 ms timeout
I2CRCV BMP085_I2CADDR, 0, 2, temp_buff(0),1,BMP085_TEMPDATA 'write then read
I2CDIS
BMP085_tu = (temp_buff(0)*2^8) + temp_buff(1)
Erase temp_buff
END SUB

'----------------------------------------------------------- --------------------
SUB read_BMP085_Raw_Pres (mode)
local OSS

' for ref only
'BMP085_I2CADDR &h77
'BMP085_ULTRALOWPOWER 0
'BMP085_STANDARD 1
'BMP085_HIGHRES 2
'BMP085_ULTRAHIGHRES 3
'BMP085_CONTROL &hF4
'BMP085_TEMPDATA &hF6
'BMP085_PRESSUREDATA &hF6
'BMP085_READTEMPCMD &h2E
'BMP085_READPRESSURECMD &h34

if (mode > BMP085_ULTRAHIGHRES) then mode = BMP085_ULTRAHIGHRES
oversampling = mode

if oversampling = 0 then OSS = &h34
if oversampling = 1 then OSS = &h74
if oversampling = 2 then OSS = &hB4
if oversampling = 3 then OSS = &hF4


DIM pres_buff(3)
I2CEN 100,100 'Enable I2C 100 Khz 100 ms timeout
'I2CSEND BMP085_I2CADDR,0,2,BMP085_CONTROL, (BMP085_READPRESSURECMD + (oversampling*2^6))' write
'simplified I2C write
I2CSEND BMP085_I2CADDR,0,2,BMP085_CONTROL,OSS ' write
I2CDIS

'wait for oversampling to finish - timed

IF (oversampling = BMP085_ULTRALOWPOWER) THEN
Pause 5 ' ms
ELSEIF (oversampling = BMP085_STANDARD) THEN
Pause 8
ELSEIF (oversampling = BMP085_HIGHRES) THEN
Pause 14
ELSE
Pause 26' ms
ENDIF
'
I2CEN 100,100 ' Enable I2C 100 Khz 100 ms timeout
I2CRCV BMP085_I2CADDR, 0, 3, pres_buff(0),1,BMP085_PRESSUREDATA 'write then read
I2CDIS
'
BMP085_pu =(PRES_buff(0)*(2^16) + PRES_buff(1)*(2^8) + PRES_buff(2)) \ 2^(8-oversampling)
raw_pres = BMP085_pu

if oversampling = 0 then BMP085_pu = BMP085_pu ' 1 sample
if oversampling = 1 then BMP085_pu = BMP085_pu / 2 ' 2 samples
if oversampling = 2 then BMP085_pu = BMP085_pu / 4 ' 4 samples
if oversampling = 3 then BMP085_pu = BMP085_pu / 8 ' 8 samples

Erase pres_buff
END SUB
'----------------------------------------------------------- --------------------
'----------------------------------------------------------- --------------------


'----------------------------------------------------------- --------------------
' I2C BMP085 Algorithms for the MaxiMite PIC32
'----------------------------------------------------------- --------------------

SUB read_BMP085_Constants
I2CEN 100,100 ' Enable I2C 100 Khz 100 ms timeout
I2CSEND BMP085_I2CADDR,0,1,&hAA ' write
I2CDIS
'
I2CEN 100,100 ' Enable I2C 100 Khz 100 ms timeout
I2CRCV BMP085_I2CADDR, 0, 22, BMP085_buff(0), 1, &hAA 'write then read
I2CDIS
End Sub

SUB convert_BMP085_Constants
'Lowbyte is MSB (e.g $AA), Highbyte is LSB (e.g. $AB)
'Device stores the MSB in the Low byte, LSB in the High byte
'
'Assuming twos complement:
'read your pair of bytes, combine them into a 16 bit number as shown above,
'check if the number is equal or greater than 0x8000 (means it is negative),
'if not then treat it as positive else invert it (number XOR &HFFFF) and add
'1 and then change the sign to negative.


BMP085_AC1 = (BMP085_buff(0)*2^8) + BMP085_buff(1)
If BMP085_AC1 >= &H8000 Then
BMP085_AC1 = BMP085_AC1 Xor &HFFFF
BMP085_AC1 = BMP085_AC1 + &h1
BMP085_AC1 = BMP085_AC1 * (-1)
EndIf

BMP085_AC2 = (BMP085_buff(2)*2^8) + BMP085_buff(3)
If BMP085_AC2 >= &H8000 Then
BMP085_AC2 = BMP085_AC2 Xor &HFFFF
BMP085_AC2 = BMP085_AC2 + &h1
BMP085_AC2 = BMP085_AC2 * (-1)
EndIf

BMP085_AC3 = (BMP085_buff(4)*2^8) + BMP085_buff(5)
If BMP085_AC3 >= &H8000 Then
BMP085_AC3 = BMP085_AC3 Xor &HFFFF
BMP085_AC3 = BMP085_AC3 + &h1
BMP085_AC3 = BMP085_AC3 * (-1)
EndIf

BMP085_AC4 = (BMP085_buff(6)*2^8) + BMP085_buff(7) ' UNSIGNED <----<<<<
BMP085_AC5 = (BMP085_buff(8)*2^8) + BMP085_buff(9) ' UNSIGNED <----<<<<
BMP085_AC6 = (BMP085_buff(10)*2^8) + BMP085_buff(11) ' UNSIGNED <----<<<<

BMP085_B1 = (BMP085_buff(12)*2^8) + BMP085_buff(13)
If BMP085_B1 >= &H8000 Then
BMP085_B1 = BMP085_B1 Xor &HFFFF
BMP085_B1 = BMP085_B1 + &h1
BMP085_B1 = BMP085_B1 * (-1)
EndIf

BMP085_B2 = (BMP085_buff(14)*2^8) + BMP085_buff(15)
If BMP085_B2 >= &H8000 Then
BMP085_B2 = BMP085_B2 Xor &HFFFF
BMP085_B2 = BMP085_B2 + &h1
BMP085_B2 = BMP085_B2 * (-1)
EndIf

BMP085_MB = (BMP085_buff(16)*2^8) + BMP085_buff(17)
If BMP085_MB >= &H8000 Then
BMP085_MB = BMP085_MB Xor &HFFFF
BMP085_MB = BMP085_MB + &h1
BMP085_MB = BMP085_MB * (-1)
EndIf

BMP085_MC = (BMP085_buff(18)*2^8) + BMP085_buff(19)
If BMP085_MC >= &H8000 Then
BMP085_MC = BMP085_MC Xor &HFFFF
BMP085_MC = BMP085_MC + &h1
BMP085_MC = BMP085_MC * (-1)
EndIf

BMP085_MD = (BMP085_buff(20)*2^8) + BMP085_buff(21)
If BMP085_MD >= &H8000 Then
BMP085_MD = BMP085_MD Xor &HFFFF
BMP085_MD = BMP085_MD + &h1
BMP085_MD = BMP085_MD * (-1)
EndIf

END SUB


'----------------------------------------------------------- --------------------

SUB print_BMP085_Constants
? "BMP085_AC1",BMP085_AC1
? "BMP085_AC2",BMP085_AC2
? "BMP085_AC3",BMP085_AC3
? "BMP085_AC4",BMP085_AC4 'Unsigned?
? "BMP085_AC5",BMP085_AC5 'Unsigned?
? "BMP085_AC6",BMP085_AC6 'Unsigned?
? "BMP085_B1", BMP085_B1
? "BMP085_B2", BMP085_B2
? "BMP085_MB", BMP085_MB
? "BMP085_MC", BMP085_MC
? "BMP085_MD", BMP085_MD
END SUB
'----------------------------------------------------------- --------------------


SUB BMP085_Derived_Calib_Data
BMP085_c3 = 160*2^-15*BMP085_AC3
'? "BMP085_c3 = ", BMP085_c3
BMP085_c4 = 10^-3*2^-15*BMP085_AC4
'? "BMP085_c4 = ", BMP085_c4
BMP085_b1 = 160^2*2^-30*BMP085_B1
'? "BMP085_b1 = ", BMP085_b1

BMP085_c5 = 2^-15/160*BMP085_AC5
'? "BMP085_c5 = ", BMP085_c5
BMP085_c6 = BMP085_AC6
'? "BMP085_c6 = ", BMP085_c6
BMP085_mc = 2^11/160^2*BMP085_MC
'? "BMP085_mc = ", BMP085_mc
BMP085_md = BMP085_MD/160
'? "BMP085_md = ", BMP085_md

BMP085_x0 = BMP085_AC1
'? "BMP085_x0 = ", BMP085_x0
BMP085_x1 = 160*2^-13*BMP085_AC2
'? "BMP085_x1 = ", BMP085_x1
BMP085_x2 = 160^2*2^-25*BMP085_B2
'? "BMP085_x2 = ", BMP085_x2

BMP085_y0 = BMP085_c4*2^15
'? "BMP085_y0 = ", BMP085_y0
BMP085_y1 = BMP085_c4*BMP085_c3
'? "BMP085_y1 = ", BMP085_y1
BMP085_y2 = BMP085_c4*BMP085_b1
'? "BMP085_y2 = ", BMP085_y2

BMP085_p0 = (3791-8)/1600
'? "BMP085_p0 = ", BMP085_p0
BMP085_p1 = 1-(7357*2^-20)
'? "BMP085_p1 = ", BMP085_p1
BMP085_p2 = 3038*100*2^-36
'? "BMP085_p2 = ", BMP085_p2
END SUB
'----------------------------------------------------------- --------------------

SUB init_BMP085
'call I2C constants only once! <-------------<<<<< Call this first!
read_BMP085_Constants
convert_BMP085_Constants
'print_BMP085_Constants' - before derived cal.
BMP085_Derived_Calib_Data
'print_BMP085_Constants' - after derived cal.
END SUB
'----------------------------------------------------------- --------------------

SUB cal_BMP085_Temperature ' <----------<<<<<< Always call this second!
read_BMP085_Raw_Temp
'compute temp
BMP085_a = BMP085_c5*(BMP085_tu - BMP085_c6)
BMP085_T = BMP085_a + (BMP085_mc / (BMP085_a + BMP085_md))
BMP085_Tc = BMP085_T
'? "BMP085_Tc degrees C = ", BMP085_Tc
BMP085_Tf = 1.8 * BMP085_T + 32
'? "BMP085_Tf degrees F = ", BMP085_Tf
'? " "
END SUB

'----------------------------------------------------------- --------------------
SUB cal_BMP085_Pressure
'used by altitude, weather calculations
'Get BMP085 temp first - for the pressure cal <----<<<<
cal_BMP085_Temperature
'
'For ref. only
'BMP085_ULTRALOWPOWER 0
'BMP085_STANDARD 1
'BMP085_HIGHRES 2
'BMP085_ULTRAHIGHRES 3
'
'USE ONLY ONE ! Comment the other out !
'
'read_BMP085_Raw_Pres BMP085_ULTRALOWPOWER ' User selectable SELECT ONLY ONE <------<<<<<
'read_BMP085_Raw_Pres BMP085_STANDARD ' User selectable SELECT ONLY ONE <------<<<<<
'read_BMP085_Raw_Pres BMP085_HIGHRES ' User selectable SELECT ONLY ONE <------<<<<<
read_BMP085_Raw_Pres BMP085_ULTRAHIGHRES ' User selectable SELECT ONLY ONE <------<<<<<

'
' Compute pressure
BMP085_s = BMP085_T - 25
'? "BMP085_s = ", BMP085_s
BMP085_x = BMP085_x2*BMP085_s^2 + BMP085_x1*BMP085_s + BMP085_x0
'? "BMP085_x = ", BMP085_x
BMP085_y = BMP085_y2*BMP085_s^2 + BMP085_y1*BMP085_s + BMP085_y0
'? "BMP085_y = ", BMP085_y
'These two factors are now used to compute an initial pressure value, BMP085_z:
BMP085_z = (BMP085_pu - BMP085_x) / BMP085_y
'? "BMP085_z = ", BMP085_z
'A polynomial in BMP085_z gives the final corrected pressure value.
BMP085_P = BMP085_p2*BMP085_z^2 + BMP085_p1*BMP085_z + BMP085_p0
'? "BMP085_P millibars = ", BMP085_P ' <-----------------------------<<<<<< In millibars!
END SUB
'----------------------------------------------------------- --------------------

SUB Compute_BMP085_pressure
'Needs derived constants and temperature <------<<<<
BMP085_s = BMP085_T - 25
'? "BMP085_s = ", BMP085_s
BMP085_x = BMP085_x2*BMP085_s^2 + BMP085_x1*BMP085_s + BMP085_x0
'? "BMP085_x = ", BMP085_x
BMP085_y = BMP085_y2*BMP085_s^2 + BMP085_y1*BMP085_s + BMP085_y0
'? "BMP085_y = ", BMP085_y
'These two factors are now used to compute an initial pressure value, BMP085_z:
BMP085_z = (BMP085_pu - BMP085_x) / BMP085_y
'? "BMP085_z = ", BMP085_z
'A polynomial in BMP085_z gives the final corrected pressure value.
BMP085_P = BMP085_p2*BMP085_z^2 + BMP085_p1*BMP085_z + BMP085_p0
'? "BMP085_P millibars = ", BMP085_P ' <-------<<<<<< In millibars!
END SUB
'----------------------------------------------------------- --------------------

SUB check_BMP085_OSS_Modes
Local avg,idx
'
read_BMP085_Constants
convert_BMP085_Constants
BMP085_Derived_Calib_Data
'
cal_BMP085_Temperature
read_BMP085_Raw_Pres BMP085_ULTRALOWPOWER
? "<BMP085 Pressure ULTRALOWPOWER Mode>"
? "Raw Pressure - BMP085 1 sample = ", raw_pres
Compute_BMP085_pressure
? "BMP085_P millibars hPa = ", BMP085_P
? " "

cal_BMP085_Temperature
read_BMP085_Raw_Pres BMP085_STANDARD
? "<BMP085 Pressure STANDARD Mode>"
? "Raw Pressure - BMP085 2 samples = ", raw_pres
Compute_BMP085_pressure
? "BMP085_P millibars hPa = ", BMP085_P
? " "

cal_BMP085_Temperature
read_BMP085_Raw_Pres BMP085_HIGHRES
? "<BMP085 Pressure HIGHRES Mode>"
? "Raw Pressure - BMP085 4 samples = ", raw_pres
Compute_BMP085_pressure
? "BMP085_P millibars hPa = ", BMP085_P
? " "

cal_BMP085_Temperature
read_BMP085_Raw_Pres BMP085_ULTRAHIGHRES
? "<BMP085 Pressure ULTRAHIGHRES Mode>"
? "Raw Pressure - BMP085 8 samples = ", raw_pres
Compute_BMP085_pressure
? "BMP085_P millibars hPa = ", BMP085_P
? " "

' Special MaxiMite Average Sample Mode
' blocks of 8 samples are averaged 75 times (600 samples)
' 26 ms/ 8 block * 75 = ~ 2 seconds
avg = 0
FOR IDX = 1 TO 75
cal_BMP085_Temperature
read_BMP085_Raw_Pres BMP085_ULTRAHIGHRES
Compute_BMP085_pressure ' Millibars
avg = avg + BMP085_P
NEXT
avg = avg/75
? "MaxiMite BMP085 (600 samples) millibars hPa = ", avg
? " "

END SUB
'----------------------------------------------------------- --------------------
SUB cal_Altitude
local Pres_x, sealevel_pres, cal_constant
sealevel_pres = 101325 ' Pascals <----- Fixed constant ?
cal_constant = 0 ' 0 millibars
' convert millibars or hectorPascals to Pascals

Pres_x = (BMP085_P - cal_constant) * 100 ' millibars to Pascals
' In meters
'BMP085_altitude_M = 44330 * (1.0 - ((Pres_x /sealevel_pres)^ 0.1903))
'better precision
BMP085_altitude_M = 44330 * (1.0 - ((Pres_x /sealevel_pres)^ 0.190294957184))
'? "BMP085 alt. M = ", BMP085_altitude_M
'
' In feet
BMP085_altitude_F = BMP085_altitude_M * 3.2808399
'? "BMP085 alt. F = ", BMP085_altitude_F
'? " "
END SUB
'----------------------------------------------------------- --------------------

SUB cal_Weather
Local ePressure_Pa, weatherDiff, BMP085_Pa, cal_constant
cal_BMP085_Pressure ' get pressure (in millibars/hectorPascals)
cal_Altitude
cal_constant = 0 ' 0 millibars
BMP085_Pa = (BMP085_P - cal_constant) * 100 ' Convert to Pascals
ePressure_Pa = BMP085_Pa * (1.0 - ((BMP085_altitude_M / 44330)^ 5.255)) ' In meters and Pascals
weatherDiff = BMP085_Pa - ePressure_pa

? "BMP085 Weather BMP085_Pa = ",BMP085_Pa
? "BMP085 Weather ePressure Pa = ",ePressure_Pa
? "BMP085 Weather Diff. Pa = ",weatherDiff

if(weatherDiff > 250) then
?"Sunny!"
ELSEIF ((weatherDiff <= 250) OR (weatherDiff >= -250)) THEN
?"Partly Cloudy"
ELSEIF if (weatherDiff > -250) THEN
?"Rain"
ENDIF
END SUB

'----------------------------------------------------------- --------------------
'----------------------------------------------------------- --------------------
SUB read_BMP085
'Init Bmp085
'call I2C constants only once!
? "<BMP085 Constants>"
read_BMP085_Constants
convert_BMP085_Constants
print_BMP085_Constants
? " "
? "<BMP085 Derived Constants>"
BMP085_Derived_Calib_Data
print_BMP085_Constants
? " "
cal_BMP085_Pressure ' calls temperature first for pressure compensation
? "<BMP085 Temperature>"
? "BMP085_Tc degrees C = ", BMP085_Tc
? "BMP085_Tf degrees F = ", BMP085_Tf
? " "
? "<BMP085 Pressure>"
? "BMP085_P millibars hPa = ", BMP085_P ' Millibars
? "BMP085_P Pascals = ", BMP085_P * 100
? " "
? "<BMP085 Altitude>"
cal_altitude ' Needs sea level pressure and BMP085 Pa pressure
? "BMP085 Alt. M = ", BMP085_altitude_M
? "BMP085 Alt. F = ", BMP085_altitude_F
? " "
? "<BMP085 Weather>"
cal_weather ' Needs altitude. Crude but needs more precision
END SUB
'----------------------------------------------------------- --------------------
'----------------------------------------------------------- --------------------

END ' end of program

 
DuinoMiteMegaAn
Senior Member

Joined: 17/11/2011
Location: Australia
Posts: 231
Posted: 06:40pm 12 Mar 2012
Copy link to clipboard 
Print this post

FYIO ... Altitude Testing

What is your altitude? You need to know this when working with the BMP085.

Since I have an airport 500 meters away on flat ground, I took their readings.
Elevation 902 feet.

Another way to check altitude use Google Earth or this link
http://www.daftlogic.com/sandbox-google-maps-find-altitude.h tm
Google Earth produced 896 feet.
Google Maps produced 896.363 feet

I used my handheld GPS and it showed 1000 feet?. <------ Do not use this reference!
GPS are NOT known by their precision altitude readings/calculations!

Sparkfun shows an error of 69 feet and I showed an error of 105 feet. <--- edited
I just added/installed a "very small" calibration offset in the software.
Edited by DuinoMiteMegaAn 2012-03-14
 
BobD

Guru

Joined: 07/12/2011
Location: Australia
Posts: 935
Posted: 07:44pm 12 Mar 2012
Copy link to clipboard 
Print this post

after I gave you info on twos complement recently I was looking at the method and thought it can be done easier. Your code, much as I suggested,
BMP085_AC1 = (BMP085_buff(0)*2^8) + BMP085_buff(1)
If BMP085_AC1 >= &H8000 Then
BMP085_AC1 = BMP085_AC1 Xor &HFFFF
BMP085_AC1 = BMP085_AC1 + &h1
BMP085_AC1 = BMP085_AC1 * (-1)
EndIf

may be simplified as the following:
BMP085_AC1 = (BMP085_buff(0)*2^8) + BMP085_buff(1)
If BMP085_AC1 >= &H8000 Then
BMP085_AC1 = BMP085_AC1 - 65536
EndIf

This includes the correct sign. The general formula is (number - 2^n) where n is the number of bits in "number". So for 16 bit negative TC numbers subtract 2^16 which is &H10000 or 65536.
 
DuinoMiteMegaAn
Senior Member

Joined: 17/11/2011
Location: Australia
Posts: 231
Posted: 07:52pm 12 Mar 2012
Copy link to clipboard 
Print this post

@BobD - Thanks for the reduced code algorithm for 2's complement. That got me
over the hump until I "hit the wall" with the two complex formulas for altitude and weather calculations.


altitude
BMP085_altitude_M = 44330 * (1.0 - ((Pres_x /sealevel_pres)^ 0.190294957184))


weather
ePressure_Pa = BMP085_Pa * (1.0 - ((BMP085_altitude_M / 44330)^ 5.255))


See anything obvious that is wrong?
Ref. Sparkfun Device BMP085 (quickstart tutorial)Edited by DuinoMiteMegaAn 2012-03-14
 
BobD

Guru

Joined: 07/12/2011
Location: Australia
Posts: 935
Posted: 04:26am 13 Mar 2012
Copy link to clipboard 
Print this post

  DuinoMiteMegaAn said   @BobD - Thanks for the reduced code algorithm for 2's complement. That got me
over the hump until I "hit the wall" with the two complex formulas for altitude and weather calculations.


altitude
BMP085_altitude_M = 44330 * (1.0 - ((Pres_x /sealevel_pres)^ 0.190294957184))


weather
ePressure_Pa = BMP085_Pa * (1.0 - ((BMP085_altitude_M / 44330)^ 5.255))


See anything obvious that is wrong?
Ref. Sparkfun Device BMP085 (quickstart tutorial)

Andy
I wouldn't have thought that the revised TC stuff was over the hump material. Are you struggling with free memory?

What problems do you have now?

The exponent in the altitude calculation may run into loss of accuracy problems. It will probably get truncated. I would be inclined to use 0.1903 instead. Just looked at your code and you are already there. I'm no help there.

If you need a way to look at your intermediate results you could try this bit of code
SUB Wait
? +++++++++++++++++++++
? ' print any variables that may be important
? " Press any key to continue > ";
DO
LOOP UNTIL INKEY$ <> ""
END SUB

when you want to use it just include a WAIT in your program and edit the SUB to print the variables. The ++++++s are just used as markers to indicate that it is not usual program output. They can be left out.
 
DuinoMiteMegaAn
Senior Member

Joined: 17/11/2011
Location: Australia
Posts: 231
Posted: 10:16am 13 Mar 2012
Copy link to clipboard 
Print this post

What I was asking if both forumulas "matched" in format the formuluas by sparkfun and by Bosch?

The weather algorithm produced 0 differential? Looking at the weather calculation, I had to insert a "fixed" value for the altitude and replaced BMP085_Pa with the pressure at sea level eg 101325 Pa. by doing so, the "epressure_Pa" seems to always stay around at 101325. The formula seems "not to change" but it gives the needed diff. "leg" for the epressure_Pa difference.

SUB cal_Weather

' algorithm fix - the differential was always zero because the altitude was variable not fixed.
' epressure calculation should have sealevel Pa!

Local ePressure_Pa, weatherDiff, BMP085_Pa, cal_constant, fixed_user_altitude_M
cal_BMP085_Pressure ' get pressure (in millibars/hectorPascals)
'cal_Altitude <--- do not use - for ref. only

fixed_user_altitude_M = 273.1 ' <-----<<<<< Local user altitude in meters

cal_constant = 0 ' 0 millibars - for calbibration if needed.


ePressure_Pa = 101325 * (1.0 - ((fixed_user_altitude_M / 44330)^ 5.255)) ' In meters and Pascals

BMP085_Pa = (BMP085_P - cal_constant) * 100 ' Convert to Pascals with cal constant

weatherDiff = BMP085_Pa - ePressure_pa

? "BMP085 Weather BMP085_Pa = ",BMP085_Pa
? "BMP085 Weather ePressure Pa = ",ePressure_Pa
? "BMP085 Weather Diff. Pa = ",weatherDiff

if(weatherDiff > 250) then
?"Sunny!"
ELSEIF ((weatherDiff <= 250) OR (weatherDiff >= -250)) THEN
?"Partly Cloudy"
ELSEIF if (weatherDiff > -250) THEN
?"Rain"
ENDIF
END SUB



Are you struggling with free memory?


Yes, but the workaround is to run "blocks of code" from the SD drive which has 16 GB. Edited by DuinoMiteMegaAn 2012-03-14
 
DuinoMiteMegaAn
Senior Member

Joined: 17/11/2011
Location: Australia
Posts: 231
Posted: 02:20pm 13 Mar 2012
Copy link to clipboard 
Print this post

Weather calculation

This code snippet is still wrong!
ePressure_Pa = 101325 * (1.0 - ((fixed_user_altitude_M / 44330)^ 5.255))



Sparkfun weather calculation.

ePressure_Pa = 101325 * (1 - fixed_user_altitude_M / 44330)^ 5.255 ' In meters and Pascals

The formula recomputes what the barometric pressure should be at a given elevation.
At sea level (101325 Pa) the elevation is 0 meters so the ref. is 101325 Pa.
At higher elevations the pressure decreases so at my elevation (273.1 meters) the calculated air pressure reference (for weather) is 98087.409 Pa.

Using the above calcuation they read the present barometric pressure to get the difference between the two values to compute the projected weather. <----- very cool

So the correct weather formula is

ePressure_Pa = 101325 * (1 - fixed_user_altitude_M / 44330)^ 5.255 ' In meters and Pascals

 
DuinoMiteMegaAn
Senior Member

Joined: 17/11/2011
Location: Australia
Posts: 231
Posted: 12:59am 14 Mar 2012
Copy link to clipboard 
Print this post

I read the Sparkfun and Adafruit tutorials on the BMP085 and they left out some important points.

<BMP085 Q&A>

1. Why doesn't the RAW BMP085 Barometric pressure reading match the local weather station?

Note: In most cases the local weather station will read higher (lower elevation) than the RAW pressure BMP085 reading. In my case, 32 millibars lower for 273.1 meters in elevation for my location.

Note: The BMP085 is good for +- 2 millibars.

All weather stations in the US and other countries? uses sea level as the pressure reference. This means, what you see from a weather station is without the change in pressure due to elevation changes.You can go from one weather station to the next and they keep the same pressure reference without changes elevation pressure.
Note: The pressure at sea level is 101325 Pa and the pressure goes down when there is an increase in elevation.(Air pressure is lighter [less pressure] at higher elevations)

To use the BMP085 as a true weather indicator you will need to add a calibration offset to the raw BMP085 pressure reading. By doing so, you are removing "your offset" due to elevation height. This way it will track other area professional weather station readings.

If you don't have a weather station close by to calibrate the BMP085 then use this website link:
http://www.csgnetwork.com/barcorrecthcalc.html
You need to know your exact elevation (in feet or meters) to add their factor for your BMP085 pressure calibration. Do not use a GPS to determine your elevation!

Please note: Sparkfun used the raw (uncalibrated) BMP085 pressure for weather prediction calculations. This is fine and will work but beware it will not match other area professional weather station readings without this calibration offset added.

2. Why doesn't the BMP085 / Sparkfun elevation calculation match the elevation at your location? If it does, consider yourself extremely lucky. This means the weather conditions, temperature, humidity at your location and at sea level is perfect!

The Sparkfun altitude calculation uses a fixed sea level pressure (101325 Pa). This is fine but the weather, temperature and humidity at sea level and at your location is not always perfect. For better precision you need to find out the pressure at sea level for your location "area". Website link:

http://aviationweather.gov/adds/metars/
select Metars
enter your 4 letter airport station iden. example "KOSU"
select translated - get the exact sea level, for the area.(Used by pilots)
This pressure is due to weather changes at sea level

Note: Australians need to find a similiar website that calculates the sea level pressure to put in the altitude calculation (for your country)

Enjoy


Edited by DuinoMiteMegaAn 2012-03-15
 
BobD

Guru

Joined: 07/12/2011
Location: Australia
Posts: 935
Posted: 01:20am 14 Mar 2012
Copy link to clipboard 
Print this post

The Australian Bureau of Meteorology gives these stats. Here is my local weather station and an explanation of terms can be found on that page (and many others) if you click on the link About weather observations . The columns of interest are the second and third from the right. The altitude is shown on the page.

Other weather stations in Victoria can be found here and if you want other states then look around. They are easily found.

One thing that confuses me is the obs at Falls Creek which is a lot higher than Yarrawonga, show a higher pressure reading. ??????
 
Print this page


To reply to this topic, you need to log in.

© JAQ Software 2024