【Raspberry Pi】照度センサ(フォトトランジスタ)と温度センサ(TMP36)
今回はRaspberry Piで、光の強さを測定できる照度計と温度計の使い方を解説していく。照度センサはフォトトランジスタの NJL7502L 、温度センサは TMP36 を使った。どちらもアナログセンサなので、2チャネルのADコンバータMAX1118を使う。なお、MAX1118の使い方は Raspberry PiでSPI通信できるようにする設定【ADコンバータMAX1118】 を参考に。
照度センサ (NJL7502L)
NJL7502Lのデータシートはこちら NJL7502Lデータシート - 秋月電子通商
フォトトランジスタの出力電圧を測定するために組んだ回路図は次のとおり。Raspberry Piの+3.3V電源を NJL7502L のコレクタ(2番)につなぐ。エミッター(1番)には1kΩの負荷抵抗Rを通してグランドへつなぎ、抵抗Rにかかる電圧を照度センサの出力電圧として MAX1118 のCH0へ接続した。
さて、NJL7502Lのデータシートから照度と電流のグラフを確認すると、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}$$ $$ I = 0.33 \times 10^{-6} \times L\tag{2}$$これを(1)式に当てはめると、
$$I = \frac{Vout}{R}\tag{3}$$となる。
ところで、抵抗Rにも電流Iが流れるので電圧Voutは、オームの法則より
$$ \frac{Vout}{1 \times 10^3} = 0.33 \times 10^{-6} \times L$$の関係になる。
また、R=1kΩであるから、(3)式を(2)式に代入すると、
$$ L = \frac{Vout}{0.33} \times 10^3\tag{4}$$となる。
これを展開して次の式となり、電圧Voutから照度Lを計算できるようになる。
$$T = \frac{Vout - 0.75}{0.01} + 25$$温度センサ (TMP36)
TMP36のデータシートはこちら。 TMP36データシート
TMP36を使ったアナログ出力の回路図は次のようになる。+VsはRaspberry Piの+3.3V電源に接続、Voutは MAX1118 のCH1へつないだ。また、+VsとGNDの間の0.1μFは安定化させるためのおまじない。入れておこう。
さて、TMP36は、電源電圧が2.7〜5.5Vの範囲で動作する。+25℃の時、Voutからは750mV出力され、1℃上がるごとに10mV出力電圧が上がっていく。よって、ADコンバータで TMP36 のVoutを検知できれば、次の簡単な式で温度Tが導き出される。
$$ΔV = \frac{3}{125 - (-40)} = 0.018$$ 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 | 名称 | 役割 | 接続先 |
---|---|---|---|
1 | Vdd | 正電源電圧 | +5V |
2 | Ch0 | アナログ電圧入力 | NJL7502L |
3 | Ch1 | アナログ電圧入力 | TMP36 |
4 | GND | グランド | GND |
5 | (REF)I.C | リファレンス入力 | 3.3V |
6 | CNVST | 変換/スタート入力 | SPIO CS0 (GPIO 8) |
7 | DOUT | シリアルデータ出力 | SPIO MISO (GPIO 9) |
8 | SCLK | シリアルクロック | SPIO SCLK (GPIO 11) |
照度と温度を測定するPythonプログラムがこちら。
# -*- coding: utf-8 -*-
import spidev
import time
import RPi.GPIO as GPIO
# MAX1118データシート
# http://akizukidenshi.com/download/ds/maxim/max111x.pdf
#
# NJL7502L
# http://akizukidenshi.com/download/NJL7502L.pdf
#
# TMP36
# https://www.analog.com/media/jp/technical-documentation/data-sheets/TMP35_36_37_jp.pdf
Vref = 3.335 # Raspberry Piの3.3V電源をテスターで実測
GPIO.setmode(GPIO.BCM)
GPIO.setup(8, GPIO.OUT) # CNVST
spi = spidev.SpiDev()
spi.open(0, 0) # bus0,cs0
spi.no_cs = True # CSを使わない
spi.max_speed_hz = 1000000 # 1MHz
spi.bits_per_word = 8
def sendCNVST(CH):
if CH == 0:
GPIO.output(8, GPIO.LOW)
GPIO.output(8, GPIO.HIGH)
GPIO.output(8, GPIO.LOW)
elif CH == 1:
GPIO.output(8, GPIO.LOW)
GPIO.output(8, GPIO.HIGH)
GPIO.output(8, GPIO.LOW)
GPIO.output(8, GPIO.HIGH)
GPIO.output(8, GPIO.LOW)
def getVolts():
adc = spi.xfer2([0x00])
return adc[0] / 255.0 * Vref
time.sleep(1.0)
try:
while True:
sendCNVST(0)
v0 = getVolts()
lux = v0 / 0.33 * 1000
time.sleep(0.1)
sendCNVST(1)
v1 = getVolts()
temp = (v1 - 0.75) / 0.01 + 25.0
# 25C = 0.75V
# 10mV/C
print("Lux: {:.0f}Lux (ch0: {:.3f}V)".format(lux, v0))
print("Temp: {:.0f}C (ch1: {:.3f}V)".format(temp, v1))
time.sleep(1.0)
except KeyboardInterrupt:
spi.close()
GPIO.cleanup()
Ambientへデータ送信
先ほどのプログラムで取得したセンサデータを保存して、ウェブブラウザでグラフ表示できたらとても便利だ。それを可能にしてくれるのが、Ambientの無料のクラウドサービスだ。こちらの記事では、Raspberry PiからAmibentへデータを送る方法を説明している。