JR6PUE HOME PAGE

USBカメラで自動撮影と外気温度のグラフ化


三郡山にあるレピーター局舎内の温度・湿度、大気圧を測定できるようになりましたが
三郡山は標高が高いため12月から3月までは、メンテナンスに伴う山頂への車の通行が禁止されます。
(*三郡山は、一般車両の通行は年中禁止されています。)
このため冬場の外気温度計測と周囲の状況も撮影したくなり、そのための手順をまとめます。

設定にあたりラズパイのupgraeをしようとしたら、Busterのupgradeが遅かったのでsources.listを
国内用に変更しました。

sudo nano /etc/apt/sources.list

#deb http://raspbian.raspberrypi.org/raspbian/ buster main contrib non-free rpi
# Uncomment line below then 'apt-get update' to enable 'apt-get source'
#deb-src http://raspbian.raspberrypi.org/raspbian/ buster main contrib non-free$    #コメントアウト
deb http://ftp.jaist.ac.jp/raspbian/ buster main contrib non-free rpi           #追加

1.USBカメラを使えるようにする。
ラズパイには、カメラモジュールが用意されていますが今回は屋外で撮影するので、防水USBカメラを
使用することにしました。インストールは、このページを参考にしました。
Amazonで購入したのは、ELP-USB100W05MT-DL36-JPというカメラです。USBケーブルが5mついています。

取り付け金具も一緒に購入しました。
USBカメラの場合は、ラズパイのUSBポートに差し込むだけで使用可能となります。

(1)Pythonで画像を扱うためのライブラリーであるOpenCVをラズパイにインストール
  @pipを最新のバージョンにする
   sudo pip3 install opencv-python==4.5.1.48
  AOpenCVをバージョン指定でインストール
   sudo pip3 install opencv-python==4.5.1.48
  BPythonでの多次元配列を扱う数値計算ライブラリnumpyというライブラリを最新にする
   pip install -U numpy
   少し時間がかかります。待ち長いです。Pi3で20分ちょっと。 (°д°)
  Cパッケージリストを最新
   sudo apt update
  D「libatlas3-base」 パッケージをインストール
   sudo apt install libatlas3-base
 
  これでUSBカメラが使えるようになります。
  Pythonプログラムでカメラ映像(動画)を表示するのには、ここを参考にしました。  

(2)USBカメラで撮影
     撮影シェルスプリクトを作成
cd ~
mkdir camera
cd /home/pi/camera
このシェルスプリクトがあるところに撮影したファイルができるので
撮影画像を保存するディレクトリーに撮影シエルスプリクトを作成します。

nano camera.py

# -*- coding: utf-8 -*-
import cv2
import datetime

dt_now = datetime.datetime.now()
file_name = dt_now.strftime('%Y年%m月%d日%H時%M分%S秒')

cap = cv2.VideoCapture(0)
ret, frame = cap.read()
cv2.imwrite(file_name + '.jpg', frame)
cap.release()

撮影するコマンドは、次の通りです。

cd /home/pi/camera
python3 camera.py

このコマンドで撮影ができることを確認します。

*トラブルが発生
 ちゃんと撮影できていたのに、VNCを使用する状態でディスプレーを接続せずにラズパイを起動したら
 カメラ撮影ができなくなるというトラブルが発生。
 ラズパイは、デフォルトではディスプレーを接続していないと720×480になるので解像度を上げてみました。
 raspi-configで 2: Display Options D1 Resolutionで
 ディスプレー解像度をDMT Mode 85 1024×768 60Hz 4:3を選択

pi@sangun:~ $ sudo nano /boot/config.txt
下記部分を変更・追加
# uncomment to force a specific HDMI mode (this will force VGA)
hdmi_group=2
hdmi_mode=85

 これで解決しました。おかしくなったら試してみてください。

(3)imagemagickをインストール
撮影したファイルには、撮影日時で名前が付きますがほとんど変化のない風景画像だけ見てもいつ撮影されたのか
わからないので、撮影した画像に時間を書き込むためimagemagickをインストールしてみます。

sudo apt install imagemagick
インストールができたらバージョンを確認

pi@sangun:~ $ convert -version
Version: ImageMagick 6.9.10-23 Q16 arm 20190101 https://imagemagick.org
Copyright: c 1999-2019 ImageMagick Studio LLC
もし、プログラムファイルがないとでたらフルパスで実行

/usr/bin/convert -version

(4)時間を書き込むために元画像をコピーして別ファイル名にするスプリクト

ホームページに撮影した画像をアップするために少し小技をいれます。
2022月日時分秒.jpgファイル名を別名(sangunpre.jpg)でコピーするスプリクトを作ります。

cd /home/pi

nano changejpg.sh

#!/bin/sh
cd /home/pi/camera
cp 202*.jpg sangunpre.jpg

sudo chmod a+x changejpg.sh

(5)imagemagickで画像に撮影時間を書き込む

cd /home/pi/camera

/usr/bin/convert /home/pi/camera/sangunpre.jpg -pointsize 48 -fill white -strokewidth 1 -stroke black -gravity SouthEast -annotate +20+20 "$(date +'%Y-%m-%d %H:%M' -r sangunpre.jpg)" -font arial.ttf /home/pi/camera/sangun.jpg

