稼働中

Raspberry Pi Pico(s_08)BMP280 用モジュール

BMP280 BMP280c.py

BMP280はデジタル温湿度センサーです。
BMP280はDIGITAL PRESSURE SENSORです。I2C通信で制御します。※詳細はBMP280のデータシートを参照ください。
Raspberry Pi PicoでBMP280センサーモジュールを使う自作の’BMP280c.py’を作成しました。記事d_10を元に作成しています。
使い方だけを記載します。’BMP280c.py’は末尾にあります。

使い方

■ファイル転送
Raspberry Pi Picoへ’BMP280c.py’を送った後でimportして使います。
※BMP280c.pyの末尾に、使用例(BMP280_ex.py)の## example以降をコピペ追加しても動作確認できます。
■メソッド
‘BMP280c’をimportすると「init_bmp280、reset_bmp280、para_bmp280、measure_bmp280、
id_bmp280、sleep_bmp280」のメソッドが使えるようになります。

BMP280(num=1,sda=10)で初期化します。
num:I2C0、I2C1の番号、デフォルトは1(I2C1)
sda:SDAのGPIO番号、デフォルトは10(GP10)

(01)init_bmp280()
ctrl_measレジスタ(0xF4)に’0x27’(oversampling ×1、power mode ノーマル)
configレジスタ(0xF5)に’0x52’(standby time 1000msec、IIR filter Filter無し、SPI not use)
を設定します。
(02)reset_bmp280()
レジスタをリセットします。
(03)measure_bmp280()
測定した温度、湿度をリストで返します。
(04)para_bmp280()
符号計算した補償用のデータ(digT,digP)をリストで返します。
(05)id_bmp280()
デバイスのID値を返します。
(06)sleep_bmp280()
スリープモードにします。
※詳細はBMP280のデータシートを参照ください。

使用例

BMP280で温湿度を測定します。
スレーブアドレス、ID値、補償用データ、温度、湿度をThonnyのShellに表示します。


BMP280c_ex.py
#!/usr/bin/env python
# -*- coding: utf-8 -*
from machine import I2C,Pin
import time
# BMP280 DIGITAL PRESSURE SENSOR / BOSCH
from BMP280c import BMP280

## exapmle -----------------------------------------
# instance BMP280(I2C_num,sda)
a=BMP280(1,10)

# address check
adr=a.i2c.scan()
print(adr, hex(adr[0]))   # [118] 0x76

## bmp280_ID register IDを表示
id=a.id_bmp280()
print('ID=',hex(id[0]))

## calibration data(Trimming parameter) を表示
T,P=a.para_bmp280()
print('digT',T)
print('digP',P)

## reset BMP280 リセット
a.reset_bmp280() # added line 

#BME280の初期化
a.init_bmp280()

## pressure and temperature
t,p= a.measure_bmp280()
print('t=',t)
print('p=',p)

実行結果

実行すると以下のようになりました。※Thonnyのshellに表示されます。


>>> %Run -c $EDITOR_CONTENT
[118] 0x76
ID= 0x58
digT [27981, 26705, -1000]
digP [37717, -10811, 3024, 2557, 124, -7, 15500, -14600, 6000]
t= 23.13            #温度
p= 1017.473         #湿度

一度、実行するとThonnyのShellでも操作できます。


>>> a.measure_bmp280()
(23.11, 1017.528)           #温度、湿度

BMP280用モジュール


