2014年7月1日 星期二

如何使用 Borch BMP180 數位氣壓感測器模組計算溫度、大氣壓力與海拔高度 ?

Borch BMP180 數位氣壓感測模組可至露天賣場訂購:
Borch BMP180 Digital Barometric Pressure Sensor, source: http://www.bosch-sensortec.com/
在這篇網頁,我們將說明如何使用 I2C 通訊方式取得 BMP180 裡的溫度與壓力的原生資料 ( raw data ),並藉由晶片內部存放在 EEPROM 裡的 11 個校正係數,計算出氣壓模組現處環境的溫度 ( 真實溫度 ) 與大氣壓力 ( 真實壓力 )。微處理器間的電路接線與程式測試,請參考後續的部落格網頁中的說明。

由於高度不同產生的大氣壓力也不同,所以由 BMP180 所計算出來的壓力和溫度值,可以用來計算出現處環境的海拔高度作為 "高度計" 使用,但前提是:海平面的壓力必須清楚得知 !

得到高度可以做什麼 ? GPS 導航時,若沒有高度計,上下橋就不知道是在橋上或是橋下;做室內導航時,就不知道現在是在一樓還是在二樓。這些都只是其中的一些應用,所以根據官網以及網路上的資料, BMP180 可以應用在下面的用途上:
  • 加強 GPS 精確導航能力 ( 航位推算,坡度 ( 上下橋 ) 檢測等 ) 
  • 室內與室外導航 
  • 休閒、體育和醫療健康等監測
  • 天氣預測
  • 垂直速度指示 ( 上升 / 下降速率 ) 
  • 風扇轉速控制 ( 利用溫度值 )
相關連結 1:
下面的連結中有 BMP180 的簡介與相關資料,對於接下來網頁中的說明有所幫助,可以打開在一邊以便隨時查閱

ps. BMP180 數位感測器模組的測試,賣場提供了 AT89S52、Arduino 和 Raspberry Pi ( 樹莓派 )四支測試程式,內容可以互相參照,但本篇網頁寫作內容,會跟 Raspberry Pi 所撰寫的程式碼契合度比較高,可作為了解程式撰寫流程的輔助。


BMP180 量測流程:

BMP178 資料手冊的 Page 11, 3.3 Measurement of pressure and temperature,說明了 BMP180 溫度與壓力取值的過程,我補充了一些東西在流程圖旁邊,這些箭頭與方塊說明了取值的細節部分,分述如下:

BMP180 量測流程圖加強版


在繼續下個溫度與大氣壓力的計算說明之前,先離題一下,討論一下我們等一下會用到的暫存器,循序漸進的方式會比較容易了解。

BMP180 的暫存器:

BMP180 使用的暫存器多是讀取功能,控制型的暫存器的設定與操作並不複雜很容易上手,在實際操作之前,我們先來看看 BMP180 各暫存器的對應圖,您可以翻閱到資料手冊的 Page 18。
BMP180 記憶體對應圖
由上圖不難看出,只有七個欄位,扣掉唯讀的暫存器 ( out_xlsb, out_lsb, out_msb, id, calib21 down to calib0 ),真正需要注意以及程式寫作要注意的就是 ctrl_meas 暫存器;而 soft_reset 是用來重置晶片用的,我沒用到!所以沒定義這個暫存器在檔案裏面,如果有需要用到再自己加上這暫存器的定義在程式碼裡面;id 暫存器,就是下面 * Hello BMP180 用來確認通訊的暫存器。


* Hello BMP180:

在整個量測流程開始之前,我們必須確認 BMP180 晶片與控制器 ( 或微處理器、或是系統 ) 是否已經連線 ?

如果使用樹莓派 ( Model B, Rev 2.0 ) 可以使用 i2ctoos 的指令

sudo i2cdetect -y 1

Rev1.0 使用 sudo i2cdetect -y 0

先得到 BMP180 的 I2C 位址:0x77

得到 BMP180 的 I2C 位址後,就可以在程式碼裡面加入讀取其暫存器 0xD0 的數值,而讀取回來的數值一定是 0x55 ,以確認晶片與控制器之間在後續的操作過程中的通訊是否可正常作用;如 Page 18 中所描述。


* 校正係數 ( Calibration Coefficients ):

接著,在計算現處環境的溫度與大氣壓力前,我們必須先取得晶片的校正係數,這些係數對於每一顆 BMP180 晶片都是獨立且不相同的,共有 11 個,每一個占據兩個位元組 ( Byte ),因此對於一個係數,一次必須讀取兩個位元組的資料之後再做移位運算,得出係數真實值。