出来上がったsangun.jpgファイルを見ると年月日時分の入った画像ファイルになっている。
     imagemagickで変更前                 imagemagickで撮影時間書き込み



3.HPサーバーへアップロードするための設定
撮影した画像をHPでどこからでも見れるように サーバーへアップロードするため
FTPコマンドをインストールします。

sudo apt-get install ftp

*下記テキストに書き込むFTPのためのIDは、自局用にあわせてください。

nano cameraup.txt

open サーバードメイン(hogehoge.jp)
user ID password (FTPでコネクトするためのIDとパスワードを記入)
binary
prompt
lcd /home/pi/camera(ラズパイ側でアップするファイルがあるディレクトリー)
cd /hoge(ホームぺージ側のアップするディレクトリ)
put sangun.jpg
bye

最終的に。satuei.shというシエルスプリクトを作成して一連の動作を行う

nano satuei.sh

#!/bin/sh
cd /home/pi/camera
python3 camera.py
sleep 20
cd /home/pi/camera
cp 202*.jpg sangunpre.jpg
/usr/bin/convert /home/pi/camera/sangunpre.jpg -pointsize 48 -fill white -strokewidth 1 -stroke black -gravity SouthEast -annotate +20+20 "$(date +'%Y-%m-%d %H:%M' -r sangunpre.jpg)" -font arial.ttf /home/pi/camera/sangun.jpg
sleep 2
/usr/bin/ftp -n < /home/pi/cameraup.txt
sleep 5
mv 202*.jpg file
rm sangun.jpg
rm sangunpre.jpg

4.DSB18B20を使用して外気温度を計測
 すでに三郡山レピータをいれた局舎内の温度・湿度・大気圧は測定できるようにしていますが
 外気温度の動きを知りたくなりました。
 防水処理されたDSB18B20温度センサーを利用して外気温度を測定します。

 DS18B20のデータ線はプルアップする必要があります。
  ラズパイの3.3VとGPIO4の間に、4.7kΩのプルアップ抵抗をつないでください。
  1−WIREのプルアップ電圧とは、単一のラインを使ってホストデバイスとスレーブデバイスの間に
  通信と電力の両方を供給します。一部の1-Wireデバイスは、EEPROM、温度測定、およびSHA-1エンジンを含む
  拡張機能を提供しています。これらの特別な機能の動作には追加の電力が必要になる可能性があるため、
  1-Wireデバイスのプルアップ抵抗(RPUP)の大きさをそれに応じて決める必要があるとのことでその電圧を
  確保するための抵抗です。
  配線図は、探せばたくさん出てきます。DS18B20の動作電圧は、3.0V〜5.5V系二対応していますのでGPIOの
  空いている電圧PINを使用します。

(1)DS18B20を使用するために「1-Wire」を有効化
  sudo /etc/modules
  w1-gpio
  w1-thermを追加

     sudo nano /boot/config.txt
     dtoverlay=w1-gpio,gpiopin=4,pullup=y

     再起動して設定を反映
  sudo reboot
 
pi@sangun:~ $ lsmod | grep w1                 このコマンドで下記が出ればi-wireが有効になっている

w1_therm               28672  
w1_gpio                16384  0
wire                   36864  2 w1_gpio,w1_therm

1-Wireが有効化され、温度センサの認識に成功すると、「 /sys/bus/w1/devices 」にファイルが生成されるので
下記コマンドでDS18B20の固有デバイスIDを調べます。

pi@sangun:~ $ ls /sys/bus/w1/devices/
28-0120683dfe52  w1_bus_master1

デバイスIDは、28-0120683dfe52とわかりました。w1_slave」というファイルの中に、温度の情報が格納されているので
cat /sys/bus/w1/devices/28-0120683dfe52/w1_slave コマンドで中身を見てみます。

pi@sangun:~ $ cat /sys/bus/w1/devices/28-0120683dfe52/w1_slave
57 01 4b 46 7f ff 0c 10 38 : crc=38 YES
57 01 4b 46 7f ff 0c 10 38 t=21437

ここの21437を1/1000した数字が温度です。この例では、21.437度ということになります。

(2)温度を自動取得
   PHPを使用する場合は、「php」と「apache2」のパッケージを事前にインストールしておきます。
   apache2をインストール
   sudo apt-get install apache2

   PHPをインストール
   sudo apt-get install php

  pi@sangun:~ $ php -v
  PHP 7.3.31-1~deb10u1 (cli) (built: Oct 24 2021 15:18:08) ( NTS )
  Copyright (c) 1997-2018 The PHP Group
  Zend Engine v3.3.31, Copyright (c) 1998-2018 Zend Technologies
    with Zend OPcache v7.3.31-1~deb10u1, Copyright (c) 1999-2018, by Zend Techno

  PHP7.3がインストールされました。

  温度データの取得・保存を行うプログラムを準備
  
  cd /var/www/html
  mkdir temperature

nano temperature.php

