超小型気圧センサーLPS25HBの使い方

LPS25HB 気圧センサー センサー

超小型気圧センサーLPS25HBから気圧データ温度データを読み取る方法を紹介します。

使用するマイコンはRaspberry Pi、プログラム言語はPythonです。

サンプルプログラムは、センサーからデータを読み取るだけでなく測定条件設定も行います。
通信方式は、I2C通信とSPI通信の2種類を記載しているので参考にしてください。

また、動作確認中に通信トラブルがあったので、その原因と対策も紹介します。

センサーの主な仕様
気圧測定
測定範囲:260hPa~1260hPa
精度:±0.1hPa(25℃時)、±1hPa(0℃~80℃時)
分解能:24bitデータ

温度測定
測定範囲:-30℃~+105℃
精度:±2℃(0℃~65℃)
分解能:16bitデータ

準備

LPS25HBの購入

LPS25HBは10端子のHLGAと呼ばれる形状です。
センサーを手ではんだ付けするのは不可能なのでモジュールの購入になると思います。

下の写真は秋月電子通商で購入したLPS25HBモジュールです。今回はサンプルプログラムでこのモジュールからデータを読み込みます。
また、このモジュールは、I2C通信とSPI通信のどちらの通信方式にも対応しています。

LPS25HBモジュール写真

Raspberry Piの通信設定とPythonの操作方法

Raspberry PiのI2C通信とSPI通信設定を有効にします。
下の記事でRaspberry Piの通信設定とPythonの基本操作を説明しています。

I2C通信でデータを取得する

モジュールとRaspberry Piの接続

接続図

接続写真

ブレッドボードを使用したLPS25HB【I2C通信】モジュールの接続写真 1
ブレッドボードを使用したLPS25HB【I2C通信】モジュールの接続写真 2

I2C通信プログラミング

プログラムコード

Pythonプログラムです。

import smbus
import time

#I2C設定
i2c = smbus.SMBus(1)
address = 0x5C

#Lセンサーの設定
i2c.write_byte_data(address, 0x20, 0x90)

#ファイルオープン(書き込みモード)
f = open("lps25hb.csv", "w")

#10回繰り返す
for i in range(10):
    
    #データ読み込み
    pxl = i2c.read_byte_data(address, 0x28)
    pl = i2c.read_byte_data(address, 0x29)
    ph = i2c.read_byte_data(address, 0x2A)
    tl = i2c.read_byte_data(address, 0x2B)
    th = i2c.read_byte_data(address, 0x2C)
    
    #データ変換
    prs = ph << 16 | pl << 8 | pxl
    tmp = th << 8 | tl
    
    #極性判断(温度)
    if tmp >= 32768:
        tmp -= 65536
    
    #物理量に変換
    prs = prs / 4096
    tmp = 42.5 + tmp / 480
    
    #表示
    print('Pressure: ' + str(prs))
    print('Temperature: ' + str(tmp))
    
    #データのCSV変換とファイルへの書き込み
    f.write(str(i + 1) + ',' + str(prs) + ',' + str(tmp) + '\n')
    
    #一時停止
    time.sleep(1)

f.close()

プログラムの説明

プログラムの流れは以下の通りです。

  1. I2C通信の設定
  2. センサーの設定
  3. 保存用ファイルをオープン
  4. センサーから気圧と温度データを取得
  5. データを物理量に変換し画面に表示
  6. CSV形式でファイルにデータを書き込む
  7. 10回繰り返したらファイルをクローズして終了

1.I2C通信の設定

#I2C設定
i2c = smbus.SMBus(1)
address = 0x5C

i2c = smbus.SMBus(1)
インスタンス生成です。使用するBus1を指定します。

address = 0x5C
アドレス指定です。LPS25HBのアドレスは0x5C(16進数)で、通信時に指定します。

Raspberry PiにLPS25HBを接続した状態で、LXTerminalから「i2cdetect -y 1」コマンドを入力すると、アドレスが0x5Cであることを確認出来ます。

2.センサーの設定

#センサーの設定
i2c.write_byte_data(address, 0x20, 0x90)

設定は write_byte_data(adr, reg, dat)関数を使用します。

第1引数 adr:I2C通信のアドレス
第2引数 reg:レジスタ(設定したい項目の記憶場所)
第3引数 dat:データ(レジスタに設定する内容)

サンプルプログラムではCTRL_REG1レジスタ設定をしています。レジスタの設定内容は以下の通りです。

