気圧センサー LPS25HB
I2CとSPIの両用で使用できる気圧センサー3.3V駆動ですが、5Vでも駆動できるブレークアウトボードが存在します。
LPS25HB(3.3V DIP化ブレークアウトボード)
LPS25HBセンサーモジュール(2.5~5.5Vレギュレータ付き)
LPS25HB搭載 電圧レギュレータ付き気圧センサモジュール
I2C接続
I2Cで使用する場合には、CSをプルアップ接続してHIGHにします。I2CアドレスはSDOをLOW(プルダウン)すると0x5C、HIGH(プルアップ)すると0x5Dになります。
レギュレータ無しのブレークアウトボードでも(チップ自体は同じなので動作は)同じです。
SPI接続
SPIのピン接続は SDA-MOSI 、SCL-SCLK、SDO-MISO、CS-CSとなります。気圧センサーの使い方
LPS25HB データシート より抜粋 LPS25HBの主要なレジスタは次の通り名称 | 形式 | アドレス | コメント |
---|---|---|---|
デバイスID | R | 0F | BD |
圧力分解能 | R/W | 10 | 温度・気圧の内部平均選択 |
制御レジスタ1 | R/W | 20 | 出力データ速度設定 |
制御レジスタ2 | R/W | 21 | リセット/FIFO有効・無効設定 |
制御レジスタ3 | R/W | 22 | 割り込み制御 |
制御レジスタ4 | R/W | 23 | 割り込み制御 |
ステータス | R | 27 | 温度・気圧データの取得状態 |
気圧データ XL | R | 28 | 気圧データ 24Bit |
気圧データ L | R | 29 | |
気圧データ H | R | 2A | |
気温データ L | R | 2B | 気温データ 16Bit |
気温データ H | R | 2C | |
FIFO制御 | R/W | 2E | |
FIFOステータス | R | 2F |
レジスタは基本的に1バイトづつしか読み出せない
参照アドレスの最上位ビットを1にする(アドレスと0x80の ORを取る)と、読みだし毎に読み出しアドレスがインクリメントされる。
※実質的に連続読み出しモードになる。
ただし、FIFOが有効な場合、0x28,0x29,0x2Aの読み出しアドレスはループループする
※0x2A読み取り後、インクリメントされたアドレスは0x2Bではなく0x28になる
このため、FIFOを有効にした場合は気圧と気温は別々に読み取るか、もしくは1バイトづつ読み取る必要がある。
気温・気圧データの読み取り
気圧データは取得した24Bit整数値÷4096でhPa単位の気圧に変換出来る。気温データは取得した16Bit整数値÷480 + 42.5 で℃単位の気温に変換できる。
この変換式はLPS25HBテクニカルノートに記載されています。
-- I2C接続 --
LPS25HB-TEST-I2C.zip
※ <>を全角<>に置き換えています。コピペの際は注意してください。
#include <Wire.h>
#define LPSADDR 0x5C
uint32_t pressure = 0 ;
float temperature = 0 ;
uint8_t i2cBuff[6] ;
// Register読み取り
uint8_t readLPS(uint8_t addr) {
uint8_t readData ;
// Read Address Set
Wire.beginTransmission(LPSADDR);
Wire.write(addr);
Wire.endTransmission();
// 1Byte Read
Wire.requestFrom(LPSADDR, 1);
while(Wire.available()<1);
readData = Wire.read();
return readData ;
}
// Register読み取り
uint8_t readLPSBuff(uint8_t addr,int readLen) {
uint8_t readData ;
// Read Address Set
Wire.beginTransmission(LPSADDR);
Wire.write(addr|0x80);
Wire.endTransmission();
// 1Byte Read
Wire.requestFrom(LPSADDR , readLen);
while(Wire.available() < readLen);
for (int i=0;i<readLen;i++) {
i2cBuff[i] = Wire.read();
}
Serial.print("i2cBuff=") ;
for (int i=0;i<readLen;i++) {
Serial.print(i2cBuff[i],HEX) ;
Serial.print(" ") ;
}
Serial.println() ;
return readData ;
}
// 気圧センサー読み取り
bool readLPS_Sencer( ) {
uint8_t stat = readLPS(0x27);
uint8_t fifoStat = readLPS(0x2F);
readLPSBuff(0x28,3) ;
uint8_t pxl = i2cBuff[0] ;
uint8_t pl = i2cBuff[1] ;
uint8_t ph = i2cBuff[2] ;
readLPSBuff(0x2B,2) ;
uint8_t tl = i2cBuff[0] ;
uint8_t th = i2cBuff[1] ;
// uint8_t pxl = readLPS(0x28) ;
// uint8_t pl = readLPS(0x29) ;
// uint8_t ph = readLPS(0x2A) ;
// uint8_t tl = readLPS(0x2B) ;
// uint8_t th = readLPS(0x2C) ;
// uint8_t fifoStat = readLPS(0x2F);
// combine bytes
pressure = (int32_t)(int8_t)ph << 16 | (uint16_t)pl << 8 | pxl;
pressure /= 4096 ;
int16_t temp = (int16_t)th << 8 | tl ;
temperature = 42.5 + (float)temp / 480;
Serial.print("stat = ") ;
Serial.print(stat,HEX) ;
Serial.print(" fifoStat = ") ;
Serial.print(fifoStat,HEX) ;
Serial.print(" ") ;
return ((stat & 0x03) == 0x03) && ((fifoStat & 0xC0) == 0xC0) ;
}
// 1バイトコマンドを送信
void sendLPS(uint8_t addr , uint8_t command) {
Wire.beginTransmission(LPSADDR);
Wire.write(addr);
Wire.write(command);
Wire.endTransmission();
}
void setup() {
Wire.begin();
Serial.begin(9600);
while (!Serial); // Leonardo: wait for serial monitor
Serial.println("\nLPS25HB 気圧センサーテスト - FIFO有効/分割読み出し");
// -- Read WHO AM I
uint8_t deviceID = readLPS(0x0F) ;
Serial.print("Device ID = ") ;
Serial.println(deviceID,HEX) ;
// --- Reset LPS25HB
sendLPS(0x21,0x04); // ソフトウェアリセット
while(readLPS(0x21)); // リセット確認
delay(100);
sendLPS(0x21,0x80); // リブートメモリ
while(readLPS(0x21)); // リブート確認
delay(100);
sendLPS(0x20,0xc0); // アクティブモード、アウトプット25Hz
// ※VCCに5V入れた場合、1Hzだと何故か誤差が大きい
// ※この設定だと+2hPa +1℃位のズレで収まる
delay(100);
sendLPS(0x21,0x40); // FiFO有効
sendLPS(0x2E,0xC7); // FIFO平均モード 8サンプル
// ※サンプル数が大きすぎるとFIFOがFULLになるまでに時間がかかる
delay(1000);
}
void loop() {
// ----- Read 気圧センサー
bool ret = readLPS_Sencer( ) ;
Serial.print("ret = ") ;
Serial.print(ret) ;
Serial.print(" / pressure = ") ;
Serial.print(pressure) ;
Serial.print(" / Temperature = ") ;
Serial.println(temperature) ;
delay(10*1000) ; // 10秒ディレイ
}
-- SPI接続 --
LPS25HB-TEST-SPI.zip
※ <>を全角<>に置き換えています。コピペの際は注意してください。
#include <SPI.h>
#define SS 10 // ArduinoUNO 10 : M5Stamp 19 : RaspberryPi PICO 5
uint32_t pressure = 0 ;
float temperature = 0 ;
// Register読み取り
uint8_t readLPS(uint8_t addr) {
uint8_t readData ;
digitalWrite(SS, HIGH);
digitalWrite(SS, LOW); //通信開始
SPI.transfer(addr|0x80);
readData = SPI.transfer(0x00);
digitalWrite(SS, HIGH); //通信終了
return readData ;
}
// 1バイトコマンドを送信
void sendLPS(uint8_t addr , uint8_t command) {
digitalWrite(SS, HIGH);
digitalWrite(SS, LOW); //通信開始
SPI.transfer(addr);
SPI.transfer(command);
digitalWrite(SS, HIGH); //通信終了
}
// 気圧センサー読み取り
bool readLPS_Sencer( ) {
uint8_t stat = readLPS(0x27);
uint8_t pxl = readLPS(0x28) ;
uint8_t pl = readLPS(0x29) ;
uint8_t ph = readLPS(0x2A) ;
uint8_t tl = readLPS(0x2B) ;
uint8_t th = readLPS(0x2C) ;
uint8_t fifoStat = readLPS(0x2F);
// combine bytes
pressure = (int32_t)(int8_t)ph << 16 | (uint16_t)pl << 8 | pxl;
pressure /= 4096 ;
int16_t temp = (int16_t)th << 8 | tl ;
temperature = 42.5 + (float)temp / 480;
Serial.print("stat = ") ;
Serial.print(stat,HEX) ;
Serial.print(" fifoStat = ") ;
Serial.print(fifoStat,HEX) ;
Serial.print(" ") ;
return ((stat & 0x03) == 0x03) && ((fifoStat & 0xC0) == 0xC0) ;
}
void setup() {
Serial.begin(9600);
while (!Serial); // Leonardo: wait for serial monitor
Serial.println("\nLPS25HB 気圧センサーテスト SPI/FIFO有効");
pinMode (SS, OUTPUT);
digitalWrite(SS, HIGH);
SPI.begin ();
SPI.setBitOrder(MSBFIRST);
SPI.setDataMode(SPI_MODE3);
SPI.setClockDivider(SPI_CLOCK_DIV16);
// -- Read WHO AM I
uint8_t deviceID = readLPS(0x0F) ;
Serial.print("Device ID = ") ;
Serial.println(deviceID,HEX) ;
// --- Reset LPS25HB
sendLPS(0x21,0x04); // ソフトウェアリセット
while(readLPS(0x21)); // リセット確認
delay(100);
sendLPS(0x21,0x80); // リブートメモリ
while(readLPS(0x21)); // リブート確認
delay(100);
sendLPS(0x20,0x90); // アクティブモード、アウトプット25Hz
// ※VCCに5V入れた場合、1Hzだと何故か誤差が大きい
// ※この設定だと+2hPa +1℃位のズレで収まる
delay(100);
sendLPS(0x21,0x40); // FiFO有効
sendLPS(0x2E,0xC7); // FIFO平均モード 8サンプル
// ※サンプル数が大きすぎるとFIFOがFULLになるまでに時間がかかる
delay(1300);
}
void loop() {
// ----- Read 気圧センサー
bool ret = readLPS_Sencer( ) ;
Serial.print("ret = ") ;
Serial.print(ret) ;
Serial.print(" / pressure = ") ;
Serial.print(pressure) ;
Serial.print(" / Temperature = ") ;
Serial.println(temperature) ;
delay(10*1000) ; // 10秒ディレイ
}