「アルプスのセンサネットワークモジュールをラズパイ3と3GPIで使ってみる(其の2 C言語によるBLEソフト)」でC言語により、センサネットワークモジュールの環境センサを使ったプログラムを作成しましたが、今回は、Pythonインタフェース「bluepy」を使用して、Raspberry Pi 3に接続したアルプスのセンサネットワークモジュールの地磁気センサと加速度センサからモーションデータを取得します。アルプスのセンサネットワークモジュールは、Bluetooth Low Energy(BLE)を用いて、気圧、温度・湿度などの環境データと共に、モーションデータを取得できます。今回は、センサネットワークモジュールを、BLEを用いて、Raspberry Pi 3と接続しました。
なお、今回使用するbluepyに関しては、「IanHarvey/bluepy」を参照してください。
Pythonインタフェース「bluepy」のインストール
次のコマンドでソースコードを取得して、インストールしてビルドします。
$ sudo apt-get install python-pip libglib2.0-dev $ sudo pip install bluepy $ sudo apt-get install git build-essential libglib2.0-dev $ git clone https://github.com/IanHarvey/bluepy.git $ cd bluepy $ sudo python setup.py build $ sudo python setup.py install
bluepyには、sensortag用のサンプルコードsensortag.pyが用意されています。しかし、そのまま実行するとimport処理でエラーとなるので、「bluepy/bluepy/sensortag.py」の1行目の「from .btle import UUID, Peripheral, DefaultDelegate」を「from btle import UUID, Peripheral, DefaultDelegate」に変更します。
アルプスのセンサネットワークモジュールでモーションデータの取得
インストールされた「btle.py」を用いて、センサネットワークモジュールで地磁気センサ(Geo-Magnetic)と加速度センサ(Acceleration)を用いて、100msごとにモーションデータを取得します。
次に、Raspberry Pi 3上で、アルプスのセンサネットワークモジュールからBLEを用いてモーションデータを取得する「alpsensor.py」のコードを示します。btle.pyファイルの「Peripheral」クラスを継承した「AlpsSensor」を使用します。BLE通信は「writeCharacteristic」メソッドを使用し、センサネットワークモジュールのコマンドガイド「Sensor Network Module評価キットApplication Note Command Guide」に従って、100msごとにモーションデータを送信してくるように設定します。Notificationメッセージは、setDelegateメソッドにより設定された NtfyDelegateメソッドにより受信します。
alpsensor.py
# -*- coding: utf-8 -*-
from btle import Peripheral
import struct
import btle
import binascii
class NtfyDelegate(btle.DefaultDelegate):
def __init__(self, params):
btle.DefaultDelegate.__init__(self)
# ... initialise here
def handleNotification(self, cHandle, data):
# ... perhaps check cHandle
# ... process 'data'
cal = binascii.b2a_hex(data)
#print u'handleNotification : {0}-{1}:'.format(cHandle, cal)
if int((cal[0:2]), 16) == 0xf2:
#print 'cal:{0}'.format(type(cal))
GeoMagnetic_X = int((cal[6:8] + cal[4:6]), 16) * 0.15
GeoMagnetic_Y = int((cal[10:12] + cal[8:10]), 16) * 0.15
GeoMagnetic_Z = int((cal[14:16] + cal[12:14]), 16) * 0.15
print 'Geo-Magnetic X:{0:.3f} Y:{1:.3f} Z:{2:.3f}'.format(GeoMagnetic_X, GeoMagnetic_Y, GeoMagnetic_Z)
Acceleration_X = int((cal[18:20] + cal[16:18]), 16) / 4096
Acceleration_Y = int((cal[22:24] + cal[20:22]), 16) / 4096
Acceleration_Z = int((cal[26:28] + cal[24:26]), 16) / 4096
print 'Acceleration X:{0:.3f} Y:{1:.3f} Z:{2:.3f}'.format(Acceleration_X, Acceleration_Y, Acceleration_Z)
class AlpsSensor(Peripheral):
def __init__(self,addr):
Peripheral.__init__(self,addr)
self.result = 1
def main():
alps = AlpsSensor("28:A1:83:E1:58:96")
alps.setDelegate( NtfyDelegate(btle.DefaultDelegate) )
#モーション(動き)検知 100ms間隔(モーション系センサのみ)
alps.writeCharacteristic(0x0013, struct.pack('<bb', 0x01, 0x00), True)
alps.writeCharacteristic(0x0016, struct.pack('<bb', 0x01, 0x00), True)
alps.writeCharacteristic(0x0018, struct.pack('<bbb', 0x2F, 0x03, 0x03), True)
alps.writeCharacteristic(0x0018, struct.pack('<bbb', 0x01, 0x03, 0x03), True)
alps.writeCharacteristic(0x0018, struct.pack('<bbb', 0x04, 0x03, 0x01), True)
alps.writeCharacteristic(0x0018, struct.pack('<bbbb', 0x06, 0x04, 0x64, 0x00), True) # 100msec
alps.writeCharacteristic(0x0018, struct.pack('<bbb', 0x2F, 0x03, 0x01), True)
alps.writeCharacteristic(0x0018, struct.pack('<bbb', 0x20, 0x03, 0x01), True)
# Main loop --------
while True:
if alps.waitForNotifications(1.0):
# handleNotification() was called
continue
print "Waiting..."
# Perhaps do something else here
if __name__ == "__main__":
main()
インストールされた「btle.py」と同じディレクトリで、上記の作成したpythonコードを実行します。Geo-Magnetic X,Y,ZとAcceleration X,Y,Zに、それぞれ磁気センサと加速度センサから取得したX,Y,Z方向のモーションデータが表示されます。
$ cd bluepy/bluepy $ sudo python alpsensor.py Geo-Magnetic X:9793.350 Y:9821.250 Z:11.100 Acceleration X:1.000 Y:0.000 Z:0.000 Geo-Magnetic X:9792.450 Y:9820.800 Z:10.800 Acceleration X:1.000 Y:0.000 Z:0.000 Geo-Magnetic X:9793.050 Y:9821.250 Z:11.250 Acceleration X:1.000 Y:0.000 Z:0.000 Geo-Magnetic X:9792.750 Y:9821.250 Z:11.400 Acceleration X:1.000 Y:0.000 Z:0.000 Geo-Magnetic X:9792.150 Y:9821.400 Z:10.950 Acceleration X:1.000 Y:0.000 Z:0.000 Geo-Magnetic X:9793.200 Y:9820.950 Z:10.950 Acceleration X:1.000 Y:0.000 Z:0.000 Geo-Magnetic X:9794.100 Y:9820.950 Z:11.100 Acceleration X:1.000 Y:0.000 Z:0.000 Geo-Magnetic X:9792.900 Y:9821.550 Z:11.100 Acceleration X:1.000 Y:0.000 Z:0.000 Geo-Magnetic X:9793.050 Y:9820.950 Z:11.400 Acceleration X:1.000 Y:0.000 Z:0.000 Geo-Magnetic X:9793.350 Y:9821.250 Z:10.950 Acceleration X:1.000 Y:0.000 Z:0.000 Geo-Magnetic X:9792.750 Y:9820.800 Z:11.250 Acceleration X:1.000 Y:0.000 Z:0.000 Geo-Magnetic X:9792.600 Y:9821.400 Z:11.100 Acceleration X:1.000 Y:0.000 Z:0.000 Geo-Magnetic X:9792.450 Y:9821.100 Z:10.950 Acceleration X:1.000 Y:0.000 Z:0.000 Geo-Magnetic X:9792.750 Y:9820.950 Z:11.400 Acceleration X:1.000 Y:0.000 Z:0.000 Geo-Magnetic X:9792.750 Y:9821.250 Z:10.500 Acceleration X:1.000 Y:0.000 Z:0.000 Geo-Magnetic X:9793.200 Y:9821.250 Z:11.400 Acceleration X:1.000 Y:0.000 Z:0.000 Geo-Magnetic X:9792.750 Y:9821.700 Z:10.950 Acceleration X:1.000 Y:0.000 Z:0.000 Geo-Magnetic X:9792.600 Y:9821.100 Z:11.400 Acceleration X:1.000 Y:0.000 Z:0.000
アルプスのセンサネットワークモジュールがGATTRequesterで接続できない件
「Pythonを使ったアルプスのセンサネットワークモジュールの接続」でインストールしたpybluezの「GATTRequester」を使用して、アルプスのセンサネットワークモジュールを接続したところ、「self.connect()」の実行でエラー「RuntimeError: Could not update HCI connection: Input/output error」が表示されて接続できませんでした。ちなみに、TIのSensorTagでは正常に接続できました。このため、上記に示したようにbluepyを使用してアルプスのセンサネットワークモジュールに接続しています。
pythonのプログラムは「karulis/pybluez」からダウンロードしました。
#!/usr/bin/python
# -*- mode: python; coding: utf-8 -*-
# Copyright (C) 2014, Oscar Acena <oscaracena@gmail.com>
# This software is under the terms of GPLv3 or later.
from __future__ import print_function
import sys
from bluetooth.ble import GATTRequester
class Reader(object):
def __init__(self, address):
self.requester = GATTRequester(address, False)
self.connect()
self.request_data()
def connect(self):
print("Connecting...", end=' ')
sys.stdout.flush()
self.requester.connect(True)
print("OK!")
def request_data(self):
data = self.requester.read_by_uuid(
"00002a00-0000-1000-8000-00805f9b34fb")[0]
try:
print("Device name: " + data.decode("utf-8"))
except AttributeError:
print("Device name: " + data)
if __name__ == '__main__':
if len(sys.argv) < 2:
print("Usage: {} <addr>".format(sys.argv[0]))
sys.exit(1)
Reader(sys.argv[1])
print("Done.")
アルプスのセンサネットワークモジュールを実行した結果を次に示します。
$ sudo python sensor_tag.py 28:A1:83:E1:58:96 Connecting... Traceback (most recent call last): File "sensor_tag.py", line 40, inReader(sys.argv[1]) File "sensor_tag.py", line 16, in __init__ self.connect() File "sensor_tag.py", line 23, in connect self.requester.connect(True) RuntimeError: Could not update HCI connection: Input/output error
TIのSensorTagでは、次のように表示され正常に終了しました。
$ sudo python sensor_tag.py B4:99:4C:64:CD:DF Connecting... OK! Device name: TI BLE Sensor Tag Done.