i2c.write_byte_data(address, 0x20, 0x90)

0x20(CTRL_REG1レジスタ)
SIM(SPIモード 4wire/3wire)
RESET_AZ(オートゼロ機能リセット)
BDU(Block data update)
DIFF_EN(割り込みの発生 有効/無効)
ODR2-ODR0(出力データレート)
PD(パワーダウンモード)

0x90
SIM(0:SPIモード 4wire(デフォルト))
RESET_AZ(0:通常モード(デフォルト))
BDU(0:continuous update(デフォルト))
DIFF_EN(0:割り込みの発生無効(デフォルト))
ODR2-ODR0(001:出力データレート 気圧1Hz、温度1Hz)
PD(1:アクティブモード)

データシートの『8.6 CTRL_REG1 (20h)』で詳細を確認できます。

PD ODR2 ODR1 ODR0 DIFF_EN BDU RESET_AZ SIM
1 1 0 0
9 0

3.保存用ファイルをオープン

#ファイルオープン(書き込みモード)
f = open("lps25hb.csv", "w")

“lps25hb.csv”ファイルを書き込みモードでオープンします。
ファイルが存在しない場合は新規作成します。存在する場合は上書き保存します。

上書きせずに追記する場合は、2番目の引数を “w” から “a” にします。
ファイルは、/home/pi ディレクトリに保存されます。

4.センサーから気圧と温度データを取得

#データ読み込み
pxl = i2c.read_byte_data(address, 0x28)
pl = i2c.read_byte_data(address, 0x29)
ph = i2c.read_byte_data(address, 0x2A)

取得は read_byte_data(adr, reg)関数を使用します。

第1引数 adr:I2C通信のアドレス
第2引数 reg:レジスタ(測定データの記憶場所)

気圧データは3つのレジスタから、温度データは2つのレジスタから取得します。

気圧データの取得

i2c.read_byte_data(address, 0x28)
i2c.read_byte_data(address, 0x29)
i2c.read_byte_data(address, 0x2A)

24bitデータです。レジスタアドレスは0x280x290x2A

LPS25HB 気圧24ビットデータのアドレス
tl = i2c.read_byte_data(address, 0x2B)
th = i2c.read_byte_data(address, 0x2C)

温度データの取得

i2c.read_byte_data(address, 0x2B)
i2c.read_byte_data(address, 0x2C)

16bitデータです。レジスタアドレスは0x2B0x2C

LPS25HB 温度16ビットデータのアドレス

5.データを物理量に変換し画面に表示

#データ変換
prs = ph << 16 | pl << 8 | pxl
tmp = th << 8 | tl

①気圧データを24bit、②温度データを16bitにします。

24bitデータ
16bitデータ
#極性判断(温度)
if tmp >= 32768:
    tmp -= 65536

if tmp >= 32768:
tmp -= 65536

2の補数表現を符号ありに変換します。

16bitデータ 符号なし 符号あり
1000000000000000 32768 -32768
1000000000000001 32769 -32767
1111111111111110 65534 -2
1111111111111111 65535 -1
0000000000000000 0 0
0000000000000001 1 1
0000000000000010 2 2
0111111111111110 32766 32766
0111111111111111 32767 32767

2の補数の詳しい説明はこちら
2の補数」(2021年10月12日 (火) 17:00 UTCの版)『ウィキペディア日本語版』

#物理量に変換
prs = prs / 4096
tmp = 42.5 + tmp / 480

prs = prs / 4096
tmp = 42.5 + tmp / 480

データを物理量に変換します。
気圧は4096で割り、温度は480で割ります(データシートを参考にしています)。

#表示
print('Pressure: ' + str(prs))
print('Temperature: ' + str(tmp))

print(‘Pressure: ‘ + str(prs))
print(‘Temperature: ‘ + str(tmp))

気圧データと温度データを画面に表示します。

6.CSV形式でファイルにデータを書き込む

#データのCSV変換とファイルへの書き込み
f.write(str(i + 1) + ',' + str(prs) + ',' + str(tmp) + '\n')

f.write(str(i + 1) + ‘,’ + str(prs) + ‘,’ + str(tmp) + ‘\n’)

f.write()のカッコの中をファイルに書き込みます。

カッコの中は、データをカンマ区切りのCSV形式にしています。
str(i+1) と str(out)をカンマで区切っています。最後に改行コード(\n)を追加します。

CSV形式の詳しい説明はこちら
Comma-Separated Value」(2021年10月25日 (月) 05:33 UTCの版)『ウィキペディア日本語版』