<?php
$deviceId = '28-0120683dfe52';
$today = date("Ym");
$month = date("md");
$time = date("H:i");
$sensor_path = '/sys/bus/w1/devices/'.$deviceId.'/w1_slave';
$csv_dir = '/var/www/html/temperature/';
$csv_file = $today.'.csv';
$t = null;
//温度取得
exec("cat ".$sensor_path, $w1_slave);
if(isset($w1_slave[1])){
$tmp = explode('t=', $w1_slave[1]);
if(isset($tmp[1])) $t = $tmp[1] / 1000;
}
//CSV書き込み
if(!file_exists($csv_dir)){
mkdir($csv_dir);
}
if( $handle = fopen( $csv_dir.$csv_file , 'a' ) ){
fputcsv( $handle, Array("'".$month.$time."'", $t) );
fclose($handle);
}
return;

説明
$deviceId = '28-0120683dfe52';  #接続したデバイスIDを記入
$today = date("Ym");       #作成するcsvを月単位にする
$month = date("md");      #グラフを表示する時に月日を表示するために設定しておく
$csv_dir = '/var/www/html/temperature/';  #CSVファイルを作るディレクトリー

下記コマンドでCSVファイルに取得した温度を書き込む

php /var/www/html/temperature.php

(3)Google Chartsを利用してグラフ化します

 これもホームページから見れるように先人のお知恵を拝借し、Google Chartsを利用しました。

cd /var/www/html/index.php

nano index.php

<?php
$today  = date("Ym");
$csv_dir  = '/var/www/html/temperature/';
$csv_file = $today.'.csv';
$grapgh   = '';

//CSV読み込み
if (($handle = fopen($csv_dir.$csv_file, "r")) !== false) {
   while (($line = fgets($handle)) !== false) {
    $grapgh .= '['.rtrim($line).'],'.PHP_EOL;
   }
   fclose($handle);
}else{
   echo 'no data';
}
?>
<html>
<head>
 <script type="text/javascript" src="https://www.google.com/jsapi"></script>
 <script type="text/javascript">
   google.load('visualization', '1.1', {packages: ['line']});
   google.setOnLoadCallback(drawChart);

   function drawChart() {
   var data = new google.visualization.DataTable();
   data.addColumn('string', 'Time');
   data.addColumn('number');
   data.addRows([

<?php echo $grapgh; ?>

   ]);

   var options = {
       chart: {
       title: '飯塚三郡山 山頂 外気温度',
       },
       height: '500'
   };
   var chart = new google.charts.Line(document.getElementById('linechart_material'$
   chart.draw(data, options);
   }
 </script>
</head>
<body>
 <div id="linechart_material"></div>
</body>
</html>

ホームぺージを見る場合は、http://IPアドレス/index.php
自分のraspberry piで動作させる場合は問題ありませんが、
レンタルサーバで行う場合は、phpの動作を許可していないサーバーもありますので
確認してください。
なお、データをレンタルサーバに送る場合は、raspberry piから cronで定期的にFTPでアップします。

graph.sh シェルスプリクト を作成

#!/bin/sh
php /var/www/html/temperature.php
sleep 5
/usr/bin/ftp -n < /home/pi/temp.txt


temo.txtを次のように作成しておきます

open ホームぺージドメイン
user ID passwd  #ホームぺージのIDとパスワードを記入
binary
prompt
lcd /var/www/html/temperature
cd /var/www/html/pue/temp
put *.csv
bye


グラフ作成ができずに画面が真っ白になる場合があります。(私もはまりました (笑)
温度を記録している(Ym).csvファイルの先頭部分に温度データの抜けがあると
この現象が発生します。

'031813:40'
'031813:50'
'031814:00'22.687
'031814:10'23.562
'031814:20'23.625
'031814:30'23.625
'031814:35'23.625

上記の場合は、上2行を削除するとグラフが作成されます。


各種動作をcronに書き込みます

crontab -e

0-59/10 * * * * ~/php /var/www/html/temperature.php #10分に1回温度尾測定しCSVファイルに書き込む
00 0-6 * * * /home/pi/satuei.sh          #0時〜6時は、正時に1度だけ撮影
*/21 7-17 * * * /home/pi/satuei.sh  #7時〜17時は、21分毎に1度撮影
00 18-23 * * * /home/pi/satuei.sh  #18時〜23時は、正時に1度撮影






Raspberry piは、cronのlogが初期設定では見れません。
cronの動作を確認するには、rsyslogでcronのログを取る設定にします。
確認がとれれば、コメントアウトして元に戻しでもよいと思います。

$ sudo nano /etc/rsyslog.conf
# First some standard log files.  Log by facility.
#
auth,authpriv.*                 /var/log/auth.log
*.*;auth,authpriv.none          -/var/log/syslog
cron.*                          /var/log/cron.log                       #ここを有効化する
daemon.*                        -/var/log/daemon.log
kern.*                          -/var/log/kern.log
lpr.*                           -/var/log/lpr.log

syslog サービスを再起動して設定を反映する。

$ sudo /etc/init.d/rsyslog restart

sudo tail -f -n100 /var/log/cron.log  #tailコマンドを使えばリアルタイムでcronの動作が確認できます。