LoginSignup
7
12

More than 5 years have passed since last update.

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

Last updated at Posted at 2016-05-03

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

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月日中の窓際くらい)があると異常な値に固定される問題があります。
7
12
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
12