有沒發現在流程圖中,為什麼在同一個區塊中畫了兩個方塊 ?

這是因為,溫度與壓力的計算是非常攏長的,為了避免程式碼的撰寫讓計算出現錯誤,導致結果出錯,因此我們需要一組虛擬的校正係數與原生溫度與壓力值作為計算參考的依據,才能知道所撰寫的程式碼是不是能正確地計算最終的結果,或是知道哪裡的計算出了問題  ? 這在程式一開始撰寫時的除錯非常有用 ( 雖然完成之後這些程式碼就顯得沒用 ),因此在樹莓派與 AT89S52 的程式碼中加入這個可切換的選項,在資料手冊的 Page 15 提供了這樣的資料。如何在程式碼中啟用這功能,請參考各範例的說明網頁。

上面方塊中所定義的符號 ( AC1, AC2, ... , MD 等 ),就是溫度與大氣壓力計算中所會用到的係數,每個係數占據兩個八位元 ( 8-bit ) 的資料,所以取得的參數必須做結合,前面的暫存器是高位元組,緊接著後面一個是低位元組,以取得 AC1 為例

AC1 = ( *0xAA << 8 ) + *0xAB ;

408 = (  0x01 << 8 ) +  0x98 ;

左邊方塊最下面的 MODE 不是係數,這是 oss ( Over-Sampleing Setting ) 的模式設定,我們在計算大氣壓力時會用到,到時再講。


* 計算現處環境的溫度值 ( calculate true temperature )

要計算現處環境的溫度之前,我們必須告訴控制暫存器 ( 0xF4 ) 我們等一下要去讀取原生溫度 ( 也就是未經過補償的溫度 ) UT,所以要寫入數值 0x2E 到控制暫存器裡面去,然後等待 4.5 ms 的時間之後,就可以從暫存器位址 0xF6 0xF7 分別讀取高位元組 ( MSB ) 和低位元組 ( LSB ) 的資料出來;如果使用資料手冊上的值,這時的 UT = 278998 。

取得 BMP180 溫度原生資料 ( Raw Temperature Data )  UT 的流程
取得 UT 再配合校正係數 ( AC5、AC6、B5、MC 和 MD ) 就可以計算出現處環境的溫度。

記住 ! 在單晶片裡使用浮點數做運算,編譯後的燒錄檔檔案大的很快,為了要能夠顯示溫度、大氣壓力與計算海拔高度在 LCD 上,不得已將 AT89S51 換成 AT89S52 大一倍的 RAM 和 Flash 記憶體,如果只需要計算溫度以及壓力,AT89S51 是足夠用的;而 Arduino 因為使用 Serial Port 輸出數據,因此現在沒這問題。

打開資料手冊上的 Page 15,由左邊的流程圖往下看,直到看到方塊的標題是 " calculate true temperature " 停下來看那方塊裡的計算公式,並對照下面相對應的程式碼  ( 我將一些資料型態轉換和不需要的部分去除掉,避免干擾!詳細的程式撰寫請參照賣場附的程式碼  ) ,其中我們將 line 3 最後一個計算式 215 不寫成 pow( 2, 15 ),而改寫成將前面計算出來的成果向右移 15 次,這就等同於將前面的計算式做 15 次 除以 2 的運算,但這執行速度卻會變快許多且記憶體也會減少使用的大小。

在接下來的計算中,會時常看到這些往左或是往右移的符號,請習慣用這來做 2 的次方乘法或是除法。

1     
2     // Temperature compensation
3     X1 = ( UT - AC6 ) * AC5 >> 15;
4     X2 = ( MC << 11 ) / ( X1 + MD );
5     B5 = X1 + X2;
6  
7     temperature = (( B5 + 8 ) >> 4 ); // Temperature in 0.1 degC
8  

line 7 是計算出來的結果,所得到的數據  ( 單位是 0.1 °C ) 會比實際溫度值大 10 倍,不過會是個整數值,將其除以 10 就會是讀起來較順的溫度數值大小,是現處環境的溫度也可稱為真實溫度。

上面計算過程所得到的 X1、X2 B5 ( line 3 ... line 5 ) 會用在下面計算現處環境的大氣壓力上。


* 計算現處環境的大氣壓力值 ( calculate true pressure )

