気温センサーBMP180のI2C読み取り
Rasberry Pi Picoを用いたI2Cの読み取りについての備忘録です。
プログラミング初心者なので、センサーのデータを読むことが出来ただけで
大分進歩した感じで、非常に嬉しいものです。
気温/気圧/高度センサーのBMP180を用いました。
今回は、気温のみの読み取りになりますが、気圧/高度にも挑戦したいと思っています。
ちなみに、I2C読み取りの学習のために、BMP180用にクラスを作成していない
初心者が書きそうなプログラムコードになっているので、ご注意ください。
接続
Picoの3.3V --- センサーのVCC
PicoのGND --- センサーのGND
PicoのGPIO0 --- SDA
PicoのGPIO1 --- SCL
コード
from machine import Pin, I2C
import time
import ustruct
# I2Cに使うピンの設定
i2c = I2C(0, scl=Pin(1), sda=Pin(0), freq=100000)
# デバイスのアドレススキャン
address = i2c.scan()[0]
print("address is:" + hex(address))
#I2Cアドレス119のデバイスのレジスタ0xAA~0xBFまで2Byteごと読み取り
#BMP180のセンサー補正値読み取り
AC1 = i2c.readfrom_mem(address,0xAA,2)
AC2 = i2c.readfrom_mem(address,0xAC,2)
AC3 = i2c.readfrom_mem(address,0xAE,2)
AC4 = i2c.readfrom_mem(address,0xB0,2)
AC5 = i2c.readfrom_mem(address,0xB2,2)
AC6 = i2c.readfrom_mem(address,0xB4,2)
B1 = i2c.readfrom_mem(address,0xB6,2)
B2 = i2c.readfrom_mem(address,0xB8,2)
MB = i2c.readfrom_mem(address,0xBA,2)
MC = i2c.readfrom_mem(address,0xBC,2)
MD = i2c.readfrom_mem(address,0xBE,2)
#補正値ビット列を10進数へ変換
#unpackするとタプルで返すため、[0]で先頭データを読み取る
fmt = '>h' #short big-endian
fmt2 = '>H' #unsigned short big-endian
AC1_x = ustruct.unpack(fmt, AC1)[0]
AC2_x = ustruct.unpack(fmt, AC2)[0]
AC3_x = ustruct.unpack(fmt, AC3)[0]
AC4_x = ustruct.unpack(fmt2, AC4)[0]
AC5_x = ustruct.unpack(fmt2, AC5)[0]
AC6_x = ustruct.unpack(fmt2, AC6)[0]
B1_x = ustruct.unpack(fmt, B1)[0]
B2_x = ustruct.unpack(fmt, B2)[0]
MB_x = ustruct.unpack(fmt, MB)[0]
MC_x = ustruct.unpack(fmt, MC)[0]
MD_x = ustruct.unpack(fmt, MD)[0]
#0xF4に0x2Eを書くと気温測定を開始
i2c.writeto_mem(address,0xF4, bytearray([0x2E]))
time.sleep(0.005)
#補正前の気温データの読み取り
UT = i2c.readfrom_mem(address,0xF6,2)
UT_raw = ustruct.unpack(fmt2, UT)[0]
#気温の計算
X1 = (UT_raw - AC6_x)*AC5_x/2**15
X2 = MC_x*2**11/(X1 + MD_x)
B5 = X1 + X2
Temp = (B5 + 8)/2**4/10
するとこんな感じで出力されます。
address is:0x77
AC1: 8233
AC2: -1091
AC3: -14152
AC4: 33442
AC5: 25693
AC6: 16550
B1: 6515
B2: 39
MB: -32768
MC: -11786
MD: 2398
Temperature: 24.36 C
つまづきやすいのは、タプルの扱いでしょうか。
address = i2c.scan() でもアドレスは取得できるのですが、複数データの入ったタプルというものになっており、
address = i2c.scan()[0] という風に最初のデータを参照しないとエラーになってしまいました。
ustruct.unpack の部分も同じく、アンパックするとタプルになるようで、タプルの最初のデータをセンサーの補正値として取り出しています。
ここでのアンパックはレジスタの0,1のデータを10進数に戻す作業です。
fmt = '>h' #short big-endian
に関しては、センサーのメモリから取り出したビットデータをどの順に並べて、
どの型(short、int、longなど)に変換しますかという部分です。
上のコードは基本的には以下を参考にしています。
micropython-bmp180/bmp180.py at master · micropython-IMU/micropython-bmp180 · GitHub
こちらでは、読み取りからunpackを1行で書いています。手慣れたものですね(^^ ;
structに関しては以下も参考になります
なかなか経験がないと、I2Cの読み取りも大変ですね。
少しづつ経験値を増やしていきたいです。