2014年7月1日 星期二

BMP180 模組使用提示 - Arduino 接線與程式測試

網頁中所使用的零件可至露天賣場訂購:
I2C 電壓轉換電路請參照下面網頁的說明
BMP180 的晶片使用說明與溫度、氣壓和海拔高度的計算,請參考下面網頁中的說明

如果沒有購買賣場的 BMP180 數位氣壓感測器模組,在沒有賣場提供的程式碼之下,這網頁中的內容就對你幫助不大。

Arduino + I2C 電壓準位轉換電路 + BMP180 數位氣壓感測模組,可在外接其他不同電壓準位的 I2C 裝置

這篇網頁主要是說明如何 BMP180 數位氣壓感測模組與 Arduino 的接線與程式測試,使用 Arduino 本身硬體 I2C 做通訊,並且將輸出結果直接輸出到 Serial Port 上,所有計算過程與結果可直接輸出到其 Arduino Monitor 或是 Serial Port 軟體上。實際完成的接線如上圖所示,程式測試結果請看下面的程式測試部分。

電路接線圖:

因為 Arduino 與 BMP180 數位氣壓感測模組通訊接腳是不同電壓,因此在 Arduino 電路上多了I2C 電壓準位轉換電路 ( 如果使用的 I2C  裝置都是 3V3 電壓準位,那這電壓轉換電路可以省略,直接將 BMP180 的 I2C 接腳接到 Arduino 上。所以若只有裝設 BMP180 一個裝置,則其 SDA 與 SCL 可以接在 ASDA / ASCL 或是 BSDA / BSCL 都可以,VCC 可以接  5V 或是 3V3,但若是使用了其他電壓準位的 I2C 通訊裝置,則必須注意接線的位置是在 A 端還是在 B 端 。上面的說明,只適用於現在這個網頁的例子 !!! ) 

BMP180 - Arduino 電路接線圖


程式測試:

在零件所提供的雲端硬碟的 Arduino 資料夾有兩組程式碼,分述如下。


* BMP180_Wire.ino 的說明

在目錄 1 下,BMP180_Wire.ino 執行時,會在 Serial Monitor ( 或 Serial Port 軟體 ) 顯示了計算溫度、大氣壓力的所有過程與結果,但這程式碼中沒有額外再提供資料手冊上的那例子上的係數來做驗證,如果有需要再自行加上。


這個程式會設定到的地方只有 line 13:設定 oss ( oversampling setting ) 這個參數,參數設定的方法請參考資料手冊,或是 "如何使用 Borch BMP180 數位氣壓感測器模組計算溫度、大氣壓力與海拔高度 ?" 裡的說明。

BMP180_Wire.ino
13 
14 const unsigned char OSS = 0;  // Oversampling Setting


setup() 函式裡,Serial Port 設定的速度是 9600 bps ( line 38 ),並讀取 BMP180 EEPROM 裡的的校正係數 ( line 40 ),每一個讀取到的校正係數,將會依照資料手冊上計算式的名稱定義輸出到 Serial Port 上。

BMP180_Wire.ino, setup()
36 void setup()
37 {
38   Serial.begin(9600);
39   Wire.begin();
40   BMP180Calibration();
41 }


loop() 函式裡,重複呼叫 BMP180ReadUT() BMP180ReadUP() 計算溫度以及大氣壓力,並且將計算過程以及最後的結果,同樣的輸出到 Serial Port 上。

BMP180_Wire.ino, loop()
43 void loop()
44 {
45   temperature = BMP180GetTemperature(BMP180ReadUT());
46   pressure = BMP180GetPressure(BMP180ReadUP());
47 
48   Serial.print("Temperature: ");
49   Serial.print(temperature, DEC);
50   Serial.println(" *0.1 deg C");
51   Serial.print("Pressure: ");
52   Serial.print(pressure, DEC);
53   Serial.println(" Pa");
54   Serial.println();
55 
56   delay(1000);
57 }


將程式編譯並上傳到 Arduino 後,打開 Serial Monitor,就可以看到下面輸出的畫面,校正係數只會出現一次,之後就只會輸出溫度與大氣壓力計算過程與結果,當然也可以使用其他的 Serial Port 軟體來看,參數請設定為 9600, N, 1, 8 ( Baud Rate:9600, Parity Bit:NONE, Data Bit:8, Stop Bit:1 ),COM Port 選擇再自己確認。如下為使用 Arduino 內建的 Serial Monitor 與 Serial Port 軟體 AccessPort 分別顯示計算過程與結果的畫面。

使用 Arduino Serial Monitor 顯示計算過程數值

使用 AccessPort  顯示計算過程數值

* BMP180_basic.ino 的說明