計算現處環境大氣壓力的流程與溫度流程差不多,但是需要多取一個原生壓力 ( 也就是未經過補償的大氣壓力 ) UP,並且將溫度計算中所得出的 X1、X2B5 結果,配合 UP 繼續往下計算,就可以得到現處環境的大氣壓力值。



要取得大氣壓力原生資料前,程式必須向 BMP180 的暫存器 0xF4 告知要使用哪個壓力量測模式 ( 又稱 oversampling_setting ( oss ) )。oss 值不只與轉換的時間長短有關係,也跟取樣次數、功率消耗和數值解析度有關係,使用者可以依自己的考量選用不同的 oss,更詳細的表格描述請參考資料手冊的 Page 12。

不同 oversampling_setting ( oss ) 所對應的暫存器的值
Measurement
Control register value
( register adress 0xF4 )
Max. conversion time
[ ms ]
Temperature 0x2E 4.5
Pressure
( oss = 0 )
0x34 4.5
Pressure
( oss = 1 )
0x74 7.5
Pressure
( oss = 2 )
0xB4 13.5
Pressure
( oss = 3 )
0xF4 25.5

一旦取樣的模式決定之後,就送出數值到暫存器 ( 例如範例測試程式是使用 oss = 0,就是寫入 0x34 到暫存器 0xF4 去 ),流程圖中的算式可以對應到不同的 oss 模式所需要寫入到暫存器的數值。

每一種 oss 模式會有不同的處理時間,因此我們必須要等待至少 2 + ( 3 >> oss ) milisecond 才可以讀取 0xF6 ... 0xF8 這三個暫存器裡的值,讀出來的值經過移位運算、相加再做模式移位運算,就可得到原生大氣壓力值 UP

取得 BMP180 大氣壓力原生資料 ( Raw Temperature Data )  UP 的流程
結合 UT 、 UP 和使用者所選用的 oss 模式就可以開始做運算  ( 我將一些資料型態轉換和不需要的部分去除掉,避免干擾!詳細的程式撰寫請參照賣場附的程式碼  ) ,運算如下:


 1     
 2     // Pressure compensation
 3     B6 = B5 - 4000;
 4     X1 = ( B2 * ( ( B6 * B6 ) >> 12 ) ) >> 11;
 5     X2 = ( AC2 * B6) >> 11;
 6     X3 = X1 + X2;
 7     B3 = ( ( ( (AC1 * 4) + X3 ) << oss ) + 2) / 4;
 8     
 9     X1 = ( AC3 * B6 ) >> 13;
10     X2 = ( B1 * ( ( B6 * B6 ) >> 12 ) ) >> 16;
11     X3 = ( ( X1 + X2 ) + 2 ) / 4.0 ;
12     B4 = ( AC4 * ( X3 + 32768 ) ) >> 15;
13     B7 = ( UP - B3 )  * ( 50000 >>  oss ) );
14     
15     if( B7 < 0x80000000 )
16     {
17         P = ( B7 << 1 ) / B4;
18     }
19     else
20     {
21         P = ( B7 / B4 ) << 1;
22     }
23     
24     X1 = ( P >> 8 ) * ( P >> 8 );    
25     X1 = ( X1 * 3038 ) >> 16;
26     X2 = ( -7357 * P ) >> 16;
27  
28     pressure = P + ( ( X1 + X2 + 3791 ) >> 4 )) / 100.0; // pressure in hPa
29  

上面的運算式就是計算現處環境大氣壓力的計算公式,這是依照資料手冊上所提供而來的,line 18 就是計算之後的結果,因為計算海拔高度是使用 hPa 做輸入,因此所計算出來的現處環境大氣壓力除以 100 轉換單位由 Pa 至 hPa。


* 海拔高度的計算

BMP180 常應用在計算海拔高度,而計算海拔高度可以使用資料手冊在 Page 16 所供的數學公式,不過我不打算跟進,我用另一個公式,將溫度納入計算海拔高度裡。所以,在這公式我們會使用到溫度、壓力 還有最重參考基準壓力:海平面壓力 ( Sea Level Pressure ),我在程式中將其定義為 1013.25 hPa,但這它會因為一些外在環境的變化並不是一個固定值,不過若只是要比較高度變化,倒是影響不大 !

但若是作為氣象站,海平面壓力若是固定一個值,你 ( 妳 ) 就會看到高度值不是維持在一個值,看一下高度值的公式:

