温度・湿度・気圧・照度をRaspberry Pi 3B+ で24時間監視する
温湿度・気圧をまとめて計測できてしまうBME280と言う超小型のセンサモジュールと、照度が計れるTSL2561センサモジュールが手に入ったので、Raspberry 3B+に繋いで、自宅の24時間環境モニタリングをやってみました!
計測したデータをこんな感じで可視化してみます。
使ったモノ
- Raspberry Pi 3B+、Raspbian Stretch
$ uname -a
Linux rpi3-03p 4.14.52-v7+ #1123 SMP Wed Jun 27 17:35:49 BST 2018 armv7l GNU/Linux
$ cat /etc/debian_version
9.4
- 温湿度・気圧センサ(BME280)
- 照度センサ(TLS2561)
- ソケット付きケーブル(ばら売りで安く売っていた物)
物理的な接続
センサとの通信は、I2C(アイ・スクエアド・シー)で行います。
1つのI2Cポートに2つのセンサモジュールをつなぐので、以下のようにまとめて1本になるようにケーブルをハンダ付けしました。
ラズベリーパイのポートは gpio readall で確認できるので、3.3V、SDA.1、SCL.1、0V(GND)を見つけて接続します。
物理ピンで3.3V(#1/赤)、SDA.1(#3/橙)、SCL.1(#5/白)、GND(#6/黒)に接続します。
接続した様子はこんな感じです。※念のため電源を落とした状態で配線しましょう。
センサデータの読み取り
コチラのサイトを参考にさせていただきました。
RPZ-IR-Sensor
raspi-config で I2C を使えるようにする
ラズパイのインターフェースの設定でI2Cを使えるようにします。
コンソールで設定する場合は、SSHで接続するか直接ターミナルを開いて、sudo raspi-config を実行し、インターフェース>I2C>Enable を選んだ後再起動します。
GUIで設定する場合には、設定>Raspberry Pi の設定>インターフェイス>I2C「有効」を選択します。
サンプルプログラムを入手する
上記の参考サイトから「rpz-sensor.zip」を入手します。
ラズベリーパイの適当なフォルダ(ここでは ${HOME}/src/env-monitoring/
)を作って展開します。
$ mkdir -p ~/src/env-monitoring/
$ cd ~/src/env-monitoring/
$ wget http://indoor.lolipop.jp/IndoorCorgiElec/RPZ-IR-Sensor/rpz-sensor.zip
$ unzip rpz-sensor.zip
動作テスト
先ほど展開してできたディレクトリに入ると、readme.txtがあるので一通り目を通しておきましょう。
$ cd rpz-sensor
$ ls
cpp python3 readme.txt
python3を使っていきます。
なお、python3が入っていない場合は初めにaptで入手しておきましょう。
$ sudo apt install python3
$ cd ./python3
まずは、bme280i2c.py で温湿度・気圧の情報を取得・表示します。
$ ./bme280i2c.py
BME280 0x76
dig_H1 : 75
dig_H2 : 364
dig_H3 : 0
dig_H4 : 312
dig_H5 : 50
dig_H6 : 30
dig_P1 : 37711
dig_P2 : -10593
dig_P3 : 3024
dig_P4 : 8371
dig_P5 : -54
dig_P6 : -7
dig_P7 : 9900
dig_P8 : -10230
dig_P9 : 4285
dig_T1 : 28172
dig_T2 : 26620
dig_T3 : 50
t_fine : 140750
adc_T : 537375
adc_P : 311316
adc_H : 29711
Temp : 27.5C
Pressure : 1003.1hPa
Humidity : 54.1%
1回目はおかしな値になっている場合があり、普通の環境では有り得ない値(Pressureの値が600になっていたりする)になっていたらもう1度実行してみてください。
(台風が近づいているので、若干低めですね。もうすぐ1000hPaを下回るかも。)
次に、tsl2561.py で照度情報を取得・表示しますが、モジュール基板の状態に併せてアドレスを修正します。
入手した基板のアドレスピンは未接続だったので、スイッチサイエンスさんの「光センサ TSL2561 の使い方」を参考に、vim tsl2561.py
でmain()のアドレス部分を書き換えます。
# tsl2561 = TSL2561(0x29)
tsl2561 = TSL2561(0x39)
実行してみましょう!
$ ./tsl2561.py
ADC Time : 402ms
ADC Gain : High
ch0 : 0x624
ch1 : 0x1BF
Lux : 31.0lux
31 lux !
ちょっと暗いのは、、、夜中の部屋の隅っこだからですw
最後に、ログファイルを作成できる rpz_sensor.py を使ってみます。
まずは必要になるdocoptパッケージをインストールします。
sudo pip3 install docopt
また、tsl2561.py の時と同じように、0x29を0x39に書き換えておきます。
ではセンサデータを表示してみましょう。
$ ./rpz_sensor.py
BME280 0x76
Temp : 30.4C
Pressure : 1002.8hPa
Humidity : 48.8%
TSL2561
Lux : 30.9lux
やった!
これで、温度・湿度・気圧・照度を取得できるようになりました!
CSVファイルとして書き出す
rpz_sensor.py にはログファイルを出力する機能があります。./rpz_sensor.py -l log.csv
のようにlオプションを付けて、ファイルを指定することで、csv形式のファイルが作成されます。
中身はこんな感じ。
$ cat log.csv
Time,Temp ch1,Temp ch2,Pressure ch1,Pressure ch2,Humidity ch1,Humidity ch2,Lux
2018/08/08 01:14,30.6,,1002.7,,48.7,,30.8
2018/08/08 01:16,30.0,,1002.8,,50.0,,30.8
日付の表示形式イマイチなので修正します。rpz_sensor.pyの76行目付近を次のように修正します。
#datestr = datetime.now().strftime("%Y/%m/%d %H:%M")
datestr = datetime.now().strftime("%s")+"000"
最後に“000"をつけているのは、後ほどグラフ化する際にミリ秒で指定する必要があるための小細工です。
これで実行すると、以下のようにunixtime表示になります。
1533660686000,30.8,,1002.4,,49.6,,30.5
cronで定期的に実行する
無事にセンサデータを取得できるようになったので、定期的に実行できるようにcronに設定します。
まず、logファイル置き場を作っておきます。
mkdir ~/log/
設定しやすいように以下の設定ファイルを作ります。
mkdir -p ~/src/cron
vim ~/src/cron/cron-pi
cron-pi の中身はこのように。
# m h dom mon dow command
LOG_DIR="/home/pi/log"
APP1="/home/pi/src/env-monitoring/rpz-sensor/python3/rpz_sensor.py"
*/10 * * * * ${APP1} -l ${LOG_DIR}/env.$(date +\%Y\%m\%d).csv > /dev/null
- 10分毎に記録し続けます。1日に144行分(6*24)のデータができます。
- ファイル名に日付を入れて日ごとに別ファイルになるようにしています。
現在のcronの設定を残しておきます。
crontab -l > ~/src/cron/cron-pi.org
cronに設定します。
crontab ~/src/cron/cron-pi
設定されているか確認します
$ crontab -l
m h dom mon dow command
LOG_DIR="/home/pi/log/"
APP1="/home/pi/src/env-monitoring/rpz-sensor/python3/rpz_sensor.py"
*/10 * * * * ${APP1} -l ${LOG_DIR}/env.$(date +\%Y\%m\%d).csv > /dev/null
これで、10分毎に計測されたデータが記録されるようになりました!
こんな感じで記録されていきます。
Time,Temp ch1,Temp ch2,Pressure ch1,Pressure ch2,Humidity ch1,Humidity ch2,Lux
1533661415000,31.4,,1002.3,,48.3,,30.5
1533661801000,31.5,,1002.3,,48.1,,30.5
1533662401000,31.6,,1002.2,,47.9,,31.0
1533663002000,31.4,,1002.0,,48.6,,0.0
1533663602000,30.6,,1001.8,,50.9,,0.0
1533664202000,30.8,,1001.6,,50.7,,0.0
1533664802000,30.0,,1001.6,,53.3,,0.0
1533665402000,30.0,,1001.7,,53.1,,0.0
1533666002000,28.9,,1001.4,,56.3,,0.0
1533666601000,28.6,,1001.5,,56.9,,0.0
1533667202000,28.7,,1001.1,,56.8,,0.0
1533667802000,28.5,,1000.9,,57.2,,0.0
データの可視化
データの羅列を眺めていてもつまらない(日時すらわからない)ので、わかりやすいようグラフ化していきましょう!
apache2でphp7が動くようにする
Webサーバーをインストールして動かします。
sudo apt install apache2 apache2-mod-php7.0
php7系を使いたいので、何が使えるが探してみます。
apt-cache search php7
php7.0系がずらずらっと出てくるので、使いたいモノを適当に入れます。
sudo apt install php7.0 php7.0-fpm php7.0-dev php7.0-mysql php7.0-sqlite3 php7.0-gd php7.0-mbstring php7.0-curl php-pear php7.0-mcrypt php7.0-xml php7.0-xmlrpc php7.0-zip php7.0-imap ssl-cert
インストールが終わったら、piユーザーで作業できるようにオーナーを変更して、エラー対策としてfqdn.confを作ってServerNameを指定します。
sudo chown -R pi /var/www/
cd /etc/apache2/
sudo sh -c "echo ServerName $HOSTNAME > /etc/apache2/conf-available/fqdn.conf"
sudo a2enconf fqdn
sudo systemctl reload apache2
canvasJSを使ってcsvデータをグラフ化する
csvでデータを取得したのでわかりやすくグラフ化します。
こちらを参考にしました。PHP Chart from CSV Data
CSVファイルをコピーしてapacheからアクセスできるようにします。
mkdir /var/www/html/log
cp /home/pi/log/env.$(date +\%Y\%m\%d).csv /var/www/html/log/ latest.csv
参考サイトに倣って以下のようなhtmlファイル(index.html)を作ります。
<!DOCTYPE html>
<html>
<head>
<title>Monitoring</title>
<script type="text/javascript" src="https://canvasjs.com/assets/script/jquery-1.11.1.min.js"></script>
<script type="text/javascript" src="https://canvasjs.com/assets/script/canvasjs.min.js"></script>
<script type="text/javascript">
window.onload = function() {
var dataPoints = [];
function getDataPointsFromCSV(csv) {
var dataPoints = csvLines = points = [];
csvLines = csv.split(/[\r?\n|\r|\n]+/);
for (var i = 0; i < csvLines.length; i++)
if (csvLines[i].length > 0) {
points = csvLines[i].split(",");
dataPoints.push({
x: parseFloat(points[0]),
y: parseFloat(points[1])
});
}
return dataPoints;
}
$.get("http://raspberrypi.local/log/latest.csv", function(data) {
var chart = new CanvasJS.Chart("chartContainer", {
title: {
text: "",
},
axisX:{
title: "time",
},
axisY:{
title: "Temperature (℃)",
//minimum: 0,
//maximum: 45,
},
data: [{
type: "area",
//type: "spline",
xValueType: "dateTime",
dataPoints: getDataPointsFromCSV(data)
}]
});
chart.render();
});
}
</script>
</head>
<body>
<div id="chartContainer" style="width:100%; height:300px;"></div>
</body>
</html>
$.get() にはログファイルを置いた場所を指定します。URL部分は自分の環境に合わせて書き換えてください。
$.get("http://rpi3-03p.local/log/latest.csv", function(data) {
Webブラウザで http://rpi3-03p.local/index.html にアクセスするとグラフが表示されます。
表示したいデータは getDataPointsFromCSV() の中にある points[] の添え字を変更すればOKです!
y: parseFloat(points[5])
1: 温度, 3: 大気圧, 5: 湿度, 7: 照度
まとめ: BME280とTSL2561をRaspberry 3B+につないで、温湿度・気圧、照度を24時間モニタリングできた!
今回やったことのまとめです。
- BME280とTSL2561をRaspberry 3B+に接続
- raspi-configでI2CをEnable
- RPZ-IR-Sensorのサンプルプログラムを入手
- アドレス部分を修正
- コマンドを実行してデータをCSV形式で保存
- cronに設定して定期的にデータ取得
- apache2+php7をインストール
- canvasJSを使ってCSVデータを可視化
自宅に転がしていたラズベリーパイと数百円で手に入るセンサ基板を使って、24時間の環境モニタリング体制ができました!
また、blynkと組み合わせれば、スマホからいつでもどこでも状態がわかるようになりますね^^
それではみなさん、良いラズパイ生活を( ^o^)ノ
ディスカッション
コメント一覧
まーく様
度々の質問お許しください。
(1) 訂正のお願い
rpz-sensor.zipを入手するところのフォルダーが「env-monitor」ですが、cron用のcron-piでは「env-monitoring」になっております。
(2)canvasJSを使用したhtmlファイルについてですが、まーく様のグラフ画像には2種類のデータが表示されていますが、自分の環境では1種類しか表示することができません。index.htmlファイルをどのように修正すれば1ページにて気温、湿度、大気圧データが表示されるようになるのでしょうか?
よろしくお願いいたします。
Pさま、コメントありがとうございます。
(1)訂正しました。
(2)iframeで複数並べて表示しています。
まーくさま
グラフの件はインフレームを利用し複数グラフを画面表示できるようになり解決する事ができました。
お手数をおかけしました。
解決できたようで良かったです。何かありましたらまたいつでもコメントください!
マーク様
突然のメールで申し訳ございません。
アップしてい頂いた情報で同じことを実現しようとしてますが
データのグラフ化のところでつまずいています。
事象:-
”同一生成元ポリシーにより、http://kaeru-s.local/log/data.csv にある
リモートリソースの読み込みは拒否されます。
(理由: CORS ヘッダー ‘Access-Control-Allow-Origin’ が足りない)
サイトで調べてトライしましたが改善させません。
apache2の設定に不備があると思うのですが。。
実施したこと
https://phaier.github.io/school/engineering/platform/server/apache/how-to/cors.html
マーク様はapache2の設定をどのようにされているかお教えいただけませんでしょうか。
勝手なお願いですみません。
よろしくお願いいたします。
環境
apache2 2.4.25-3+deb
debian 9.8
かえる
かえる様、
とんでもないです、お気軽にお問い合わせくださいませ。
まず、本文中の表示用index.htmlのソースコードが一部消えてしまっていたので修正しました。
データの場所とファイル名が同じで、apacheの読み取り権限があれば表示されると思います。
apacheのconfファイルはほとんどデフォルトのままで、本文中に記載している「ホスト名」を修正している程度です。
動作が確認できた環境:
– debian 9.8
– Apache/2.4.25 (Raspbian)
「CORS」に関しては特にいじっていないのですが、もしかするとブラウザによるのかもしれません。
こちらで動作を確認できたのは、macOS環境の「Safari」「Chrome」「FireFox」、Raspbianの「Webブラウザ」です。
まーく様
ご検討・ご回答ありがとうございます。
週末に再トライしたいと思います。
取り急ぎ、お礼まで。
かえる
マークさま
もう一度全部の設定を見直して「Chrome」「FireFox」でトライしましたが
両方ともNGでした。
自分のスキルのなさを実感しました。
別の方法でデータを可視化する方法にトライしてみます。
結果を出せずに残念です。
お付き合いいただきありがとうございました。
かえる
かえるさま、
そういえば、セキュリティの観点で年々webブラウザの制限が増えています。
※jQueryなどでローカルファイルや異なるサイトのファイルを開けなくなっている。
データと表示用webサーバが同一であれば問題無いと思います。
テスト環境だけならば、Safariの「開発」メニューを表示して、「クロスオリジンの制限」や「ローカルファイルの制限」を無効にすることでアクセスできるようになります。が、その状態でネットの海を泳ぐと大変危険なのでお気を付けください。
ま~く様
ラズパイを mopera(L-02F) Wifi ステーションに接続してグラフ表示させています。
同一ネットワーク環境(受信側もmopera に接続)では、Webブラウザでグラフを表示することはできたのですが、異なるネットワーク環境(ぷららやスマホデザリング)では接続できません。
対応方法をご教授お願いします。
makuさま、
ルーターとして働く機器の設定によりますので、詳細な設定がわからないとなんともしがたい所です。
テザリングで同じスマホに複数の機器が接続したとして、接続された機器同士が通信できる設定になっているかどうかを確認してみてはどうでしょうか。
例えば、サブネットマスクやファイヤーウォールでhttp(80番)が許可されているかなどの設定です。
おそらく一般的なスマホのテザリングだと、機器同士は通信できないと思います。※wi-fiルーターはルーティング機能があるので可能。
それから、「ぷらら」はISP、「スマホデザリング」は機能の話なので、どのようなネットワーク環境で、どのような使い方を想定しているか、もう少し詳しく情報いただければ何か解決法を探れるかもしれません。
よろしくお願いします。