#やること
ラズパイに繋いだPS3コントローラーで、Bluetoothで接続したmicro:bit搭載のプログラミング・フォロを操作できるようにしてみた。
##プログラミング・フォロ
まずはプログラミング・フォロの組み立てについて。
組み立てはこちら
##ラズパイからmicro:bitにBluetoothで繋ぐ
次にラズパイとmicro:bitをBluetoothで接続する方法。
micro:bitのプログラムもこれを使う。
方法はこちら
##ラズパイにPS3コントローラーを繋ぐ
次にラズパイにPS3のコントローラーを繋ぐ方法。
方法はこちら
##PS3コントローラーの操作でプログラミング・フォロを操作する
今までのを合わせて、PS3コントローラーを操作してプログラミング・フォロを操作出来るようにしてみました。
プログラムはgithubにも
from bluepy import btle
import binascii
import struct
import time
devadr = "e4:1e:1f:1f:f4:49"
uuid_svc_iopin = "e95d127b-251d-470a-a062-fa1922dfa9a8"
uuid_pin_io_conf = "e95db9fe-251d-470a-a062-fa1922dfa9a8"
uuid_pin_ad_conf = "e95d5899-251d-470a-a062-fa1922dfa9a8"
uuid_pin_data = "e95d8d00-251d-470a-a062-fa1922dfa9a8"
device_path = "/dev/input/js0"
EVENT_FORMAT = "LhBB"
EVENT_SIZE = struct.calcsize(EVENT_FORMAT)
def main(chPin):
with open(device_path, "rb") as device :
event = device.read(EVENT_SIZE)
while event :
(ds3_time, ds3_val, ds3_type, ds3_num) = struct.unpack(EVENT_FORMAT, event)
#print("{0}, {1}, {2}, {3}".format(ds3_time, ds3_val, ds3_type, ds3_num))
# X button to end
if ds3_num == 0 and ds3_type == 1:
#print(" move stop")
chPin.write(b"\x0d\x00")
chPin.write(b"\x0e\x00")
#print(" rotate stop")
chPin.write(b"\x0f\x00")
chPin.write(b"\x10\x00")
per.disconnect()
return
# right stick to rotate
if ds3_num == 3 and ds3_type == 2:
if abs(ds3_val) < 4000:
#print(" rotate stop")
chPin.write(b"\x0f\x00")
chPin.write(b"\x10\x00")
elif ds3_val > 0 :
val = ds3_val>>7
#print(" rotate right %d" %val)
chPin.write(b"\x0f\x00")
chPin.write(b"\x10" + val.to_bytes(1, 'little'))
else :
ds3_val = -ds3_val
val = ds3_val>>7
#print(" rotate left %d" %val)
chPin.write(b"\x10\x00")
chPin.write(b"\x0f" + val.to_bytes(1, 'little'))
# left stick to move
if ds3_num == 1 and ds3_type == 2:
if abs(ds3_val) < 4000:
#print(" move stop")
chPin.write(b"\x0d\x00")
chPin.write(b"\x0e\x00")
elif ds3_val > 0 :
val = ds3_val>>7
#print(" move back %d" %val)
chPin.write(b"\x0d\x00")
chPin.write(b"\x0e" + val.to_bytes(1, 'little'))
else :
ds3_val = -ds3_val
val = ds3_val>>7
#print(" move forward %d" %val)
chPin.write(b"\x0e\x00")
chPin.write(b"\x0d" + val.to_bytes(1, 'little'))
time.sleep(0.01)
event = device.read(EVENT_SIZE)
if __name__ == "__main__" :
per = btle.Peripheral(devadr, btle.ADDR_TYPE_RANDOM)
svcPinIO = per.getServiceByUUID(uuid_svc_iopin)
#pin13-16 as Analog
chPinAD = svcPinIO.getCharacteristics(uuid_pin_ad_conf)[0]
chPinAD.write(b"\x00\xe0\x01\x00")
#pin13-16 as Output
chPinIO = svcPinIO.getCharacteristics(uuid_pin_io_conf)[0]
chPinIO.write(b"\x00\x00\x00\x00")
#pin
chPin = svcPinIO.getCharacteristics(uuid_pin_data)[0]
print("Remote control Folo by PS3 controller")
print(" left stick : move to forward or back")
print(" right stick : turn left or right")
print(" Button X : End")
main(chPin)
簡単に言うと、
micro:bitのIO端子をアナログの出力が出来るようにして、
PS3のスティックの信号(-32767〜0が前進、0〜32767が後退)を見て、動かすモーターの端子(前進ならP13)に信号を出力する(0〜255の範囲)。
入力信号から出力信号へは数値の範囲を合わせるためにそのまま1/128(右へ7bitシフト)している。
##実行
% python3 folo_control.py
操作は下記に割り振ってある
|操作 |動作 |
|-------------+---------|
|左スティック上下|前進、後退|
|右スティック左右|左右回転 |
|Xボタン |終了 |
前進、後退、左右への回転もちゃんと動くし、スティックの倒す量にしたがってスピードも変わるように動いた。