ラズパイで照度と温度を測定してみた (Raspberry Pi, フォトトランジスタ, TMP36)



今回はRaspberry Pi(以下ラズパイ)で、光の強さを測定できる照度計と温度計をつくってみたいと思う。

照度センサーはフォトトランジスタの NJL7502L を使い、温度センサーは TMP36 を使う。

どちらのセンサーもアナログ電圧を出力するので、ADコンバータがに必要となる。
ADコンバータは前回の記事で書いた、2チャネルの MAX1118 を使用する。
MAX1118 の詳しい使い方は前回の記事にまかせるとして、ここでは省略する。





照度センサー (NJL7502L)



NJL7502Lデータシートより


フォトトランジスタの出力電圧を測定するために組んだ回路図は次のとおりだ。


ラズパイの+3.3V電源を NJL7502L のコレクタ(2番)につなぐ。エミッター(1番)には1kΩの負荷抵抗Rを通してグランドへつなぎ、抵抗Rにかかる電圧を照度センサーの出力電圧として MAX1118 のCH0へ接続した。

さて、データシートの照度と電流のグラフを確認すると、100Luxの時33μA電流が流れるようになっている。照度と電流は比例関係にあり1000Luxの時330μAの電流が流れると言う具合に、照度が10倍になれば電流も10倍流れる関係になっている。


照度をL、電流をIとして、グラフの関係を数式に表すと次のようになる。
$$I = a \times L + b\tag{1}$$

100Luxの時33μA、1000Luxの時330μAより、a、bは次のように求められる。
$$a = 0.33 \times 10^{-6}$$
$$b = 0$$

これを(1)式に当てはめると、
$$ I = 0.33 \times 10^{-6} \times L\tag{2}$$
となる。

ところで、抵抗Rにも電流Iが流れるので電圧Voutは、オームの法則より
$$I = \frac{Vout}{R}\tag{3}$$
の関係になる。

また、R=1kΩであるから、(3)式を(2)式に代入すると、
$$ \frac{Vout}{1 \times 10^3} = 0.33 \times 10^{-6} \times L$$
となる。

これを展開して次の式となり、電圧Voutから照度Lを計算できるようになる。
$$ L = \frac{Vout}{0.33} \times 10^3\tag{4}$$



このままでは照度センサーの指向性と感度が強すぎるので、弱めるために100均のLED電球のガワを利用してセンサーを中に入れることにした。



センサーをシリコンシーラントで真ん中に固定する。



写真のようにセンサーをキャップでフィルターしてしまうと、電流と照度の関係が成り立たなくなり、Luxを求めることができなくなる。
照度計を使って基準となる照度を合わせれば良いのだが、やってみるとこれがなかなか難しい。少しの角度や位置でLuxの値は大きく変わってしまうのだ。
またそれほど指向性も改善されなかったので、最終的に照度センサーを裸のまま使うことにした。

センサーに長めのコードを付けて扱いやすいようにしてある。




温度センサー (TMP36)




TMP36データシートより

TMP36を使ったアナログ出力の回路図は次のようになる。


+Vsはラズパイの+3.3V電源に接続、Voutは MAX1118 のCH1へつないだ。また、+VsとGNDの間のコンデンサは安定化させるためのおまじないだから入れておいた方が良さそうだ。

さて、TMP36データシートを確認すると、電源電圧は2.7〜5.5Vで動作する。
+25℃の時、Voutからは750mV出力され、1℃上がるごとに10mV出力電圧が上がっていく。
よって、ADコンバータで TMP36 のVoutを検知できれば、次のような簡単な式で温度Tが導き出される。

$$T = \frac{Vout - 0.75}{0.01} + 25$$

TMP36 の測定できる温度は−40°C〜+125°Cとなっている。また精度は±1℃である。
基準電圧を3Vとした場合、1℃の変化を測定できる出力電圧の最小単位ΔVは次の計算から導き出される。

