Arduinoで遊ぶページ

Arduinoで遊んだ結果を残すページです。
garretlab
大気圧・温度センサモジュールの実験

概要

LPS25Hという大気圧センサを使った実験です。温度センサも入っています。

実際には、秋月電子通商で販売している、8ピンDIPモジュールを使用しました。

有機ELディスプレイに大気圧等を表示させてみました。こちらから。

MPL115A2という大気圧センサを利用した実験はこちらから。

データシート

LPS25Hのデータシートを参照して、どのようなものかを調べました。いろいろ機能があるようですが、まずは、秋月電子通商で買ったときについてきた説明書に従い、

SPIかI2Cのどちらかを選択することができます。今回は、I2Cを利用しました。

概要

LPS25Hの仕様の概要は以下の通りです。

項目 内容
電源電圧(Vdd) 1.7V~3.6V
動作温度 -30℃~105℃(0℃~80℃が、Full Accuracyとなっています)
動作気圧 260hPa~1260hPa
精度(大気圧) ±0.2hPa(20℃~60℃、260hPa~1260hPa)
精度(温度) ±2℃(0℃~65℃)
I2Cアドレス 0x5c(0b1011100)/0x5d(0b1011101)のどちらかを選択

LPS25Hモジュールは、8ピンのデバイスで、I2Cで利用する場合の各ピンの意味は以下の通りです。

ピン番号 内容
1 VDD
2 SCL
3 SDA
4 SA0(I2Cアドレスの選択。VDDに接続すると0x5d, GNDに接続すると0x5c。
5 I2C/SPI選択。VDDに接続するとI2C。
6 NC
7 INT1(割り込み1)
8 GND

このデバイスが動作する電源電圧の最大値は3.6Vです。Arduino Unoで利用する場合は、レベルコンバータなどを利用して電源電圧を調整する必要があるので注意してください。今回はArduino Dueを利用しました。

インタフェース

レジスタ

LPS25Hは多くのレジスタを持っています。以下に、今回の実験で利用したレジスタを記載しました。

アドレス 名前 説明
0x0f WHO_AM_I このデバイスのID(0xbd)が入っています。
0x20 CTRL_REG1 制御レジスタ1
0x28 PRESS_OUT_XL 大気圧データ(下位バイト)
0x29 PRESS_OUT_L 大気圧データ(中位バイト)
0x2a PRESS_OUT_H 大気圧データ(上位バイト)
0x2b TEMP_OUT_L 温度データ(下位バイト)
0x2c TEMP_OUT_H 温度データ(上位バイト)

他にも多くのレジスタがあります。

設定

上記に記載した制御レジスタ1を利用して、LPS25Hの動作を設定することができます。

ビット 名前 説明
7 PD パワーダウン制御 0 パワーダウンモード
1 アクティブモード
6:4 ODR2/ODR1/ODR0 出力データレート選択 000 one shot
001 1Hz
010 7Hz
011 12.5Hz
100 25Hz
101 予約
110
111
3 DIFF_EN 割り込み制御 0 割り込み無効
1 割り込み有効
2 BDU ブロックデータ更新 0 継続して更新
1 MSBとLSBが読まれるまで更新停止
1 RESET_AZ オートゼロ機能リセット 0 無効
1 REF_Pレジスタをデフォルト値に設定
0 SIM SPIインタフェースのモード設定 0 4-wire
1 3-wire

今回の実験では、以下の通り設定しました。

  • パワーダウン制御:1(アクティブに)
  • 出力データレート選択:001(1秒ごとにデータ出力)

上記の通りに設定レジスタに設定する値は、0b10010000 = 0x90 となります。

他にも、FIFOを利用して、いくつかのサンプルの平均値を出力させたり、以前の測定値(?)との差分を出力させたりすることもできるようです。

コマンド

制御1レジスタの設定

制御1レジスタに値を書き込むには、制御1レジスタのアドレス送信後、1バイトの設定値を送信します。

大気圧・温度の取得

今回は、1秒ごとにデータ出力するモードにしているので、1秒ごとに大気圧と温度データが更新されます。

大気圧データは24ビット、温度データは16ビットで表されていて、それぞれ、2の補数表現とデータシートには書かれています。

PRESS_OUT_HとPRESS_OUT_L、PRESS_OUT_XLの3つを結合した値を4096で割った値が、大気圧(hPa)になります。今回は、差分ではなく絶対値を取得するため、この値が負になることはないので、気にせず計算ができます。

大気圧[hPa] = ((PRESS_OUT_H << 16) | (PRESS_OUT_L << 8) | PRESS_OUT_XL) / 4096

TEMP_OUT_HとTEMP_OUT_Lの2つを結合した値を480で割って、42.5を足すと、温度(℃)になります。

このことから、42.5℃以下の場合は、測定データは負になるはずなので、16ビット長の整数型変数に値を代入してしまえば、普通に計算できそうです。

Arduinoでは、shortが16ビットなので、short型の変数に代入してしまえばそのまま計算できます。

温度[℃] = ((TEMP_OUT_H << 8) | TEMP_OUT_L) / 480 + 42.5

実験

LPS25HとArduinoとの接続

LPS25HモジュールとArduino Dueとを以下のように接続します。

LPS25Hの電源電圧は最大3.6Vなので、Arduino Unoを利用する場合は注意してください。

LPS25Hのピン Arduino Dueのピン
1 3.3V
2 SCL(21)
3 SDA(20)
4 GND(I2Cアドレスを0x5cに設定)
5 3.3V(プロトコルをI2Cに設定)
6 NC
7 未使用
8 GND

A3・A4・A5はArduinoのアナログの3番・4番・5番です。

Arduinoプログラミング

Wireライブラリを利用して、ArduinoとLPS25Hとの通信を行います。

初期化

setCtrlReg1という関数を作成しました。

CTRL_REG1に0x90を設定することで、毎秒1回測定を行います。

大気圧の取得

getPressure()という関数を作成しました。

大気圧データを読み取り、気圧に変換しています。

温度の取得

getTemperature()という関数を作成しました。

温度データを読み取り、温度に変換しています。

スケッチ

温度と湿度を取得するスケッチです。最初にWHO_AM_I(0xBD)を取得して表示しています。

#include <Wire.h>

#define LPS25H_ADDRESS  0x5c /* SA0 -> GND */
#define LPS25H_WHO_AM_I     0x0f
#define LPS25H_CTRL_REG1    0x20
#define LPS25H_PRESS_OUT_XL 0x28
#define LPS25H_PRESS_OUT_L  0x29
#define LPS25H_PRESS_OUT_H  0x2a
#define LPS25H_TEMP_OUT_L   0x2b
#define LPS25H_TEMP_OUT_H   0x2c

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  Wire.begin();
  
  Serial.print("WHO_AM_I = 0x");
  Serial.println(whoAmI(), HEX);
  
  setCtrlReg1();
}

