スイッチサイエンスさんの(BME-280)プログラムを元に、マイクロパイソンでなるべく簡単に使えるようなBME280のライブラリーを制作してみました。
BME280
主な特徴
- 温度測定範囲:-40℃ ~ +85℃(精度±1.0℃)
- 測定湿度範囲:0% ~ 100% RH(精度±3% RH)
- 気圧測定範囲:300 ~ 1100 hPa(精度±1 hPa)
- インターフェース:I2C/SPI対応
- 低消費電力:IoTデバイスにも適した設計
準備
必要なもの(BME280センサー、マイコンボード、開発環境Thonny)
今回はi2c接続
接続方法(ラズベリーパイpico)
接続例
今回はこのように接続してみました。

マイクロPython用のライブラリー
スイッチサイエンスさんのサンプルプログラムを元にアレンジして作ってみました、他にもプログラムする方法はあると思いますが、今回はこのようになりました。
from machine import Pin,I2C
import time
class Bme_280:
DEVICE_ADDR = 0x76
digT = []
digP = []
digH = []
t_fine = 0.0
def __init__(self, id1=0,scl_pin = 1,sda_pin = 0):
self.i2c = I2C(id1,scl=Pin(scl_pin),sda=Pin(sda_pin),freq=400000)
self.int280()
self.get_calib_param()
def int280(self):
self.i2c.writeto_mem(self.DEVICE_ADDR, 0xF2, bytes([0x01]))
self.i2c.writeto_mem(self.DEVICE_ADDR, 0xF4, bytes([0x27]))
self.i2c.writeto_mem(self.DEVICE_ADDR, 0xF5, bytes([0xA0]))
time.sleep_ms(50)
def get_calib_param(self):
calib_t = bytearray(6)
self.i2c.readfrom_mem_into(0x76, 0x88, calib_t)
self.digT.append((calib_t[1] << 8) | calib_t[0])
self.digT.append((calib_t[3] << 8) | calib_t[2])
self.digT.append((calib_t[5] << 8) | calib_t[4])
calib_p = bytearray(0x12)
self.i2c.readfrom_mem_into(0x76, 0x8E, calib_p)
self.digP.append((calib_p[1] << 8) | calib_p[0])
self.digP.append((calib_p[3] << 8) | calib_p[2])
self.digP.append((calib_p[5] << 8) | calib_p[4])
self.digP.append((calib_p[7] << 8) | calib_p[6])
self.digP.append((calib_p[9] << 8) | calib_p[8])
self.digP.append((calib_p[11] << 8) | calib_p[10])
self.digP.append((calib_p[13] << 8) | calib_p[12])
self.digP.append((calib_p[15] << 8) | calib_p[14])
self.digP.append((calib_p[17] << 8) | calib_p[16])
calibh=bytearray(1)
self.i2c.readfrom_mem_into(0x76, 0xA1, calibh)
self.digH.append(calibh[0])
calib_h = bytearray(8)
self.i2c.readfrom_mem_into(0x76, 0xE1, calib_h)
self.digH.append((calib_h[1] << 8) | calib_h[0])
self.digH.append(calib_h[2])
self.digH.append((calib_h[3] << 4) | (0x0F & calib_h[4]))
self.digH.append((calib_h[5] << 4) | ((calib_h[4] >> 4) & 0x0F))
self.digH.append(calib_h[6])
for i in range(1,2):
if self.digT[i] & 0x8000:
self.digT[i] = (-self.digT[i] ^ 0xFFFF) + 1
for i in range(1,8):
if self.digP[i] & 0x8000:
self.digP[i] = (-self.digP[i] ^ 0xFFFF) + 1
for i in range(0,6):
if self.digH[i] & 0x8000:
self.digH[i] = (-self.digH[i] ^ 0xFFFF) + 1
def read_data(self):
data1 = bytearray(0x08)
self.i2c.readfrom_mem_into(0x76,0xF7,data1)
prse_raw = (data1[0] << 16 | data1[1] << 8 | data1[2]) >> 4
temp_raw = (data1[3] << 16 | data1[4] << 8 | data1[5]) >> 4
hum_raw = data1[6] << 8 | data1[7]
comp_t = self.compensate_T(temp_raw)
comp_p = self.compensate_P(prse_raw)
comp_h = self.compensate_H(hum_raw)
return comp_t , comp_p , comp_h
def compensate_P(self,adc_P):
#global t_fine
pressure = 0.0
v1 = (self.t_fine / 2.0) - 64000.0
v2 = (((v1 / 4.0) * (v1 / 4.0)) / 2048) * self.digP[5]
v2 = v2 + ((v1 * self.digP[4]) * 2.0)
v2 = (v2 / 4.0) + (self.digP[3] * 65536.0)
v1 = (((self.digP[2] * (((v1 / 4.0) * (v1 / 4.0)) / 8192)) / 8) + ((self.digP[1] * v1) / 2.0)) / 262144
v1 = ((32768 + v1) * self.digP[0]) / 32768
if v1 == 0:
return 0
pressure = ((1048576 - adc_P) - (v2 / 4096)) * 3125
if pressure < 0x80000000:
pressure = (pressure * 2.0) / v1
else:
pressure = (pressure / v1) * 2
v1 = (self.digP[8] * (((pressure / 8.0) * (pressure / 8.0)) / 8192.0)) / 4096
v2 = ((pressure / 4.0) * self.digP[7]) / 8192.0
pressure = pressure + ((v1 + v2 + self.digP[6]) / 16.0)
return pressure/100
def compensate_T(self,adc_T):
#self.t_fine
v1 = (adc_T / 16384.0 - self.digT[0] / 1024.0) * self.digT[1]
v2 = (adc_T / 131072.0 - self.digT[0] / 8192.0) * (adc_T / 131072.0 - self.digT[0] / 8192.0) * self.digT[2]
self.t_fine = v1 + v2
temperature = self.t_fine / 5120.0
return temperature
def compensate_H(self,adc_H):
#global t_fine
var_h = self.t_fine - 76800.0
if var_h != 0:
var_h = (adc_H - (self.digH[3] * 64.0 + self.digH[4]/16384.0 * var_h)) * (self.digH[1] / 65536.0 * (1.0 + self.digH[5] / 67108864.0 * var_h * (1.0 + self.digH[2] / 67108864.0 * var_h)))
else:
return 0
var_h = var_h * (1.0 - self.digH[0] * var_h / 524288.0)
if var_h > 100.0:
var_h = 100.0
elif var_h < 0.0:
var_h = 0.0
return var_h
補足説明します。
calib_t = bytearray(6)
self.i2c.readfrom_mem_into(0x76, 0x88, calib_t)
でバイトデータを取得しましたが、下記のような方法でも取得できると思います。
calib_t[] = self.i2c.readfrom_mem(self.DEVICE_ADDR, 0x88, 6)
使いかた
例、上記のプログラムをmybme280.pyとして同じピコWのフォルダーに保存し呼び出して使います。
今回の使用例では、5回データが呼び出されて表示されます。
from mybme280 import Bme_280 # ライブラリー インポート
import time
test=Bme_280() #インスタンス(scl pin 変更できます)
for i in range(5):
print(test.read_data())
time.sleep(3)
MPY: soft reboot
(24.18851, 1007.21, 38.58954)
(24.19365, 1007.246, 38.20091)
(24.19365, 1007.273, 38.15309)
(24.17824, 1007.249, 38.12332)
(24.18338, 1007.202, 38.15317)
あとがき
bme280のデータの取得やキャリブレーションについては詳しく説明しませんでしたが、簡単に使えるライブラリーができたのではないかと思います。