以前使っていたセンサーモジュール AE-BME280 が手元にあったので、ネットワーク内から簡単に参照できるようにしてみました。
検証環境
・Raspberry Pi 2 Model B
・Raspbian Jessie Lite January 2017
・Apache 2.4.10
・PHP 5.6.29
・Python 2.7.9
準備
必要となるパッケージをインストールします。
$ sudo aptitude update
$ sudo apt-get install i2c-tools python-smbus apache2 php5
ちなみに、なぜPython単体ではなくApacheとPHPを使用するかですが、単にPythonでWebホストする方法がわからなかっただけです。
なのでセキュリティはガバガバです。あらかじめご了承ください。
ローカル向けなのでポート開放をしてはいけない(戒め)
センサーの接続
http://deviceplus.jp/hobby/raspberrypi_entry_039/
こ↑こ↓ を参考にRaspberry Piに接続します。
Python側
上記URL内のサンプルコードを少しいじっただけです。Python ワッカリマセーン
#coding: utf-8
import smbus
import time
bus_number = 1
i2c_address = 0x76
bus = smbus.SMBus(bus_number)
digT = []
digP = []
digH = []
t_fine = 0.0
def writeReg(reg_address, data):
bus.write_byte_data(i2c_address,reg_address,data)
def get_calib_param():
calib = []
for i in range (0x88,0x88+24):
calib.append(bus.read_byte_data(i2c_address,i))
calib.append(bus.read_byte_data(i2c_address,0xA1))
for i in range (0xE1,0xE1+7):
calib.append(bus.read_byte_data(i2c_address,i))
digT.append((calib[1] << 8) | calib[0])
digT.append((calib[3] << 8) | calib[2])
digT.append((calib[5] << 8) | calib[4])
digP.append((calib[7] << 8) | calib[6])
digP.append((calib[9] << 8) | calib[8])
digP.append((calib[11]<< 8) | calib[10])
digP.append((calib[13]<< 8) | calib[12])
digP.append((calib[15]<< 8) | calib[14])
digP.append((calib[17]<< 8) | calib[16])
digP.append((calib[19]<< 8) | calib[18])
digP.append((calib[21]<< 8) | calib[20])
digP.append((calib[23]<< 8) | calib[22])
digH.append( calib[24] )
digH.append((calib[26]<< 8) | calib[25])
digH.append( calib[27] )
digH.append((calib[28]<< 4) | (0x0F & calib[29]))
digH.append((calib[30]<< 4) | ((calib[29] >> 4) & 0x0F))
digH.append( calib[31] )
for i in range(1,2):
if digT[i] & 0x8000:
digT[i] = (-digT[i] ^ 0xFFFF) + 1
for i in range(1,8):
if digP[i] & 0x8000:
digP[i] = (-digP[i] ^ 0xFFFF) + 1
for i in range(0,6):
if digH[i] & 0x8000:
digH[i] = (-digH[i] ^ 0xFFFF) + 1
def readData():
data = []
for i in range (0xF7, 0xF7+8):
data.append(bus.read_byte_data(i2c_address,i))
pres_raw = (data[0] << 12) | (data[1] << 4) | (data[2] >> 4)
temp_raw = (data[3] << 12) | (data[4] << 4) | (data[5] >> 4)
hum_raw = (data[6] << 8) | data[7]
return [compensate_T(temp_raw), compensate_H(hum_raw), compensate_P(pres_raw)]
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)
return pressure;
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
temperature = t_fine / 5120.0
return 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] / 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
def setup():
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
writeReg(0xF2,ctrl_hum_reg)
writeReg(0xF4,ctrl_meas_reg)
writeReg(0xF5,config_reg)
# coding: utf_8
import bme280 as bme
bme.setup()
bme.get_calib_param()
data = bme.readData()
print str(data[0]) + "," + str(data[1]) + "," + str(data[2] / 100)
now.py の出力部分については、各数値をコンマ区切り(気温,湿度,気圧)で出力しています。
また、気圧はPaで出力されるので100で割ってhPaにしています。
sudo の壁
このPythonプログラム、実行しようとするとsudo権限が必要になります。よって
sudo python now.py
と実行するわけですが、PHPのexec()からsudo使えません。
なのでsudoers変えちゃいましょう。(セキュリティ?知らない子ですねぇ。)
以下の行を追記します。
www-data ALL=(root) NOPASSWD: ALL
PHP 側
あとはPython呼び出すだけです。
適当にデザインしました。
<?php $data = explode(",", exec("sudo python now.py")); ?>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Temp Monitor</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<link rel="stylesheet" href="css/font-awesome.min.css">
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-4" align="center" style="padding: 20px 10px">
<h2><i class="fa fa-thermometer-three-quarters"></i></h2>
<span class="num-large"><?= substr($data[0], 0, 2) ?></span>
<span class="num-small"><?= substr($data[0], 2, 3) ?> ℃</span>
</div>
<div class="col-md-4" align="center" style="padding: 20px 10px">
<h2><i class="fa fa-tint"></i></h2>
<span class="num-large"><?= substr($data[1], 0, 2) ?></span>
<span class="num-small"><?= substr($data[1], 2, 3) ?> %</span>
</div>
<div class="col-md-4" align="center" style="padding: 20px 10px">
<h2><i class="fa fa-tachometer"></i></h2>
<span class="num-large"><?= substr($data[2], 0, 4) ?></span>
<span class="num-small"><?= substr($data[2], 4, 3) ?> hPa</span>
</div>
</div>
<br>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
</body>
</html>
body {
background-color: #272727;
color: #fff;
font-family: "Segoe UI Light", sans-serif;
}
.num-large {
font-size: 5em;
}
.num-small {
font-size: 3em;
}
おわりに
基本的にガバガバです。気にしないでください。
もっと良い書き方はいくらでもあります。
リンク
・ラズベリーパイで温度・湿度・気圧をまとめて取得!AE-BME280でIC2通信 | Device Plus - デバプラ
http://deviceplus.jp/hobby/raspberrypi_entry_039/
・Font Awesome, the iconic font and CSS toolkit
http://fontawesome.io/
・Bootstrap · The world's most popular mobile-first and responsive front-end framework.
http://getbootstrap.com/