概要
Raspberry Pi でSIM経由で通信する顔認証システムを作成し、認証結果を kintone で管理するシステムを構築します。
今回は、顔認証した時のオフィス環境データを取得するため Raspberry Pi で温湿度気圧センサの値を読み込むまでを行います。!
顔認証システム構築シリーズ
Raspberry Pi で顔を認識しファイルに保存する
https://qiita.com/yukataoka/items/7510217f4b6efdefff06
Amazon Rekognition で顔が同じか比較判定し、感情などの情報を取得する
https://qiita.com/yukataoka/items/3fde5d6b22255ff1aed9
Raspberry Pi でCO2センサを使う
https://qiita.com/yukataoka/items/a3b4065e8210b8f372ff
Raspberry Pi で温湿度気圧センサを使う
https://qiita.com/yukataoka/items/8f9046587c978e91f689
利用する温湿度気圧センサについて
今回は1モジュールで、温度、湿度、気圧が計測できる、スイッチサイエンスのBME280搭載 温湿度・気圧センサモジュールを用います。
測定精度は温度が±1℃、湿度が±3%、気圧が±1hPa と、オフィス環境の計測には十分な性能です。
BME280搭載 温湿度・気圧センサモジュール
https://www.switch-science.com/catalog/2236/
配線について
BME280 は I2C か SPI 通信で測定値を取得します。
よくあるI2C温湿度センサでは SDI、SCK と 3.3v 、GND のみの配線ですが、今回は気圧センサもあるためか、6つの配線が必要です。
Raspberry Pi の配線は、以下のサイトを参考に行います。
Raspberry Pi 2で温湿度・気圧センサのBME280をPythonから使う
https://qiita.com/masato/items/027e5c824ae75ab417c1
私の場合は以下のように配線しました。
SDI (BME280) -> SDA P03 (Raspberry Pi)
SCK (BME280) -> SCL P05 (Raspberry Pi)
GND (BME280) -> GND P06 (Raspberry Pi)
SDO (BME280) -> GND P09 (Raspberry Pi)
Vio (BME280) -> 3.3v P01 (Raspberry Pi)
CSB (BME280) -> 3.3v P17 (Raspberry Pi)
環境の設定
先の作業で、Pyton3 と pip3 の設定までは完了しています。
- I2C 通信の設定
sudo raspi-config で I2C 通信を設定します。
手順は以下です。
"5 Interfacing Option" を選択。
"P5 I2C" を選択。
"Yes" を選択し、raspi-config 完了後に再起動します。
再起動後に、センサが指定のI2Cアドレスで認識されているか確認します。
$ sudo i2cdetect -y 1
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- 76 --
I2Cアドレス76を使っていることが確認できます。
- Python3 の設定
I2C 通信用のライブラリィ smbus2 をインストールします。
$ sudo pip3 install smbus2
スイッチサイエンスのGitHub BME280 より、bme280_sample.py を入手します。
https://github.com/SWITCHSCIENCE/BME280
https://github.com/SWITCHSCIENCE/BME280/blob/master/Python27/bme280_sample.py
bme280_sample.py は Python2.7 用のプログラムです。
そのまま Python3 で実行すると、以下のエラーになります。
$ python3 bme280_sample.py
File "bme280_sample.py", line 95
print "pressure : %7.2f hPa" % (pressure/100)
^
SyntaxError: invalid syntax
以下のように print 文を修正すると、Python3 でも利用できます。
(前略)
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))
ef 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
temperature = t_fine / 5120.0
print("temp : %-6.2f ℃" % (temperature) )
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)) * (digH[1] / 65536.0 * (1.0 + digH[5] /$
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
print("hum : %6.2f %" % (var_h))
(後略)
修正後に実行すると、以下の結果を得ることができます。
$ python3 bme280.py
temp : 25.33 ℃
pressure : 997.92 hPa
hum : 58.60 %
Python3 の修正コード
スイッチサイエンスのサンプルはそのままだと使いづらいので、改良をしたものが以下です。
#!/usr/bin/python3
# -*- coding: utf-8 -*-
from smbus2 import SMBus
import time
class Bme280:
def __init__(self, busNumber=1, i2cAddress=0x76):
self.bus = SMBus(busNumber)
self.i2cAddress = i2cAddress
self.digT = []
self.digP = []
self.digH = []
self.timeFine = 0.0
self.presRaw = 0.0
self.tempRaw = 0.0
self.humRaw = 0.0
osrsT = 1 #Temperature oversampling x 1
osrsP = 1 #Pressure oversampling x 1
osrsH = 1 #Humidity oversampling x 1
mode = 3 #Normal mode
tSb = 5 #Tstandby 1000ms
filter = 0 #Filter off
spi3wEn = 0 #3-wire SPI Disable
ctrlMeasReg = (osrsT << 5) | (osrsP << 2) | mode
configReg = (tSb << 5) | (filter << 2) | spi3wEn
ctrlHumReg = osrsH
self.writeReg(0xF2,ctrlHumReg)
self.writeReg(0xF4,ctrlMeasReg)
self.writeReg(0xF5,configReg)
self.getCalibParam()
self.readData()
def writeReg(self, regAddress, data):
self.bus.write_byte_data(self.i2cAddress, regAddress, data)
def getCalibParam(self):
calib = []
for i in range (0x88,0x88+24):
calib.append(self.bus.read_byte_data(self.i2cAddress,i))
calib.append(self.bus.read_byte_data(self.i2cAddress,0xA1))
for i in range (0xE1,0xE1+7):
calib.append(self.bus.read_byte_data(self.i2cAddress,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
def readData(self):
data = []
for i in range (0xF7, 0xF7+8):
data.append(self.bus.read_byte_data(self.i2cAddress,i))
self.presRaw = (data[0] << 12) | (data[1] << 4) | (data[2] >> 4)
self.tempRaw = (data[3] << 12) | (data[4] << 4) | (data[5] >> 4)
self.humRaw = (data[6] << 8) | data[7]
def getPressure(self):
pressure = 0.0
v1 = (self.timeFine / 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 - self.presRaw) - (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 getTemperature(self):
v1 = (self.tempRaw / 16384.0 - self.digT[0] / 1024.0) * self.digT[1]
v2 = (self.tempRaw / 131072.0 - self.digT[0] / 8192.0) * (self.tempRaw / 131072.0 - self.digT[0] / 8192.0) * self.digT[2]
self.timeFine = v1 + v2
temperature = self.timeFine / 5120.0
return temperature
def getHumidity(self):
varH = self.timeFine - 76800.0
if varH != 0:
varH = (self.humRaw - (self.digH[3] * 64.0 + self.digH[4]/16384.0 * varH)) * (self.digH[1] / 65536.0 * (1.0 + self.digH[5] / 67108864.0 * varH * (1.0 + self.digH[2] / 67108864.0 * varH)))
else:
return 0
varH = varH * (1.0 - self.digH[0] * varH / 524288.0)
if varH > 100.0:
varH = 100.0
elif varH < 0.0:
varH = 0.0
return varH
if __name__ == '__main__':
sensor = Bme280()
try:
print("pressure : %7.2f hPa" % sensor.getPressure())
print("temperature : %-6.2f ℃" % sensor.getTemperature())
print("humidity : %6.2f %" % sensor.getHumidity())
except KeyboardInterrupt:
pass
なお、利用させていただいたスイッチサイエンスのライセンスは以下となります。
# Copyright (c) 2018 Switch Science
# This software is released under the MIT License.
# http://opensource.org/licenses/mit-license.php
結果
改良後、以下のように計測値が確認できました。
$ python3 bme280.py
pressure : 966.44 hPa
temperature : 23.64 ℃
humidity : 58.99 %
参考サイト
BME280搭載 温湿度・気圧センサモジュール
https://www.switch-science.com/catalog/2236/
スイッチサイエンス / BME280
https://github.com/SWITCHSCIENCE/BME280
Raspberry Pi 2で温湿度・気圧センサのBME280をPythonから使う
https://qiita.com/masato/items/027e5c824ae75ab417c1
40: Raspberry Pi3 で BME280 温度、湿度、気圧計センサー
https://qiita.com/KZ2/items/68076fa6a086d89f668e