7.10回繰り返したらファイルをクローズして終了します

#10回繰り返す
for i in range(10):

for i in range(10):
繰り返し命令です。10回繰り返します。

※この『for i in range(10):』は、15行目のfor文です。

f.close()

f.close()
ファイルをクローズします。

プログラムの実行結果

プログラムを実行します。

①Runボタンを押します。
②気圧データと温度データを1秒間隔で10回画面に表示します。

PythonのRunボタン
LPS25HBのプログラムの実行結果

プログラムを実行すると、/home/pi/ディレクトリにlps25hb.csvファイルが作成されます。

③CSV形式で10回分のデータが保存されています。

lps25hb.csvファイルの内容

lps25hb.csvファイル

以上、LPS25HBからI2C通信で気圧データと温度データを読み込んでCSV形式で保存するサンプルでした。

発生したトラブル

症状

I2C通信のreadでも writeでも、数回通信を繰り返すと Remote I/O error を発生して止まります。

I2C通信トラブル Pythonエラー

原因と対策

プログラムを確認しましたが悪い場所が分からなかったので、オシロスコープを使って信号を確認したところ、電位が定まっていない信号があることが分かりました。

電位の異常なのでハードウェア周りに問題が有る可能性が高いと考え調査したところ、モジュールの4番ピン(I2Cアドレス決定ピン)が未接続になっており、本来は電源かGNDに接続して電位を確定する必要がありました。

4番ピンが未接続であっても「i2cdetect」コマンドの返送が[0x5C]と返ってきていたので、正常に動作していると思い、気づかずに4番ピンを未接続のままにしていたことが原因です。

I2C通信トラブル I2C信号エラー

対策は、4番ピンをGNDに接続し電位を確定させました。
それからはエラーは発生していません。

SPI通信でデータを取得する

モジュールとRaspberry Piの接続

接続図

ブレッドボードを使用したLPS25HBモジュールとRaspberryPiの接続【SPI】

接続写真

ブレッドボードを使用したLPS25HB【SPI通信】モジュールの接続写真 1
ブレッドボードを使用したLPS25HB【SPI通信】モジュールの接続写真 2

SPI通信プログラミング

プログラムコード

Pythonプログラムです。

import spidev
import time

#SPI設定
spi = spidev.SpiDev()
spi.open(0, 0)
spi.max_speed_hz = 100000
spi.mode = 3

s_dat = [0x00, 0x00]
t_dat = [0x00, 0x00, 0x00]
p_dat = [0x00, 0x00, 0x00, 0x00]

#Lセンサーの設定
s_dat[0] = 0x20
s_dat[1] = 0x90
readByteArry = spi.xfer2(s_dat)

#ファイルオープン(書き込みモード)
f = open("lps25hb.csv", "w")

#繰り返し
for i in range(10):
    
    #設定
    p_dat[0] = 0x28
    p_dat[0] |= 0x80
    p_dat[0] |= 0x40
    
    t_dat[0] = 0x2B
    t_dat[0] |= 0x80
    t_dat[0] |= 0x40
    
    #データ読み込み
    readByteArry = spi.xfer2(p_dat)
    readByteArry = spi.xfer2(t_dat)
    
    #データ変換
    prs = p_dat[3] << 16 | p_dat[2] << 8 | p_dat[1]
    tmp = t_dat[2] << 8 | t_dat[1]
    
    #極性判断(温度)
    if tmp >= 32768:
        tmp -= 65536
    
    #物理量(気圧)に変換
    prs = prs / 4096
    
    #物理量(温度)に変換
    tmp = 42.5 + tmp / 480
    
    #表示
    print('Pressure: ' + str(prs))
    print('Temperature: ' + str(tmp))
    
    #データのCSV変換とファイルへの書き込み
    f.write(str(i+1) + ',' + str(prs) + ',' + str(tmp) + "\n")
    
    #一時停止
    time.sleep(1)

f.close()
spi.close

プログラムの説明

プログラムの流れは以下の通りです。

  1. SPI通信の設定
  2. センサーの設定
  3. 保存用ファイルをオープン
  4. センサーから気圧と温度データを取得
  5. データを物理量へ変換し画面に表示
  6. CSV形式でファイルにデータを書き込む
  7. 10回繰り返したらファイルをクローズして終了

1.SPI通信の設定