要使用 BMP180_basic.ino 前,請先將下面 libraries 目錄下的兩個子目錄 ( BMP180/I2Cdev/ ) 直接複製到 Arduino libraries 目錄下 ( 若不知如何新增新的函式庫到 Arduino,看 "Installing Additional Arduino Libraries" 這篇網頁中的說明 )。


安裝好之後,就會在Arduino IDE 的選單列中 File / Examples / BMP180 / Examples / 下 看到 BMP180 目錄下的 BMP180_basic.ino,點擊打開。


BMP180_basic.ino 使用到三個標頭檔:Wire.hI2Cdev.hBMP180.h,前面兩個是 Arduino 硬體 I2C 用到的函式庫( line 46, line 51 ),最後面那一個是 BMP180 用到的函式庫標頭檔 ( line 51 );line 56:BMP180 的實體宣告,並且使用預設的 7-bit I2C 位址 0x77

BMP180 / Examples / BMP180_basic / BMP180_basic.ino
43 
44 // Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation
45 // is used in I2Cdev.h
46 #include "Wire.h"
47 
48 // I2Cdev and BMP180 must be installed as libraries, or else the .cpp/.h files
49 // for both classes must be in the include path of your project
50 #include "I2Cdev.h"
51 #include "BMP180.h"
52
53 // class default I2C address is 0x77
54 // specific I2C addresses may be passed as a parameter here
55 // (though the BMP180 supports only one address)
56 BMP180 barometer;

setup() 函式中,首先初始化 Arduino I2C 通訊 ( line 68 ) ( 只要使用到 Arduino Wire 函式庫,整個程式一開始一定要做的動作,只要做一次就好 ( Arduino Wire.begin() 說明 ) );Serial 速度設定為 9600 bps ( line 73 );輸出初始化字串 ( line 76 ) 再初始化 BMP180 ( line 77 ),BMP180 會直接將 EEPROM 裡的校正係數全部取出 ( BMP180 / BMP180.cpp:line 75 ... line 90 ),做為等一下的計算使用。

BMP180 / Examples / BMP180_basic / BMP180_basic.ino, setup()
 65 
 66 void setup() {
 67     // join I2C bus (I2Cdev library doesn't do this automatically)
 68     Wire.begin();
 69 
 70     // initialize serial communication
 71     // (38400 chosen because it works as well at 8MHz as it does at 16MHz, but
 72     // it's really up to you depending on your project)
 73     Serial.begin(9600);
 74 
 75     // initialize device
 76     Serial.println("Initializing I2C devices...");
 77     barometer.initialize();
 78 
 79     /* line 79 ... line 81 省略 */
 82 
 83     // configure LED pin for activity indication
 84     pinMode(LED_PIN, OUTPUT);
 85 }

BMP180 / BMP180.cpp, BMP180::initialize(), BMP180::testConnection() BMP180::loadCalibration()
57 /**
58  * Prepare device for normal usage.
59  */
60 void BMP180::initialize() {
61     // load sensor's calibration constants
62     loadCalibration();
63 }
64 
65 /* line 65 ... line 71 省略 */
..
72 
73 /* calibration register methods */
74 
75 void BMP180::loadCalibration() {
76     uint8_t buf2[22];
77     I2Cdev::readBytes(devAddr, BMP180_RA_AC1_H, 22, buf2);
78     ac1 = ((int16_t)buf2[0] << 8) + buf2[1];
79     ac2 = ((int16_t)buf2[2] << 8) + buf2[3];
80     ac3 = ((int16_t)buf2[4] << 8) + buf2[5];
81     ac4 = ((uint16_t)buf2[6] << 8) + buf2[7];
82     ac5 = ((uint16_t)buf2[8] << 8) + buf2[9];
83     ac6 = ((uint16_t)buf2[10] << 8) + buf2[11];
84     b1 = ((int16_t)buf2[12] << 8) + buf2[13];
85     b2 = ((int16_t)buf2[14] << 8) + buf2[15];
86     mb = ((int16_t)buf2[16] << 8) + buf2[17];
87     mc = ((int16_t)buf2[18] << 8) + buf2[19];
88     md = ((int16_t)buf2[20] << 8) + buf2[21];
89     calibrationLoaded = true;
90 }

進入到 loop() 函式,在開始做溫度與大氣壓力計算前,BMP180 必須先知道使用者要讀取溫度或是大氣壓力的原生資料。若是要讀取溫度,先將 BMP180_MODE_TEMPERATURE 由函式 setControl() 送給 BMP180 ( line 89 ),由於 BMP180 在可以讀取溫度原生資料需要一些時間處理,因此需要延遲一段時間 ( > 4.5 ms, line 92 ... line 93 ),才能開始讀取溫度的原生資料 ( line 96),計算實際溫度的數值 ( line 96 )。