其中,
  • h:海拔高度 ( Meter, 公尺 )
  • P0:海平面壓力 ( hPa, 百帕斯卡 )
  • P:大氣壓力  ( hPa, 百帕斯卡 ),現處環境的大氣壓力值
  • T:溫度 ( 攝氏溫度, °C )
所以今天看到的高度與明天看到的高度,就會因為程式中將海平面壓力作為固定值,而造成計算之後的高度有所變化,一般在同一個地點,高度值是不應該造成變化的!哪去哪裡找當地的海平面壓力呢 ? 可以利用下面所提供的資料 ( 如何尋找當地海平面壓力 ),跳一下 !


如何尋找當地海平面壓力 ?
在坐飛機的時候常會聽到機長廣播一些天氣的資料,這對於飛機在航行時很重要,這些資料來自於"航空力行天氣報告" ( METAR ),飛行員與航管員會用它來評估機場天氣狀況,但詳細的細節不用去討論 ( 請看 WiKi:航空例行天氣報告 和 剖析機場天氣報告(METAR/SPECI)電碼的意義,有些名詞下面會用到,有問題再到上面網址找一下資料 ),只要參考的海平面壓力。

另開新網頁,打開這個網址:http://www.aviationweather.gov/
台灣高雄 METAR,  from Aviation Weather Center, Aciation Weather Overview
第一次打開應該是顯示美國那邊的地圖。若要看到像上圖一樣,用滑鼠按住畫面往右移動幾次就會看到,使用滾輪往前就會放大圖示。台灣只顯示兩個點:一個在台北,一個在高雄( 高雄這一點要放大之後才會看到 )。因為我居住的地方離高雄比較近,因此點一下台灣圖示下面那個點 ( RCKH ),就會出現一個小視窗將 METAR 的資料列出來 ( 若要了解這些資料的意思,就進入 剖析機場天氣報告(METAR/SPECI)電碼的意義 網站看 ),其中 Q1002 代表 QNH ( 高度表撥定值以海平面為基點 ) 1002 hPa,這就是我們所要的海平面壓力。

我們可以在網頁的左上角 ( 黃色位置 ) 輸入 RCKF kaohsiung,就會進入到另一個詳細的天氣預測的網頁,下圖黃色的部分就是與上面一樣是我們要的海平面壓力資料。
台灣高雄 METAR,  from Aviation Weather Center, Acviation information and Forcast
我沒去特別研究如何能夠即時從網路得到海平面壓力的資料,但找一下做天氣預報方面的,裡面應該會有資料可以做參考!


如下,將公式轉成程式碼,回傳 line 2 整段計算的結果,就是海拔高度。


1     
2((pow((seaLevel/atmospheric), 0.190223F) - 1.0F) * (temp + 273.15F)) / 0.0065F;
3 


* 計算海平面壓力與現處環境大氣壓力

利用海拔高度計算的公式,做一下的移項就可以得到下面計算海平面壓力與大氣壓力兩個公式






上面這兩個公式在 BMP180 所附的樹莓派程式碼裡面有 ( 其餘的只有計算海拔高度的公式 ),使用者可以自行移植到其他控制器上


 1 /*====== Altitude to pressure
 2 --------------------------------------------------------------------------*/
 3 float altitudeToPressure( float altitude, float sealevelpressure, float temp )
 4 {
 5     // Hyposometric formula:                      
 6     //                                            
 7     // where: h   = 高度 (公尺)                   
 8     //        P0  = 海平面壓力 (百帕)             
 9     //        P   = 現在測得的大氣壓力氣壓 (百)   
10     //        T   = temperature ( degC )          
11     
12     return (float)pow(((0.0065 * altitude) / (temp + 273.15)) + 1, -0.190223F) * sealevelpressure;    
13 }
14 
15 /*====== Sea level pressure
16 --------------------------------------------------------------------------*/
17 float seaLevelPressure( float altitude, float atmospheric, float temp )
18 {
19     // Hyposometric formula:                      
20     //                                          
21     // where: h   = 高度 (公尺)                 
22     //        P0  = 海平面壓力 (百帕)           
23     //        P   = 現在測得的大氣壓力氣壓 (百) 
24     //        T   = temperature ( degC )        
25 
26     return (float)pow(((0.0065 * altitude) / (temp + 273.15)) + 1, 0.190223F) * atmospheric;
27 }
28  


以上所說明的就是 BMP180 數位氣壓感測器的溫度、壓力與計算海拔高度的流程與方法,對於手邊有 BMP085 晶片的同樣也適用。

