Python
RaspberryPi
raspbian
Raspberrypi3

Rasberry pi 3でストロベリー・リナックス社製の「TSL2561 照度センサ・モジュール (メーカー品番:TSL2561)」を使う(まとめ編)

More than 1 year has passed since last update.

必要なところだけまとめました。試行錯誤編はこちらです。

2017-04-09 githubにupしてました。

https://github.com/boyaki-machine/TSL2561


物理配線

届いたセンサに、ピンヘッダをハンダ付けします。その後、配線します。


センサ1pin(GND) -> Raspi 6番pin

センサ2pin(SDA) -> Raspi 3番pin

センサ3pin(SCL) -> Raspi 5番pin

センサ4pin(VDD) -> Raspi 1番pin


こんな感じです。

TSL2561.png


Raspberry piでI2Cを使えるようにする

OSのコンフィグメニューで設定。

$ sudo raspi-config

"9 Advenced Options” -> “A7 I2C” の順にメニューを選択。

「Would you like the ARM I2C interface to be enabled?」と聞いてくるのでyesを選択。

「Would you like the I2C kernel module to be loaded by default?」と聞いてくるのでyesを選択。

次に、/boot/config.txtを編集。

$ sudo vi /boot/config.txt

...以下の内容を追記
dtparam=i2c_arm=on

更に、/etc/modulesを編集。

$ sudo vi /etc/modules

...以下の内容を追記
snd-bcm2835
i2c-dev

設定終了後、Raspyを再起動。

再起動後にカーネルモジュールがロードされていることを確認。

$ lsmod

...
i2c_dev 6709 0
snd_bcm2835 21342 0
...


ツール類をインストールする

$ sudo apt-get install i2c-tools python-smbus


アドレス確認

センサのアドレスを確認します。

$ sudo i2cdetect -y 1

0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- 39 -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --

アドレス0x39で認識。


Pythonでデータを取得する

以下のクラスを使います。

#!/usr/bin/python -u

# -*- coding: utf-8 -*-

import smbus
import time

# Strawberry Linux社の「TSL2561 照度センサ・モジュール」から
# I2Cでデータを取得するクラス
# https://strawberry-linux.com/catalog/items?code=12561
# 2016-05-03 Boyaki Machine
class SL_TSL2561:
def __init__(self, address, channel):
self.address = address
self.channel = channel
self.bus = smbus.SMBus(self.channel)
self.gain = 0x00 # 0x00=normal, 0x10=×16
self.integrationTime = 0x02 # 0x02=402ms, 0x01=101ms, 0x00=13.7ms
self.scale = 1.0

# センサ設定の初期化
self.setLowGain()
self.setIntegrationTime('default')

def powerOn(self):
self.bus.write_i2c_block_data(self.address, 0x80, [0x03])
time.sleep(0.5)

def powerOff(self):
self.bus.write_i2c_block_data(self.address, 0x80, [0x00])

# High Gainにセットする(16倍の感度?)
def setHighGain(self):
# High Gainにするとうまくrawデータが取れないことがある。
# 要原因調査 ( 5047固定値になる )
self.gain = 0x10
data = self.integrationTime | self.gain
self.bus.write_i2c_block_data(self.address, 0x81, [data])
self.calcScale()

# Low Gain(default) にセットする
def setLowGain(self):
self.gain = 0x00
data = self.integrationTime | self.gain
self.bus.write_i2c_block_data(self.address, 0x81, [data])
self.calcScale()

# 積分する時間の設定(1回のセンシングにかける時間?)
# val = shor, middle, logn(default)
def setIntegrationTime(self, val):
if val=='short':
self.integrationTime = 0x00 # 13.7ms scale=0.034
elif val=='middle':
self.integrationTime = 0x01 # 101ms scale=0.252
else:
self.integrationTime = 0x02 # defaultVal 402ms scale=1.0
data = self.integrationTime | self.gain
self.bus.write_i2c_block_data(self.address, 0x81, [data])
self.calcScale()

def getVisibleLightRawData(self):
data = self.bus.read_i2c_block_data(self.address, 0xAC ,2)
raw = data[1] << 8 | data[0] # 16bitで下位バイトが先
return raw

def getInfraredRawData(self):
data = self.bus.read_i2c_block_data(self.address, 0xAE ,2)
raw = data[1] << 8 | data[0] # 16bitで下位バイトが先
return raw

def getRawData(self):
data = self.bus.read_i2c_block_data(self.address, 0xAC ,4)
VL = data[1] << 8 | data[0] # 可視光 16bitで下位バイトが先
IR = data[3] << 8 | data[2] # 赤外線 16bitで下位バイトが先
return (VL,IR)

def calcScale(self):
_scale = 1.0
# integrationTimeによるスケール
if self.integrationTime == 0x01: # middle
_scale = _scale / 0.252
elif self.integrationTime == 0x00: # short
_scale = _scale / 0.034

# gainによるスケール
if self.gain == 0x00 : # gain 1
_scale = _scale * 16.0

self.scale = _scale

def getLux(self):
# センサ生データの取得
raw = self.getRawData()

# 65535の時はエラー出力にする実装
if raw[0] == 65535 or raw[1] == 65535:
return "Range Over"

# センサ設定により生データをスケールする
VLRD = raw[0] * self.scale
IRRD = raw[1] * self.scale

# 0の除算にならないように
if (float(VLRD) == 0):
ratio = 9999
else:
ratio = (IRRD / float(VLRD))

# Luxの算出
if ((ratio >= 0) & (ratio <= 0.52)):
lux = (0.0315 * VLRD) - (0.0593 * VLRD * (ratio**1.4))
elif (ratio <= 0.65):
lux = (0.0229 * VLRD) - (0.0291 * IRRD)
elif (ratio <= 0.80):
lux = (0.0157 * VLRD) - (0.018 * IRRD)
elif (ratio <= 1.3):
lux = (0.00338 * VLRD) - (0.0026 * IRRD)
elif (ratio > 1.3):
lux = 0

return lux

if __name__ == "__main__":
sensor = SL_TSL2561(0x39,1)
sensor.powerOn()
# sensor.setHighGain()
sensor.setIntegrationTime('default')
while True:
print "Lux : " + str(sensor.getLux())
time.sleep(1.0)


留意点


  • High Gainにした時、ある程度の照度(5月日中の窓際くらい)があると異常な値に固定される問題があります。