而大氣壓力的原生資料跟讀取溫度原生資料流程差不多,但同樣必須讀取溫度原生資料然後再讀取大氣壓力原生資料。讀取大氣壓力原生資料前,送給 BMP180 要使用的量測模式 ( line 99 ),程式碼使用的是 BMP180_MODE_PRESSURE_3 ( ultra high resolution, Conversion time pressure max.:25.5 ms ),送出之後需要等待一段時間 ( line 100 ) 才可以讀取大氣壓力原生資料 ( line 103 ),而不同的模式設定會影響這一段延遲時間的長短  ( BMP180 / BMP180.cpp:line 181 ... line 198 ),但程式碼會自行搞定 !

有了上面溫度與大氣壓力原生資料,就可以直接將數值送到計算函式中進行計算 ( line 103, line 108 ),其中在計算海拔高度所使用的海平面壓力是 101325 Pa,採用資料手冊 Page 15 所提供的公式 ( BMP180 / BMP180.cpp:line 275 ... line 277  )。

line 111 ... line 115:將溫度、大氣壓力與海拔高度輸出到 serial port;line 118:切換 LED ( digital IO pin number 13 ) 的狀態,並輸出 ( line 119 );最後延遲 100 ms ( line 122 ) 再重複讀取的循環。

如此就完成整個 BMP1800 程式的流程。

BMP180 / Examples / BMP180_basic / BMP180_basic.ino, loop()
 87 void loop() {
 88     // request temperature
 89     barometer.setControl(BMP180_MODE_TEMPERATURE);
 90     
 91     // wait appropriate time for conversion (4.5ms delay)
 92     lastMicros = micros();
 93     while (micros() - lastMicros < barometer.getMeasureDelayMicroseconds());
 94 
 95     // read calibrated temperature value in degrees Celsius
 96     temperature = barometer.getTemperatureC();
 97 
 98     // request pressure (3x oversampling mode, high detail, 25.5ms delay)
 99     barometer.setControl(BMP180_MODE_PRESSURE_3);
100     while (micros() - lastMicros < barometer.getMeasureDelayMicroseconds());
101 
102     // read calibrated pressure value in Pascals (Pa)
103     pressure = barometer.getPressure();
104 
105     // calculate absolute altitude in meters based on known pressure
106     // (may pass a second "sea level pressure" parameter here,
107     // otherwise uses the standard value of 101325 Pa)
108     altitude = barometer.getAltitude(pressure);
109 
110     // display measured values if appropriate
111     Serial.print("T/P/A\t");
112     Serial.print(temperature); Serial.print("\t");
113     Serial.print(pressure); Serial.print("\t");
114     Serial.print(altitude);
115     Serial.println("");
116 
117     // blink LED to indicate activity
118     blinkState = !blinkState;
119     digitalWrite(LED_PIN, blinkState);
120     
121     // delay 100 msec to allow visually parsing blink and any serial output
122     delay(100);
123 }

BMP180 / BMP180.cpp, getMeasureDelayMilliseconds()
181 uint8_t BMP180::getMeasureDelayMilliseconds(uint8_t mode) {
182     if (mode == 0) mode = measureMode;
183     if (measureMode == 0x2E) return 5;
184     else if (measureMode == 0x34) return 5;
185     else if (measureMode == 0x74) return 8;
186     else if (measureMode == 0xB4) return 14;
187     else if (measureMode == 0xF4) return 26;
188     return 0; // invalid mode
189 }
190 uint16_t BMP180::getMeasureDelayMicroseconds(uint8_t mode) {
191     if (mode == 0) mode = measureMode;
192     if (measureMode == 0x2E) return 4500;
193     else if (measureMode == 0x34) return 4500;
194     else if (measureMode == 0x74) return 7500;
195     else if (measureMode == 0xB4) return 13500;
196     else if (measureMode == 0xF4) return 25500;
197     return 0; // invalid mode
198 }

BMP180 / BMP180.cpp, getAltitude()
275 float BMP180::getAltitude(float pressure, float seaLevelPressure) {
276     return 44330 * (1.0 - pow(pressure / seaLevelPressure, 0.1903));
277 }


總結:

即便手中沒有原始碼,但 BMP180 的程式走向流程,全部都是根據  "如何使用 Borch BMP180 數位氣壓感測器模組計算溫度、大氣壓力與海拔高度 ?" 這篇網頁裡的量測流程來寫作,而且當中每一方塊剛好可以對應到程式的寫作。若是對於上面講解不清楚的話,先看一下上面連結網頁中的說明,再來看這些使用提示,會更容易了解 !


<< BMP180 數位氣壓感測器系列文章 >>

沒有留言:

張貼留言