$$ΔV = \frac{3}{125 - (-40)} = 0.018$$

つまり1℃の変化を検知するのに、18mVの変化をADコンバータ側で検知できればよいということだ。
max1118 の分解能は8bitなので、リファレンス電圧を仮に3Vとして、256で割れば12mVが導き出される。
これは TMP36 の分解能18mVより小さいので、max1118 の組み合わせで十分だと言える。

照度センサーと同様に長めのコードを付けて、現場で扱いやすいようにする。


コードを三つ編みにする。


電子部品で切り捨てたジャンパワイヤーと熱収縮チューブで、ブレッドボードに刺さりやすいピンを作る。


水中の温度も計れるように、シリコンシーラントでセンサーの端子を覆い隠して防水対策してみた。




Pythonプログラム




ADコンバータ MAX1118 へ次にように接続して、プログラムを組んでいく。

MAX1118名称役割接続先
1Vdd正電源電圧Pi +5V
2Ch0アナログ電圧入力NJL7502L
3Ch1アナログ電圧入力TMP36
4GNDグランドGND
5(REF)I.Cリファレンス入力Pi 3.3V
6CNVST変換/スタート入力Pi SPIO CS0 (GPIO 8)
7DOUTシリアルデータ出力Pi SPIO MISO (GPIO 9)
8SCLKシリアルクロックPi SPIO SCLK (GPIO 11)

Piはラズパイの意味。


MAX1118の記事で使ったプログラムを少し改造して、照度と温度を測定できるようにした。





Ambientへデータ送信


照度計と温度計ができたところでデータを保存していきたい。
ラズパイにCSV形式で保存したり、自前のサーバーにデータ送信したりしても良いが、ここではAmbientというクラウドサービスを使ってデータを保存してみたいと思う。
AmbientはIoTから数値データを受け取り、グラフに反映してくれるサービスだ。ある程度までは無料で使うことができる。

さっそくラズパイで使えるように、ここを参考に設定していく。

まずはPythonで使えるambientライブラリをインストールする。
$ pip3 install git+https://github.com/AmbientDataInc/ambient-python-lib.git
$ pip3 list | grep ambient
ambient       0.1.6 


Pythonプログラムでモジュールをインポートする。
import ambient
import requests


Ambientにデータを送るのは簡単で、チャネルIDとライトキーを設定して、 am.send({'d1': 数値, 'd2': 数値}) の形でデータを送信するだけだ。

am = ambient.Ambient(チャネルId, ライトキー)

try:
    res = am.send({'d1': 数値, 'd2': 数値})
    print('sent to Ambient (ret = %d)' % res.status_code)
except requests.exceptions.RequestException as e:
    print('request failed: ', e)


ただし、Ambientに送ることができる一日のデータ件数は1チャネルあたり、3000件となっている。それ以上を超えると413エラーが返ってきてしまう。30秒以上の間隔を空けて送信すれば、この制限に引っかかることはないだろう。
Ambientの諸元、制限より


また、SSHがログアウトされるとプログラムも終了してしまうため、プログラムの実行には nohup を使う。

$ nohup python3 photo-temp.py > out.log &


終了させる場合は $ ps x でプロセスIDを調べて $ kill PID する。
  PID TTY      STAT   TIME COMMAND
 1197 ?        Ss     0:00 /lib/systemd/systemd --user
 1200 ?        S      0:00 (sd-pam)
 1215 ?        S      0:00 sshd: pi@pts/0
 1218 pts/0    Ss     0:00 -bash
 1267 pts/0    S      0:02 python3 photo-temp.py
 1275 pts/0    R+     0:00 ps x


以上を踏まえ、ベランダの照度と水耕栽培の水温を測って、Ambientにデータを送信してみた。


このようにグラフでログを見れる。照度計と温度計を使って、ベランダのやさい菜園に役立てていきたいと思う。






参考


MAX1118データシート
NJL7502Lデータシート
TMP36データシート



あなたにおすすめ