Edited at

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

More than 1 year has passed since last update.

SPIでセンサ情報を取得しようとして挫折したので、

より簡単そうな?I2Cセンサに鞍替えした。


■完成図


■環境

raspberry pi zero w(raspbian-jessie)

python3

mac

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

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)



を参考にさせていただきました。

pipからtsl2561をインストール

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())


実行してみる。

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の場所を探す。

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データ、右が抜けがないか確認するためのカウンタ。

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]

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

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それぞれ取得できる。便利!

というわけで、それを元に以下作成。(コピペの集大成)


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秒毎に表示が切り替わる)

このあとcsvで書き出したりとか、センサやLCDのプログラムを

モジュールにしたりしているが、とりあえずベースはできた感じ。


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

最初は、以下のサイトを参考にさせていただき、順に追っていったのだが途中で止まってしまった。備忘も兼ねてこちらも簡単に載せておく。

Raspberry pi 2でTSL2561を使ってpythonで照度を取得する

ダウンロード

wget https://github.com/janheise/TSL2561/archive/master.zip

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

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'をインストール

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が無いと言われるのでシンボリックリンクにする(よく分かってない)

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

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

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