TI社のSensorTagで測った温度、湿度、気圧、照度、バッテリーレベルをBluetooth Low Energy(BLE)でRaspberry Pi3(RPi3)に送り、RPi3からAmbientに送ってデーターをグラフ化しました。
2017/6/1追記。「SensorTagはアドバタイズ状態で2分間放っておくとスリープモードに入って通信できなくなるので、長期間測定する端末としては使いにくい」と書きましたが、接続したままにすればスリープモードには入らないので、長期間測定する端末としても問題なく使えることが分かりました。詳しくは「SensorTagで温度、湿度などを測りRaspberry Pi3経由でAmbientに送ってグラフ化する」をご覧ください。
SensorTag
SensorTagは通信モジュールの異なる3種類のデバイスがあります。今回使ったのは「マルチスタンダード SensorTag」というもので、BLEで通信します。センサーとしては周囲および表面の温度センサー、湿度センサー、気圧センサー、周辺光センサー、加速度センサー、ジャイロスコープ、コンパス、磁気センサーが搭載されています。
SensorTagは2分間放っておくとスリープモードに入ります。省電力設計なのですが、再度電源ボタンを押さないと通信できなくなるので、どこかに設置して長期間気温などを測定する端末としては使いにくい仕様です。
(最初の版で「3分放っておくと」と書きましたが、TIの資料を再度調べたところ「アドバタイズが始まってから2分」で低消費電力モードに入るとのことでした)
今回はこの使いにくい仕様には目をつぶり、SensorTagからRPi3を経由してAmbientにデーターを送るテストをおこないました。
Raspberry Pi3(RPi3)のPythonでAmbientに中継する
「マルチスタンダード SensorTag」はBLEで通信します。そこでゲートウェイとしてRaspberry Pi3(RPi3)を使い、RPi3からBLEでSensorTagのデーターを取得し、Ambientに送りました。
プログラムはPythonで書きました。ライブラリーとしてbluepyを使いました。まずbluepyをRPiにインストールします。
pi$ sudo apt-get install python-pip libglib2.0-dev pi$ git clone https://github.com/IanHarvey/bluepy.git pi$ cd bluepy pi$ python3 setup.py build pi$ sudo python3 setup.py install
次にAmbientのPythonライブラリーもインストールします。
pi$ sudo pip3 install git+https://github.com/TakehikoShimojima/ambient-python-lib.git
SensorTagからデーターを取得するPythonプログラムは大まかには次のような流れになっています。
- BLEデバイスをスキャンする
- スキャンできたデバイスから、SensorTagを探す
(SensorTagはローカルネームが’CC2650 SensorTag’になっている) - SensorTagに接続する
(SensorTagクラスのインスタンスを作ると接続してくれる) - 温度、湿度、気圧、照度、バッテリーセンサーを有効化する
- 温度、湿度、気圧、照度、バッテリーの値を読む
- センサーを無効化する
- 読んだ値をAmbientに送信する
- 5秒ごとに上記の動作を繰り返す
このプログラムを動かすと、SensorTagのデーターがAmbientに送信され、グラフ化されるのが確認できました。
pi$ sudo python3 st2ambient.py scanning tag found SensorTag, addr = 24:71:89:bc:63:84 {'d4': 81, 'd5': 336.32, 'd2': 45.806884765625, 'd1': 25.1875, 'd3': 1016.45} 200
Ambientの画面上では次のように表示されます。
プログラムを最後に掲載します。今回はSensorTagからRPi3を経由してAmbientにデーターを送るテストということで、SensorTagがスリープモードに入った場合は手動で電源ボタンを押して再起動する必要がありますし、Pythonプログラムは複数のSensorTagがある場合を考慮していません。これらは次の課題です。
# -*- coding: utf-8 -*- # while True: # SensorTagをスキャンし、見つけたデバイスに接続し、 # 温度、湿度、気圧、照度、バッテリーレベルを取得し、Ambientに送信 # import bluepy import time import sys import argparse import ambient def main(): channelId = チャネルID writeKey = 'ライトキー' parser = argparse.ArgumentParser() parser.add_argument('-i',action='store',type=float, default=120.0, help='scan interval') parser.add_argument('-t',action='store',type=float, default=5.0, help='scan time out') arg = parser.parse_args(sys.argv[1:]) scanner = bluepy.btle.Scanner(0) am = ambient.Ambient(channelId, writeKey) while True: dev = None print('scanning tag...') devices = scanner.scan(arg.t) # BLEをスキャンする for d in devices: for (sdid, desc, val) in d.getScanData(): if sdid == 9 and val == 'CC2650 SensorTag': # ローカルネームが'CC2650 SensorTag'のものを探す dev = d print('found SensorTag, addr = %s' % dev.addr) sys.stdout.flush() if dev is not None: tag = bluepy.sensortag.SensorTag(dev.addr) # 見つけたデバイスに接続する tag.IRtemperature.enable() tag.humidity.enable() tag.barometer.enable() tag.battery.enable() tag.lightmeter.enable() # Some sensors (e.g., temperature, accelerometer) need some time for initialization. # Not waiting here after enabling a sensor, the first read value might be empty or incorrect. time.sleep(1.0) data = {} data['d1'] = tag.IRtemperature.read()[0] # set ambient temperature to d1 data['d2'] = tag.humidity.read()[1] # set humidity to d2 data['d3'] = tag.barometer.read()[1] # set barometer to d3 data['d5'] = tag.lightmeter.read() # set light to d5 data['d4'] = tag.battery.read() # set battery level to d4 tag.IRtemperature.disable() tag.humidity.disable() tag.barometer.disable() tag.battery.disable() tag.lightmeter.disable() print(data) r = am.send(data) print(r.status_code) sys.stdout.flush() time.sleep(arg.i) # tag.waitForNotifications(arg.t) tag.disconnect() del tag if __name__ == "__main__": main()