void loop() {
  // put your main code here, to run repeatedly:
  Serial.print("Pressure = ");
  Serial.print(getPressure());
  Serial.print(" hPa, Temperature = ");
  Serial.print(getTemperature());
  Serial.println(" degree");
  
  //getPressure();
  delay(1000);
}

int whoAmI() {
  Wire.beginTransmission(LPS25H_ADDRESS);
  Wire.write(LPS25H_WHO_AM_I);
  Wire.endTransmission();
  
  Wire.requestFrom(LPS25H_ADDRESS, 1);
  while(Wire.available() < 1) {
    ;
  }
  
  return Wire.read();
}

void setCtrlReg1() {
  Wire.beginTransmission(LPS25H_ADDRESS);
  Wire.write(LPS25H_CTRL_REG1);
  Wire.write(0x90);
  Wire.endTransmission();
}

float getPressure() {
  long pData = 0;
  
  for (int i = 0; i < 3; i++) {
    Wire.beginTransmission(LPS25H_ADDRESS);
    Wire.write(LPS25H_PRESS_OUT_XL + i);
    Wire.endTransmission();

    Wire.requestFrom(LPS25H_ADDRESS, 1);
    while(Wire.available() < 1) {
      ;
    }
    
    pData |= Wire.read() << (8 * i);
  }
  
  return pData / 4096.0;
}

float getTemperature() {
  short tData = 0;
  
  for (int i = 0; i < 2; i++) {
    Wire.beginTransmission(LPS25H_ADDRESS);
    Wire.write(LPS25H_TEMP_OUT_L + i);
    Wire.endTransmission();

    Wire.requestFrom(LPS25H_ADDRESS, 1);
    while(Wire.available() < 1) {
      ;
    }
    
    tData |= Wire.read() << (8 * i);
  }
  
  return 42.5 + tData / 480.0;
}

実行の様子

上記のスケッチを実行している様子です。

バージョン

Arduino 1.6.0/Arduino Due



メニューを表示するためにJavaScriptを有効にしてください。

Arduinoで遊ぶページ
Copyright © 2015 garretlab all rights reserved.
inserted by FC2 system