だいたいだいだい

だいたいのことはたいていなんとかなる 旅行とか飛行機とか工作とか

【MultiWii】その5:I2CdevlibでBMP085の値を読み出す【Arduino】

前回,MultiWiiI SE V2.5 CRIUSのセンサーを使うために用いる,I2Cdevlibの紹介とライブラリのインストール方法について書きました.

(おそらく,他のArduino環境でも同様に使えます.) 

 

www.daitai-daidai.com

 

今回は,それを用いて,実際に気圧センサーBMP085の値を読み出していきます.

 とりあえず,I2Cdevlibのサンプルプログラムを動かしてみます.それから,コードを読みながら詳しく使い方を見ていきます.

 

BMP085のサンプルプログラム

前回ダウンロードしたI2Cdevlibのライブラリのなかにサンプルプログラム"BMP_085_basic.ino"があります.

i2c Device Libraries\i2cdevlib-master\Arduino\BMP085\examples\BMP085_basic

 

これを,書き込みます.

 

f:id:dai65527:20180501114433j:plain

 

とりあえず動かしてみた結果

書き込んだら,シリアルモニタを起動して結果を見てみましょう.

ボーレートは38400bpsです.

f:id:dai65527:20180501114633p:plain

 

T/P/Aとありますが,表示は右から,Temperature(温度℃) /Pressure(大気圧力Pa) /Altitude(高度m)が表示されています.

 

温度は少し高めに出ているような気がします.うちには温度計がないのでなんとも言えませんが,体感では27℃ほど暑くないような気がします.春だしまだ.

圧力はそれっぽい値が出ていますね.1Paきざみの値が出ています.

高度は,気圧から計算されます.(高度が上がるほど気圧が下がる.詳しいことは後述します.)こちらは1mきざみの値が出力されています.特にセンサーは動かしてないけど値はぶれてますね.

 

サンプルプログラムに沿って使い方を見ていく

サンプルプログラムに沿って,ライブラリの使い方を見ていきましょう.

 

ライブラリのインクルード

ライブラリのインクルードは40行目まででされていますね.以下の3つのヘッダファイルがインクルードされています.

#include "Wire.h"

#include "I2Cdev.h"
#include "BMP085.h"

Wire.hはArduinoIDEに用意されているI2C通信用のライブラリです.これは,I2Cdev.hで使われています.

I2Cdev.hBMP085.hは,前回インストールしたものですね.I2Cdev.hはI2Cdevlib全体で使われます.

 

BMP085クラスのインスタンスを生成

45行目です.BMP085を使うための関数はBMP085という名前のクラスにまとまっています.

BMP085 barometer;

ここでは,barometerという名前のインスタンスを生成しています.

 

グローバル変数など

float temperature;
float pressure;
int32_t altitude;

#define LED_PIN 13 // (Arduino is 13, Teensy is 11, Teensy++ is 6)
温度,圧力,高度を格納する変数の宣言と,動作確認用LEDの繋がっているピン番号LED_PINを指定しています.
今回使っているMultiWiiボードは他のArduinoボード同様に,13番のデジタルピンに内臓のLEDが接続されています.
 
 
 
続いて54行目から73行目のsetup関数(起動後1回実行される関数)のなかを見ていきましょう.

Wire.beginとSerial.begin

    // join I2C bus (I2Cdev library doesn't do this automatically)
    Wire.begin();

    // initialize serial communication
    // (38400 chosen because it works as well at 8MHz as it does at 16MHz, but
    // it's really up to you depending on your project)
    Serial.begin(38400);

Wire.beginはI2Cバスに接続する変数です.I2Cdevライブラリはこれを勝手にやってくれないのでここでやる必要があります.(なお,引数を設定しないとマスターとして,引数にアドレスを設定するとスレーブとして接続するようです.今回は,MultiWii側がマスターなので引数なしです)

Serial.beginはArduinoとPCのシリアル通信を開始するための関数です.引数はボーレートです.ここでは38400bpsとなっていますが,ソースコード内のコメントにもあるように,他の値でも問題ありません.(9600bpsでも115200bpsでも動きました.)

 

デバイスの初期化と接続のテスト

    // initialize device
    Serial.println("Initializing I2C devices...");
    barometer.initialize();

    // verify connection
    Serial.println("Testing device connections...");
    Serial.println(barometer.testConnection() ? "BMP085 connection successful" : "BMP085 connection failed");

initialize関数を実行し,デバイスを初期化,その後,接続できているかテストし,接続できていれば,BMP connection successful か failed がシリアルモニタに表示されます.

 

LEDピンの設定

    // configure LED pin for activity indication
    pinMode(LED_PIN, OUTPUT);

先ほど設定した動作確認用のLEDピン(LED_PIN)のピンモードを出力(OUTPUT)に設定します.ArduinoでLチカやったことあるならおなじみの関数ですね.

 

 