若您有購買賣場這項商品的,接下來就是跳至部落格其他網頁,了解如何在 Arduino、AT89S52 與樹莓派測試與使用 BMP180 數位氣壓感測器。


<< BMP180 數位氣壓感測器系列文章 >>
  • 使用 N-Channel MOSFET 做 I2C 電壓準位轉換電路
  • 簡易但是很好用的 3V3 <--> 5V,  I2C 電壓準位 ( Level Shifter ) 轉換電路,這電路會用在 BMP180 與單晶片、Arduino 或是任何 3V3 系統程式測試上。

  • BMP180 模組使用提示 - 單晶片接線與程式測試
  • 單晶片、BMP180 與 { 3V3 } / { 5V } 整合型 1602 LCD 之間的接線,並加入了電壓準位轉換電路,轉換不同電壓之間的雙向通訊訊號,最後將所有裝置結合在一起作程式測試,顯示溫度、大氣壓力與海拔高度在 LCD 中。

  • BMP180 模組使用提示 - Arduino 接線與程式測試
    這篇網頁主要針對兩個賣場提供的 Arduino 做使用說明。主要是說明如何 BMP180 數位氣壓感測模組與 Arduino 的接線與程式測試,使用 Arduino 本身硬體 I2C 做通訊,並且將輸出結果直接輸出到 Serial Port 上,所有計算過程與結果可直接輸出到其 Arduino Monitor 或是 Serial Port 軟體上。

  • BMP180 模組使用提示 - Raspberry Pi 接線與程式測試
  • 這篇網頁主要說明如何使用賣場所提供的樹莓派 ( Raspberry Pi ) BMP180 程式。這程式只包含一個檔案,所有 BMP180 的操作、溫度、大氣壓力、海拔高度,以及反算海平面壓力與大氣壓力都在其中,經由檔案開頭處的參數設定,就可以很方便操控整個程式 !

8 則留言:

  1. https://www.adafruit.com/datasheets/BST-BMP180-DS000-09.pdf
    您好,寫得很清楚。把規格書解釋得很清楚,不過我實務上,我遇到一個問題,想請教您,我實際上量測"乾空氣",約莫在1700hPa就無法在量測更高的壓力。我的裝置架構很簡單,是用一個水族用品店用的小馬達,5V2A的行動電源可驅動,加上一個水族用品店可買到的逆止閥(其功用如同二極體,防止逆流),外加一個寶特瓶打一個孔,接上scencer BMP180;BMP180上用一個矽膠軟管(五金店有),用三秒膠封裝在氣孔上,另一頭就接在保特瓶子上。是否市面上有更高的壓力感測器。
    我參考了另外一個MEMS壓力感測器 飛思卡爾的
    http://cache.freescale.com/files/sensors/doc/data_sheet/MPXHZ6400A.pdf

    回覆刪除
  2. 市面上是有可量測高壓力的壓力感測器,只要規格符合您的壓力上下限規格就可以使用。
    下面是一個例子提供參考
    http://david.neonquill.com/projects/rain_barrel/

    回覆刪除
  3. 請問參考BMP180 data sheet page 15 時,其溫度 X2值是 -2344 or -2343 呢? 計算時是否該四捨五入呢?

    回覆刪除
    回覆
    1. 範例上面的輸出數值就是用來測試所撰寫的程式碼輸出是不是正確,如果跟範例表格上的數值不同,就要根據現有輸出做修正,看是要四捨五入還是要無條件進位或是捨去。

      刪除
  4. 請問Aviation Weather Center 的 Aviation Information and Forecast 頁面如何進入 ?
    在左上角輸入 RCSS (松山機場) 並未正常文字顯示. 想得知松山機場的溫度及壓力.

    回覆刪除
    回覆
    1. 那個網站好像輸入查詢有問題,但可以找到所需要的 METAR 資料自己轉換;若是要台灣地區各地溫度與海平面壓力可以參考這個網站 http://www.cwb.gov.tw/V7/observe/real/ALLData.htm

      刪除
    2. 文中所列Hypsometric formula 與網站略有出入 ?
      http://keisan.casio.com/has10/SpecExec.cgi?path=06000000.Science%2F02100100.Earth%20science%2F12000300.Altitude%20from%20atmospheric%20pressure%2Fdefault.xml&charset=utf-8

      刪除
    3. 公式都是一樣的,我不曉得你說的那邊有出入?
      如果覺得數據出來跟網站上面的不同,可以再根據資料自己驗證看是哪邊出問題?

      刪除