#SPI設定
spi = spidev.SpiDev()
spi.open(0, 0)
spi.max_speed_hz = 100000
spi.mode = 3

spi.open(0,0)
Bus0をチップセレクト0でオープンします。

spi.max_speed_hz = 100000
クロックのスピードを10kHzにします。

spi.mode = 3
SPI通信のハードウェア設定です。(mode 3は負論理の立下りエッジ検出)

SPI通信の詳しい説明はこちら
シリアル・ペリフェラル・インタフェース」(2021年10月21日 (木) 02:31 UTCの版)『ウィキペディア日本語版』

2.センサーの設定

#センサーの設定
s_dat[0] = 0x20
s_dat[1] = 0x90
readByteArry = spi.xfer2(s_dat)

s_dat[0] = 0x20
CTRL_REG1レジスタを指定

s_dat[1] = 0x90
指定したレジスタの設定

CTRL_REG1レジスタは、I2C通信の2.センサーの設定に詳しい説明があります。

3.保存用ファイルをオープン

#ファイルオープン(書き込みモード)
f = open("lps25hb.csv", "w")

“lps25hb.csv”ファイルを書き込みモードでオープンします。
ファイルが存在しない場合は新規作成します。存在する場合は上書き保存します。

上書きせずに追記する場合は、2番目の引数を “w” から “a” にします。
ファイルは、/home/pi ディレクトリに保存されます。

4. センサーから気圧と温度データを取得

#設定
p_dat[0] = 0x28
p_dat[0] |= 0x80
p_dat[0] |= 0x40
    
t_dat[0] = 0x2B
t_dat[0] |= 0x80
t_dat[0] |= 0x40

気圧:0x28
温度:0x2B
気圧、温度データを読み込むためのアドレス設定です。

共通:0x80
[読み込み/書き込み] を [読み込み]に設定します。

共通:0x04
読み込みを自動インクリメントに設定します。

アドレスについては、I2C通信の4.センサーから気圧と温度データを取得に詳しい解説があります。

#データ読み込み
readByteArry = spi.xfer2(p_dat)
readByteArry = spi.xfer2(t_dat)

気圧データと温度データを取得します。

p_dat:気圧データ
t_dat:温度データ

5.データを物理量に変換し画面に表示

(I2C通信の5.データを物理量に変換し画面に表示で詳しい解説をしています。)

#データ変換
prs = p_dat[3] << 16 | p_dat[2] << 8 | p_dat[1]
tmp = t_dat[2] << 8 | t_dat[1]

8bitのデータを、気圧データ24bitと温度データ16bitに変換します。

#極性判断(温度)
if tmp >= 32768:
    tmp -= 65536

if(out_x >= 2048):
out_x = out_x – 4096

2の補数表現を符号ありに変換します。

#物理量(気圧)に変換
prs = prs / 4096
    
#物理量(温度)に変換
tmp = 42.5 + tmp / 480

データを物理量に変換します。
気圧は4096で割り、温度は480で割ります(データシートを参考にしています)

#表示
print('Pressure: ' + str(prs))
print('Temperature: ' + str(tmp))

気圧データと温度データを画面に表示します。

6.CSV形式でファイルにデータを書き込

#データのCSV変換とファイルへの書き込み
f.write(str(i+1) + ',' + str(prs) + ',' + str(tmp) + "\n")

f.write(str(i+1) + ‘,’ + str(prs) + ‘,’ + str(tmp) + “\n”)

f.write()のカッコの中をファイルに書き込みます。

カッコの中は、データをカンマ区切りのCSV形式にしています。
str(i+1) と str(out)をカンマで区切っています。最後に改行コード(\n)を追加します。

7.10回繰り返したらファイルをクローズして終了します

#繰り返し
for i in range(10):

for i in range(10):
繰り返し命令です。10回繰り返します。

※この『for i in range(10):』は、23行目のfor文です。

f.close()

f.close()
ファイルをクローズします。

プログラムの実行結果

プログラムの実行結果は、I2C通信時の実行結果と同じなので割愛します。

まとめ

LPS25HBモジュールからRaspberry PiにI2C通信とSPI通信でデータを読み込んで表示と保存するサンプルでした。如何でしたでしょうか。

今回は、I2C通信でトラブルが発生したので原因と対策も記載しました。

完全に通信が出来ないわけではなかったので、ソフトウェアを疑っていたのですが、ソースコードを極限まで削除してもダメだったので、信号を調べて原因が分かったという感じです。

プログラミングやソフトウェアの記事です。

コメント