LoginSignup
2
0

More than 3 years have passed since last update.

サーマルカメラ(サーモ AI デバイス TiD) Python BME280編

Last updated at Posted at 2021-01-10

BOSCH 温湿度気圧センサ BME280の温湿度・気圧データを、I2C通信で取得します。


  1. 紹介編
  2. センサ編
  3. センサケース編
  4. Raspberry Pi編
  5. Python編
    5.1 Form編
    5.2 オムロン 非接触温度センサ D6T-44L-06編
    5.3 Pololu 測距センサ VL53L0X編
    5.4 BOSCH 温湿度・気圧センサ BME280
    5.5 シャットダウン・再起動スイッチ編
    5.6 OpenCV編
    5.7 高速化編

bme280.jpg
Raspberry Pi上のPythonでI2Cを制御する為に、smbusモジュールを使用します。
smbusモジュールがインストールされていない場合、下記コマンドでインストールしてください。

pip install smbus

bme280.pyはパッケージとしてimportして使用しますが、テスト用に単体で温湿度・気圧データを取得できます。
bme280.py (ZIPで圧縮済)

#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
BM280 script.
=============
Temperature: -40 to +85 [degC]
Dumidity: 0 ot 100[%]
barometer: 300 to 1100[hPa]
"""
i2c_enable = False
try:
    import smbus
    i2c_enable = True
except:
    i2c_enable = False

import random
import time


class BME280():
    def __init__(self):
        self.bus_number  = 1
        self.i2c_address = 0x76
        self.i2c_enable = i2c_enable

        if self.i2c_enable:
            self.bus = smbus.SMBus(self.bus_number)
        else:
            self.bus = self.SMBus(self.bus_number)
            return

        self.digT = []
        self.digP = []
        self.digH = []

        self.t_fine = 0.0

        self.setup()
        self.get_calib_param()

    @property
    def barometer(self):
        result = float(f'{random.uniform(1020.0, 1040.0):.2f}')
        if self.i2c_enable == False:
            return result

        # For I2C error at pushed power switch.
        try:
            pres_raw = self._read_bus_data('barometer')
        except:
            return result

        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 - pres_raw) - (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)  

        #print('pressure : %7.2f hPa' % (pressure/100))
        result = float(f'{pressure/100:7.2f}')
        return result

    def get_calib_param(self):
        if self.i2c_enable == False:
            return

        calib = []

        for i in range (0x88,0x88+24):
            calib.append(self.bus.read_byte_data(self.i2c_address,i))
        calib.append(self.bus.read_byte_data(self.i2c_address,0xA1))
        for i in range (0xE1,0xE1+7):
            calib.append(self.bus.read_byte_data(self.i2c_address,i))

        self.digT.append((calib[1] << 8) | calib[0])
        self.digT.append((calib[3] << 8) | calib[2])
        self.digT.append((calib[5] << 8) | calib[4])
        self.digP.append((calib[7] << 8) | calib[6])
        self.digP.append((calib[9] << 8) | calib[8])
        self.digP.append((calib[11]<< 8) | calib[10])
        self.digP.append((calib[13]<< 8) | calib[12])
        self.digP.append((calib[15]<< 8) | calib[14])
        self.digP.append((calib[17]<< 8) | calib[16])
        self.digP.append((calib[19]<< 8) | calib[18])
        self.digP.append((calib[21]<< 8) | calib[20])
        self.digP.append((calib[23]<< 8) | calib[22])
        self.digH.append( calib[24] )
        self.digH.append((calib[26]<< 8) | calib[25])
        self.digH.append( calib[27] )
        self.digH.append((calib[28]<< 4) | (0x0F & calib[29]))
        self.digH.append((calib[30]<< 4) | ((calib[29] >> 4) & 0x0F))
        self.digH.append( calib[31] )

        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 

    @property
    def humidity(self):
        result = float(f'{random.uniform(10.0, 60.0):.2f}')
        if self.i2c_enable == False:
            return result

        # For I2C error at pushed power switch.
        try:
            hum_raw = self._read_bus_data('humidity')
        except:
            return result

        var_h = self.t_fine - 76800.0
        if var_h != 0:
            var_h = (hum_raw - (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
        #print('hum : %6.2f %' % (var_h))
        result = float(f'{var_h:.2f}')
        return result

    def _read_bus_data(self, data_type):
        """
        data_tpye: 'temperature' or 'hidumity' or 'barometer'
        """
        data = []

        for i in range (0xF7, 0xF7+8):
            data.append(self.bus.read_byte_data(self.i2c_address,i))

        if data_type == 'barometer':
            return (data[0] << 12) | (data[1] << 4) | (data[2] >> 4)
        elif data_type == 'humidity':
            return (data[6] << 8) | data[7]
        elif data_type == 'temperature':
            return (data[3] << 12) | (data[4] << 4) | (data[5] >> 4)
        else:
            return [0]

    def read_data(self):
        t = self.temperature
        h = self.humidity
        p = self.barometer
        return [t, h, p]

    def setup(self, ):
        osrs_t = 1            #Temperature oversampling x 1
        osrs_p = 1            #Pressure oversampling x 1
        osrs_h = 1            #Humidity oversampling x 1
        mode   = 3            #Normal mode
        t_sb   = 5            #Tstandby 1000ms
        filter = 0            #Filter off
        spi3w_en = 0          #3-wire SPI Disable

        ctrl_meas_reg = (osrs_t << 5) | (osrs_p << 2) | mode
        config_reg    = (t_sb << 5) | (filter << 2) | spi3w_en
        ctrl_hum_reg  = osrs_h

        self.write_reg(0xF2,ctrl_hum_reg)
        self.write_reg(0xF4,ctrl_meas_reg)
        self.write_reg(0xF5,config_reg)

    # Dummy SMBus.
    class SMBus():
        def __init__(self, *args, **kwargs):
            pass

    @property
    def temperature(self):
        result = float(f'{random.uniform(20.0, 40.0):.2f}')
        if self.i2c_enable == False:
            return result

        # For I2C error at pushed power switch.
        try:
            temp_raw = self._read_bus_data('temperature')
        except:
            return result

        v1 = (temp_raw / 16384.0 - self.digT[0] / 1024.0) * self.digT[1]
        v2 = (temp_raw / 131072.0 - self.digT[0] / 8192.0) * (temp_raw / 131072.0 - self.digT[0] / 8192.0) * self.digT[2]
        self.t_fine = v1 + v2
        temperature = self.t_fine / 5120.0

        result = float(f'{temperature:.2f}')
        return result

    def write_reg(self, reg_address, data):
        if self.i2c_enable == False:
            return

        try:
            self.bus.write_byte_data(self.i2c_address, reg_address, data)
        except:
            self.i2c_enable = False
            self.bus = self.SMBus(self.bus_number)


if __name__ == '__main__':
    em = BME280()
    while True:
        print(em.read_data())
        #print(em.barometer)
        #print(em.humidity)
        #print(em.temperature)
        time.sleep(0.5)

YouTube: サーマルカメラ(サーモ AI デバイス TiD) Python編
web: サーモ AI デバイス TiD Python BME280編 (URLが変更されました)

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0