ここまででsetup関数は終了.続いては,loop関数(setup関数のあと,エンドレスで繰り返される関数)を見ていきましょう.ここがメインでデータを扱うところとなります.

温度の取得

気圧の前に温度を取得していきます.

    // request temperature
    barometer.setControl(BMP085_MODE_TEMPERATURE);
    
    // read calibrated temperature value in degrees Celsius
    temperature = barometer.getTemperatureC();

getTemperatureC関数で温度を取得する前に,setControlという関数を呼ぶ必要があるようです.

BMP085.cpp,BMP085.h,とデータシートを少し読んでみたのですが,BMP085setControlの計測をする際に,計測モード?の指定をする必要があるみたいで,それをしているのがsetControlのようです.(データシート4.4節参照)

 

setControlの引数となりうるのは,次の5つです.

  • BMP085_MODE_TEMPERATURE (=0x2E,温度計測モード)
  • BMP085_MODE_PRESSURE_0 (=0x34,圧力計測モード0)
  • BMP085_MODE_PRESSURE_1 (=0x74,圧力計測モード1)
  • BMP085_MODE_PRESSURE_2 (=0xB4,圧力計測モード2)
  • BMP085_MODE_PRESSURE_3 (=0xF4,圧力計測モード3)

それぞれ,BMP085.hで定義されています.温度を測るときは,BMP085_MODE_TEMPERATUREを入れてやればいいわけですね.

(その他は以下で詳述します.)

 

getTemperatureCは,セ氏温度を返してくれます.かわりにgetTemperatureFを使えば華氏で返してくれるようです.(絶対使わないけど)

 

気圧の取得

次はメインの気圧の計測地を取得します.

    // request pressure (3x oversampling mode, high detail, 23.5ms delay)
    barometer.setControl(BMP085_MODE_PRESSURE_3);

    // read calibrated pressure value in Pascals (Pa)
    pressure = barometer.getPressure();

まず,前述した,setControl関数を呼び出します.気圧を測るときは引数を,

  • BMP085_MODE_PRESSURE_0 (=0x34,圧力計測モード0)
  • BMP085_MODE_PRESSURE_1 (=0x74,圧力計測モード1)
  • BMP085_MODE_PRESSURE_2 (=0xB4,圧力計測モード2)
  • BMP085_MODE_PRESSURE_3 (=0xF4,圧力計測モード3)

のいずれかにすればよいようです.今回は,BMP085_MODE_PRESSURE_3としてあります.

これらのモードの違いは,解像度と消費電力,計測時間による違いで,それぞれ以下の表のようになっています.

f:id:dai65527:20180502170925j:plain

圧力計測モード(BMP085データシートより引用)

何に使うかによって好きに変えていいみたいですね.

 

getPressureは,計測した気圧を32ビットの整数(int32_t)で返してくれます.単位はPaです.

 

高度の取得

高度は前述の通り気圧から計算されます.

    // calculate absolute altitude in meters based on known pressure
    // (may pass a second "sea level pressure" parameter here,
    // otherwise uses the standard value of 101325 Pa)
    altitude = barometer.getAltitude(pressure);

getAltitude関数を使うことで,気圧から高度を計算しています.データシートによると,以下の式で計算されているみたいです.

\displaystyle h=44330\times\left(1-\left(\frac{p}{p_0}\right)^\frac{1}{5.255}\right)

ただし,h:高度[m],p:圧力(気圧)[Pa],p_0:海面気圧[Pa]です.

この式で,海面気圧が使われています.これを,getAltitudeの2つ目の引数として,入力することもできるようです.入力しない場合は,p_0 = 101325がデフォルトの値として使われます.

f:id:dai65527:20180503154035j:plain

気圧と高度の関係(BMP085データシートより引用)



シリアル出力とLED点滅

あとは,計測されたデータをシリアルモニターに出力する部分とLED関係です.

    // display measured values if appropriate
    Serial.print("T/P/A\t");
    Serial.print(temperature); Serial.print("\t");
    Serial.print(pressure); Serial.print("\t");
    Serial.print(altitude);
    Serial.println("");

    // blink LED to indicate activity
    blinkState = !blinkState;
    digitalWrite(LED_PIN, blinkState);
    
    // delay 100 msec to allow visually parsing blink and any serial output
    delay(100);

得られたデータをSerial.outでシリアル出力しています.また,digitalWriteで動作確認用のLEDを点滅させていますね.

delayさせてるのは,LEDの点滅とシリアルモニターを見やすくするためですね.なくてもいいです.

 

まとめ

I2Cdevlibで,BMP085を動かしてみましたが,すごい簡単ですね!!

他にも,関数がいくつか用意されてるみたいなので必要に応じて調べていきたいと思います.