全然BLOGに手をつけてなく電子工作グダグダやってました。
流れ的にI2Cなので定番のBME280での温度・湿度・気圧測定です。
必要なもの一式組み込みます。(Python3ベース)
$ sudo apt-get -y install python3-dev $ sudo apt-get -y install python3-pip # pip3 入れる $ sudo apt-get -y install python3-gpiozero # pinout 使えるようにしてみる $ sudo apt-get -y install i2c-tools # pi OS(lite) には入ってないっぽい
モジュール[smbus2]入れます
$ pip3 install smbus2
BME280はデータシート見ながら&Python勉強。と
ソースぐちゃぐちゃですが貼り付けます。
#-------------------------------------------------------------------------------- # 0x80 ~ 0xA1 R 調整データ dig.T1 ~ T3,dig.P1 ~ P9,dig_H1 19? # 0xD0 R チップID chip_id [7-0] # 0xE0 W リセット reset [7-0] # 0xE1 ~ 0xF0 R 調整データ dig.H2 ~ H6 # 0xF2 R/W 制御レジスタ osrs_h[2-0] # 0xF3 R ステータス measuring,im_up_date # 0xF4 R/W 制御レジスタ osrc_t[2-0],osrs_p[2-0],mode[1-0] # 0xF5 R/W 設定レジスタ t_sb[2-0],filter[2-0],pi3w_en # 0xF7 R 圧力測定データ(HIGH) press.msb [7-0] # 0xF8 R 圧力測定データ(LOW) press.lsb [7-0] # 0xF9 R 圧力測定データ(exLOW) press.xlsb [7-4] # 0xFA R 温度測定データ (HIGH) temp.msb [7-0] # 0xFB R 温度測定データ (LOW) temp.lsb [7-0] # 0xFC R 温度測定データ (exLOW) temp.xlsb [7-4] # 0xFD R 湿度測定データ(HIGH) press.lsb [7-0] # 0xFE R 湿度測定データ(LOW) press.lsb [7-0] #-------------------------------------------------------------------------------- from smbus2 import SMBus bus_number = 1 i2c_address = 0x76 bus = SMBus(bus_number) digT = [] digP = [] digH = [] t_fine = 0.0 #-------------------------------------------------------------------------------- # Register Write #-------------------------------------------------------------------------------- def writeReg(reg_address, data): bus.write_byte_data(i2c_address,reg_address,data) #-------------------------------------------------------------------------------- # flg:0 DWORD,1:WORD,2:BYTE #-------------------------------------------------------------------------------- _DWORD = 0 _WORD = 1 _BYTE = 3 def unsigned2long(dt,flg=1): cf = 0x80000000 mk = 0xffffffff if flg & 1: cf >>= 16 mk >>= 16 if flg & 2: cf >>= 8 mk >>= 8 if dt & cf: dt = (-dt ^ mk)+1 return dt; #-------------------------------------------------------------------------------- # キャリブレーション # 0x88 - 0x8D T1(WORD),T2,T3(short) 6Byte # 0x8E - 0x9F P1(WORD),P2-P9(short) 18Byte # 0xA1 H1(BYTE) # 0xE1 H1(BYTE) #-------------------------------------------------------------------------------- def get_calib_param(): #---------------------------------------------------------------------------- # T1 ~ T3 for i in list(range(0x88,0x8E,2)): digT.append(bus.read_word_data(i2c_address,i)) #---------------------------------------------------------------------------- # P1 - P9 for i in list(range(0x8E,0xA0,2)): digP.append(bus.read_word_data(i2c_address,i)) #---------------------------------------------------------------------------- # H1 - H6 digH.append(bus.read_byte_data(i2c_address,0xA1)) #H1 digH.append(bus.read_word_data(i2c_address,0xE1)) #H2 digH.append(bus.read_byte_data(i2c_address,0xE3)) #H3 t = bus.read_word_data(i2c_address,0xE4) digH.append(((t & 0xFF) << 4) | ((t >> 8) & 0x0F)) #H4 0xE4 / 0xE5[3-0] => [11-4]/[3-0] t = (t >> 12) & 0x0F t = t | (bus.read_byte_data(i2c_address,0xE6) << 4) digH.append(t) #H5 0xE5[7-4] / 0xE6 => [3-0]/[11-4] digH.append(bus.read_byte_data(i2c_address,0xE7)) #H6 #---------------------------------------------------------------------------- # sign Flip # T2,T3 : (short) for i in range(1,2): digT[i] = unsigned2long(digT[i],_WORD) # P2 ~ P9 : (short) for i in range(1,9): digP[i] = unsigned2long(digP[i],_WORD) # H2,H4,H5 : (short) for i in [1,3,4]: digH[i] = unsigned2long(digH[i],_WORD) # H6 : (char) digH[5] = unsigned2long(digH[5],_BYTE) #-------------------------------------------------------------------------------- # データ読み込み # 0xF7 ~ 0xFE #-------------------------------------------------------------------------------- def readData(): data = [] for i in range (0xF7, 0xF7+8): data.append(bus.read_byte_data(i2c_address,i)) p_raw = (data[0] << 12) | (data[1] << 4) | (data[2] >> 4) t_raw = (data[3] << 12) | (data[4] << 4) | (data[5] >> 4) h_raw = (data[6] << 8) | data[7] t = compensate_T(t_raw) p = compensate_P(p_raw) h = compensate_H(h_raw) d = 0.81 * t + 0.01 * h * (0.99 * t - 14.3) + 46.3 return [t,p,h,d] #-------------------------------------------------------------------------------- # 圧力 #-------------------------------------------------------------------------------- def compensate_P(adc_P): global t_fine pressure = 0.0 v1 = (t_fine / 2.0) - 64000.0 v2 = (((v1 / 4.0) * (v1 / 4.0)) / 2048) * digP[5] v2 = v2 + ((v1 * digP[4]) * 2.0) v2 = (v2 / 4.0) + (digP[3] * 65536.0) v1 = (((digP[2] * (((v1 / 4.0) * (v1 / 4.0)) / 8192)) / 8) + ((digP[1] * v1) / 2.0)) / 262144 v1 = ((32768 + v1) * 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 = (digP[8] * (((pressure / 8.0) * (pressure / 8.0)) / 8192.0)) / 4096 v2 = ((pressure / 4.0) * digP[7]) / 8192.0 pressure = pressure + ((v1 + v2 + digP[6]) / 16.0) # print ("pressure:%7.2f hPa" % (pressure/100)) return pressure/100 #-------------------------------------------------------------------------------- # 温度 #-------------------------------------------------------------------------------- def compensate_T(adc_T): global t_fine v1 = (adc_T / 16384.0 - digT[0] / 1024.0) * digT[1] v2 = (adc_T / 131072.0 - digT[0] / 8192.0) * (adc_T / 131072.0 - digT[0] / 8192.0) * digT[2] t_fine = v1 + v2 return t_fine / 5120.0 #-------------------------------------------------------------------------------- # 湿度 #-------------------------------------------------------------------------------- def compensate_H(adc_H): global t_fine var_h = t_fine - 76800.0 if var_h != 0: var_h = (adc_H - (digH[3] * 64.0 + digH[4]/16384.0 * var_h)) var_h *= (digH[1] / 65536.0 * (1.0 + digH[5] / 67108864.0 * var_h * (1.0 + digH[2] / 67108864.0 * var_h))) else: return 0 var_h = var_h * (1.0 - 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 #-------------------------------------------------------------------------------- # Setup # 0xF2 [00000hhh] osrs_h 湿度 over sampling 0:skip 1:x1 2:x2 3:x4 4:x8 5~:x16 # 0xF4 [tttpppmm] osrs_t 温度 over sampling 0:skip 1:x1 2:x2 3:x4 4:x8 5~:x16 # osrs_p 圧力 over sampling 0:skip 1:x1 2:x2 3:x4 4:x8 5~:x16 # mode デバイスのセンサーモード # 0 : スリープ # 1-2: 強制 # 3 : 通常 # 0xF5 [tttfff0i] t_sb 通常モードでの休止状態の継続時間 # 0: 0.5ms # 1: 62.5ms # 2: 125.0ms # 3: 250.0ms # 4: 500.0ms # 5:1000.0ms # 6: 10.0ms # 7: 20.0ms # filter 0:OFF 1:2 2:4 3:8 5~:16 # spi3w 0:4WireSPI 1:3WireSPI #-------------------------------------------------------------------------------- def setup(): osrs_h = (1 ) # 湿度 oversampling x 1 osrs_t = (1 << 5) # 温度 oversampling x 1 osrs_p = (1 << 2) # 圧力 oversampling x 1 mode = (3 ) # Normal mode t_sb = (5 << 5) # Tstandby 1000ms filter = (0 << 2) # Filter off spi3w = (0 ) # 3-wire SPI Disable writeReg(0xF2,osrs_h ) # 制御レジスター osrs_h[2-0] writeReg(0xF4,osrs_t | osrs_p | mode ) # 制御レジスター osrs_t[2-0] osrs_p[2-0] mode[1-0] writeReg(0xF5,t_sb | filter | spi3w) # 設定レジスター t_sb [2-0] , filter [2-0] , pi3w_en #-------------------------------------------------------------------------------- # Start! # Addr:0xD0 chip_id [0x56,0x57,0x58:BMP280] / [0x60:BME280] #-------------------------------------------------------------------------------- setup() # 初期化 get_calib_param() # チップ固有の個体差パラメータ読込 if __name__ == '__main__': chip_id = bus.read_byte_data(i2c_address,0xD0); if chip_id == 0x60: print("BME280") else: print("BMP280") try: dat = readData() print("温度:%-3.2f℃" % dat[0]) print("気圧:%7.2fhPa" % dat[1]) print("湿度:%6.2f%" % dat[2]) print("不快指数:%3.2f"% dat[3]) except KeyboardInterrupt: pass #-------------------------------------------------------------------------------- #EOF
チップの型番チェックとモジュールとして呼び出しができるように設定しています。
不快指数も計算してみました。
>>> %Run bme280.py BME280 温度:27.78℃ 気圧:1007.67hPa 湿度: 35.88% 不快指数:73.53
コメント