raspberrypiでI2CのTSL2561(照度センサー)とAE-BME280(温度・湿度・大気圧計)を使う

SPIでセンサ情報を取得しようとして挫折したので、
より簡単そうな?I2Cセンサに鞍替えした。

###■完成図
<img src="https://qiita-image-store.s3.amazonaws.com/0/199149/06cd77fb-9962-b050-27bc-e9443ed777fb.jpeg" width="70%">

##■環境
raspberry pi zero w(raspbian-jessie)
python3
mac


センサを接続してi2cdetectでアドレス確認。

```console
pi@raspberrypi:~ $ i2cdetect -y 1
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- 39 -- -- -- -- 3e --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- 76 --
```


###■I2C接続機器
39: TSL2561 (照度センサー)
3e: LCDディスプレイ (AE-AQM0802)
76: AE-BME-280 (温度・湿度・大気圧計)

I2Cの認識はOK

##■TSL2561 I2C照度センサーの導入

[AWS と Azure と Raspberry Pi (ラズパイ) で IoT してみた (1)
](https://www.creationline.com/lab/17190)
を参考にさせていただきました。


pipからtsl2561をインストール

```console
pi@raspberrypi:~ $ pip install tsl2561
Collecting tsl2561
  Downloading tsl2561-3.3-py2.py3-none-any.whl
Installing collected packages: tsl2561
Successfully installed tsl2561-3.3
```

参考サイトでは、以下を使っていたので、自分のプログラム(I2CSensor.py)に組み込んでみた。

```tsl2561.py
from tsl2561 import TSL2561

if __name__ == "__main__":
  tsl = TSL2561(debug=True)
  print(tsl.lux())
```

実行してみる。

```console
pi@raspberrypi:~ $ sudo python pyhome/I2CSensor.py
Traceback (most recent call last):
  File "pyhome/I2CSensor.py", line 4, in <module>
    from tsl2561 import TSL2561
ImportError: No module named tsl2561
```

モジュールが無いと言われたので、`pip show`でtsl2561の場所を探す。

```console
pi@raspberrypi:~ $ pip show tsl2561
Name: tsl2561
Version: 3.3
Summary: Driver for the TSL2561 digital luminosity (light) sensors
Home-page: https://github.com/sim0nx/tsl2561
Author: Georges Toth
Author-email: georges@trypill.org
License: BSD
Location: /home/pi/.pyenv/versions/3.5.1/lib/python3.5/site-packages
Requires:
```

場所がわかったので、プログラムの冒頭に以下を記載して読み込ませる

```pyhome/I2CSensor.py
sys.path.append('/home/pi/.pyenv/versions/3.5.1/lib/python3.5/site-packages')
```

表示できた。※左がLuxデータ、右が抜けがないか確認するためのカウンタ。

```console
pi@raspberrypi:~ $ sudo python pyhome/I2CSensor.py
(422, 1)
(421, 2)
(421, 3)
(420, 4)
(420, 5)
(420, 6)
(420, 7)
(421, 8)
(423, 9)
(421, 10)
(420, 11)
```


##■AE-BME280(温度・湿度・大気圧計)の導入

bme280.pyというのがあるらしいのでwgetにて取得。

```
pi@raspberrypi:~ $ wget https://bitbucket.org/MattHawkinsUK/rpispy-misc/raw/master/python/bme280.py
--2017-10-01 19:19:57--  https://bitbucket.org/MattHawkinsUK/rpispy-misc/raw/master/python/bme280.py
bitbucket.org (bitbucket.org) をDNSに問いあわせています... 2401:1d80:1010::150, 104.192.143.3, 104.192.143.2, ...
bitbucket.org (bitbucket.org)|2401:1d80:1010::150|:443 に接続しています... 接続しました。
HTTP による接続要求を送信しました、応答を待っています... 200 OK
長さ: 5057 (4.9K) [text/plain]
`bme280.py' に保存中

bme280.py           100%[=====================>]   4.94K  --.-KB/s 時間 0s

2017-10-01 19:19:58 (11.6 MB/s) - `bme280.py` へ保存完了 [5057/5057]
```

実行してみると、何も変えなくても表示できた!!!

```console
pi@raspberrypi:~ $ sudo python bme280.py
Chip ID     : 96
Version     : 0
Temperature :  25.71 C
Pressure :  1018.94496737 hPa
Humidity :  63.7514647032 %
```


中を見てみると、`readBME280All()`の関数内で気温・大気圧・湿度をreturnで返しているので、bme280をメインのプログラムと同じ場所において、そのままモジュールにできそう。

なので

```
import bme280

temperature, pressure, humidity = bme280.readBME280All()
```

と加えてやるとtemperature, pressure, humidityそれぞれ取得できる。便利!
というわけで、それを元に以下作成。(コピペの集大成)

```python:I2CSensor.py
#!/path/to/python
# -*- coding: utf-8 -*-

import sys
sys.path.append('/home/pi/.pyenv/versions/3.5.1/lib/python3.5/site-packages')

import BME280 #airpressure,temp,humidity sensor
import bme280
from tsl2561 import TSL2561 #light sensor
import smbus  # sudo apt-get install python-smbus
import time
CHANNEL = 0
GAIN = 1

bus = smbus.SMBus(1)  # Rev 2 Pi, Pi 2 & Pi 3 uses bus 1


class i2clcd:
    i2c = smbus.SMBus(1) 
    addr = 0x3e
    contrast = 30  # 0～63

    def __init__(self):
        self.i2c.write_byte_data(self.addr, 0, 0x38)  # function set(IS=0)
        self.i2c.write_byte_data(self.addr, 0, 0x39)  # function set(IS=1)
        self.i2c.write_byte_data(self.addr, 0, 0x14)  # internal osc
        self.i2c.write_byte_data(self.addr, 0, (0x70 | (self.contrast & 0x0f)))  # contrast
        self.i2c.write_byte_data(self.addr, 0, (0x54 | ((self.contrast >> 4) & 0x03)))  # contrast/icon/power
        self.i2c.write_byte_data(self.addr, 0, 0x6c)  # follower controlß
        time.sleep(0.2)

    def clear(self):
        self.i2c.write_byte_data(self.addr, 0, 0x38)  # function set(IS=0)
        self.i2c.write_byte_data(self.addr, 0, 0x0C)  # Display On
        self.i2c.write_byte_data(self.addr, 0, 0x01)  # Clear Display
        self.i2c.write_byte_data(self.addr, 0, 0x06)  # Entry Mode Set
        time.sleep(0.2)

    def puts(self, msg):
        self.i2c.write_byte_data(self.addr, 0, 0x38)  # function set(IS=0)
        [self.i2c.write_byte_data(self.addr, 0x40, ord(c)) for c in msg]

    def setaddress(self, line, col):
        self.i2c.write_byte_data(self.addr, 0, 0x38)  # function set(IS=0)
        self.i2c.write_byte_data(self.addr, 0, 0x80 | (0x40 if line > 0 else 0) | col)

    def setcg(self, no, cg):
        self.i2c.write_byte_data(self.addr, 0, 0x38)  # function set(IS=0)
        self.i2c.write_byte_data(self.addr, 0, 0x40 | (no << 3))
        [self.i2c.write_byte_data(self.addr, 0x40, c) for c in cg]

    def putcg(self, line, col, no):
        self.setaddress(line, col)
        self.i2c.write_byte_data(self.addr, 0x40, no)


if __name__ == "__main__":

    count=0
    errcount = 0

    while True:
        lcd = i2clcd()
        lcd.clear()
        temperature, pressure, humidity = bme280.readBME280All()
        tsl = TSL2561(debug=True)
        light = tsl.lux()
        count += 1

        pressure = int(pressure)
        temperature = round(temperature,1)
        humidity = round(humidity,1)

        try:
            lcd.setaddress(0, 0)
            lcd.puts(str(light).rjust(5)+"Lux") #rjust(5)で5桁の右揃え
            lcd.setaddress(1, 0)
            lcd.puts(str(pressure).rjust(5)+"hPa")

            # lcd.puts("c:"+str(count))

            time.sleep(2)
            lcd.clear()

            lcd.setaddress(0, 0)
            lcd.puts(str(temperature).rjust(5)+"'C")
            lcd.setaddress(1, 0)
            lcd.puts(str(humidity).rjust(5)+"%")

            print("OUT  :L"+str(light),"P"+str(pressure),"T"+str(temperature),"H"+str(humidity))

        except IOError:
            errcount +=1
            lcd.setaddress(1, 4)
            lcd.puts("e")
            lcd.setaddress(1, 5)
            lcd.puts(str(errcount))
            print(light, count,errcount)

        time.sleep(2)
```


こんな感じで表示できました。(2秒毎に表示が切り替わる)

<img src="https://qiita-image-store.s3.amazonaws.com/0/199149/06cd77fb-9962-b050-27bc-e9443ed777fb.jpeg" width="70%">

<img src="https://qiita-image-store.s3.amazonaws.com/0/199149/50bd410f-c664-ac7f-f940-7db2d359a4cb.jpeg" width="70%">


このあとcsvで書き出したりとか、センサやLCDのプログラムを
モジュールにしたりしているが、とりあえずベースはできた感じ。




## ■備忘(失敗バージョン)

最初は、以下のサイトを参考にさせていただき、順に追っていったのだが途中で止まってしまった。備忘も兼ねてこちらも簡単に載せておく。
[Raspberry pi 2でTSL2561を使ってpythonで照度を取得する](http://blog.1783.org/2016/03/raspi2_tsl2561/)


ダウンロード
`wget https://github.com/janheise/TSL2561/archive/master.zip`



 'quick2wire'が無いと言われる。

```console
pi@raspberrypi:~ $ python TSL2561-master/TSL2561.py
Traceback (most recent call last):
  File "TSL2561-master/TSL2561.py", line 3, in <module>
    import quick2wire.i2c as i2c
ImportError: No module named 'quick2wire'
```

'quick2wire'をインストール


```console
pi@raspberrypi:~ $ cd TSL2561-master/
pi@raspberrypi:~/TSL2561-master $ cd ~
pi@raspberrypi:~ $ git clone https://github.com/quick2wire/quick2wire-python-api.git
Cloning into 'quick2wire-python-api'...
remote: Counting objects: 1674, done.
remote: Total 1674 (delta 0), reused 0 (delta 0), pack-reused 1674
Receiving objects: 100% (1674/1674), 3.10 MiB | 678.00 KiB/s, done.
Resolving deltas: 100% (916/916), done.
Checking connectivity... done.
pi@raspberrypi:~ $ cd quick2wire-python-api/
pi@raspberrypi:~/quick2wire-python-api $ sudo python3 setup.py install
running install
Checking .pth file support in /usr/local/lib/python3.4/dist-packages/
/usr/bin/python3 -E -c pass
TEST PASSED: /usr/local/lib/python3.4/dist-packages/ appears to support .pth files
running bdist_egg
running egg_info
.
.
.
.
```


i2c-0が無いと言われるのでシンボリックリンクにする(よく分かってない)

```console
pi@raspberrypi:~ $ sudo python3 TSL2561-master/TSL2561.py
Traceback (most recent call last):
  File "TSL2561-master/TSL2561.py", line 300, in <module>
    with i2c.I2CMaster(0) as bus:
  File "/usr/local/lib/python3.4/dist-packages/quick2wire_api-0.0.0.2-py3.4.egg/quick2wire/i2c.py", line 48, in __init__
FileNotFoundError: [Errno 2] No such file or directory: '/dev/i2c-0'
pi@raspberrypi:~ $ sudo ln -s /dev/i2c-1 /dev/i2c-0
```


↑リンク先では、ここまでやると動作しているが、自分の場合は下記エラーが出た。


`OSError: [Errno 95] Operation not supported`


```console
pi@raspberrypi:~ $ sudo python3 TSL2561-master/TSL2561.py
Traceback (most recent call last):
  File "TSL2561-master/TSL2561.py", line 324, in <module>
    i2c.reading(address, 2)
  File "/usr/local/lib/python3.4/dist-packages/quick2wire_api-0.0.0.2-py3.4.egg/quick2wire/i2c.py", line 78, in transaction
OSError: [Errno 95] Operation not supported
```

ここから先のエラーの対処ができなかったのでこちらは諦め。