#!/usr/bin/env python
# -*- coding: utf-8 -*-
from machine import I2C,Pin
import time
# pico_bmp280_class_01pyからからモジュールに
# BMP280 DIGITAL PRESSURE SENSOR / BOSCH
class BMP280:
    def __init__(self,num=1,sda=10):
        # BMP280 DIGITAL PRESSURE SENSOR / BOSCH
        #slave address
        self.addr=0x76    # [118] 0x76
        self.i2c=I2C(num, scl=Pin(sda+1), sda=Pin(sda), freq=100_000)
        #self.i2c=I2C(1, scl=Pin(11), sda=Pin(10), freq=100_000)      

        #t_fine carries fine temperature as global value
        self.t_fine = 0.0
        #Compensation data
        self.digT = [] # 補償用データ配列に保管
        self.digP = []

    ## read out
    # read start register set (yomidasu register address set)
    def r_reg(self,dat):
        buf=bytearray(1)
        buf[0]=dat
        self.i2c.writeto(self.addr,buf)
    # data write resister/data
    def w_reg(self,reg,dat):
        buf=bytearray(2)
        buf[0]=reg
        buf[1]=dat
        self.i2c.writeto(self.addr,buf)   
    # signed data fugo keisan 16bit
    def sig(self,dat):
        if dat >= (2**15):
            dat=dat-(2**16)
        return dat

    # compensation parameter 補正データ読み込み 
    def para_bmp280(self):    
        ## dig_T1~T3 0x88~0x8d 6byte
        self.r_reg(0x88)
        com_t=self.i2c.readfrom(self.addr,6)   # dig_T1~T3 6byte
        
        # 16bitデータに変換
        for i in range(0,6,2):
            self.digT.append((com_t[i+1] <<8) | (com_t[i])) # digT[0] unsigned
            # dig_T2,T3(digT1,2) signed data->fugou keisan
        for i in range(1,3):
            self.digT[i]=self.sig(self.digT[i])
        
        ## dig_P1~P9 0x8E~0x9f 18byte
        self.r_reg(0x8E)
        com_p=self.i2c.readfrom(self.addr,18)   # dig_P1~P9 6byte
        #print(com_t)
        # 16bitデータに変換
        for i in range(0,18,2):
            self.digP.append((com_p[i+1] <<8) | (com_p[i])) # digP[0] unsigned
        # dig_P2~P9(digP1~P8) signed data->fugou keisan 
        for i in range(1,9):
            self.digP[i]=self.sig(self.digP[i])
        return self.digT,self.digP

    ## init  測定設定
    def init_bmp280(self):
        self.w_reg(0xF4,0x27)   #Register 0xF4 “ctrl_meas”
        self.w_reg(0xF5,0x52)   #Register 0xF5 “config” 
        time.sleep_ms(10)    
    # reset    
    def reset_bmp280(self):
        self.w_reg(0xe0,0xb6) #Register 0xE0 “reset”    
        time.sleep_ms(2)
    # sleep
    def sleep_bmp280(self):
        self.w_reg(0xF4,0x24) #ctr_meas(0xF4) sleep 0b_00100100'0x24'
        time.sleep_ms(2)        
    # BMP280_ID
    def id_bmp280(self):
        self.r_reg(0xD0) #Register 0xD0 “id” 
        self.dat=self.i2c.readfrom(self.addr,1)   # 
        #print('ID=',hex(dat[0]))
        return self.dat 

    # compensation formula
    def bmp280_compensate_t(self,adc_T):
        #global  t_fine
        var1  = ( ((adc_T>>3)-(self.digT[0]<<1)) * (self.digT[1]) ) >> 11
        var2  = (( ( ((adc_T>>4)-(self.digT[0])) * ((adc_T>>4)-(self.digT[0])) ) >> 12) \
                 * (self.digT[2]))>> 14
        self.t_fine = var1 + var2 
        t = (self.t_fine * 5 + 128) >> 8
        t= t/100
        #print(var1,var2,t_fine)
        return t 

    def bmp280_compensate_p(self,adc_P):
        #global  t_fine
        var1 = (self.t_fine)-128000 
        var2 = var1 * var1 * self.digP[5] 
        var2 = var2 + ((var1*self.digP[4])<<17) 
        var2 = var2 + ((self.digP[3])<<35) 
        var1 = ( (var1 * var1 * self.digP[2]) >>8 ) + ( (var1 * self.digP[1]) <<12 ) 
        var1 = ( ( ((1)<<47) +var1 ) )*(self.digP[0])>>33

        if var1 == 0:
            return 0 # avoid exception caused by division by zero 

        p = 1048576 - adc_P 
        p = ( ( (p<<31)-var2 )*3125 )/var1  # p(float)
        #print('p',p,type(p)) # p 6.7116e+09 
        p=int(p)             # float >> int
        #print('p',p,type(p)) # p 6711599104 
        var1 = (self.digP[8] * (p>>13) * (p>>13)) >> 25
        var2 = (self.digP[7] * p) >>19 
        p = ( (p + var1 + var2) >>8) + (self.digP[6] <<4)
        p = p / 256 / 100
        return p

    ##  温度、気圧データ読込>>補償計算>>温度、気圧の値を返す
    def (self):
        ## temp press data register
        ## 測定データ読み込み press_msb 0xF7~temp_xlsb 0xFC  3+3 6byte
        self.r_reg(0xF7)
        dat=self.i2c.readfrom(self.addr,6)   # dig_P1~P9 6byte
        #print('r_mdata=',dat)    

        #データ変換
        dat_p = (dat[0] << 16 | dat[1] << 8 | dat[2]) >> 4  # 0xF7~0xF9 20bit
        dat_t = (dat[3] << 16 | dat[4] << 8 | dat[5]) >> 4  # 0xFA~0xFC 20bit
        #補正
        tmp=self.bmp280_compensate_t(dat_t)
        prs=self.bmp280_compensate_p(dat_p)
        return tmp,prs