LoginSignup
0
3

More than 3 years have passed since last update.

PS3コントローラーでプログラミング・フォロを操作する

Posted at

やること

ラズパイに繋いだPS3コントローラーで、Bluetoothで接続したmicro:bit搭載のプログラミング・フォロを操作できるようにしてみた。

プログラミング・フォロ

まずはプログラミング・フォロの組み立てについて。
組み立てはこちら

ラズパイからmicro:bitにBluetoothで繋ぐ

次にラズパイとmicro:bitをBluetoothで接続する方法。
micro:bitのプログラムもこれを使う。
方法はこちら

ラズパイにPS3コントローラーを繋ぐ

次にラズパイにPS3のコントローラーを繋ぐ方法。
方法はこちら

PS3コントローラーの操作でプログラミング・フォロを操作する

今までのを合わせて、PS3コントローラーを操作してプログラミング・フォロを操作出来るようにしてみました。
プログラムはgithubにも

folo_control.py
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ボタン     終了

ps3_folo.gif
前進、後退、左右への回転もちゃんと動くし、スティックの倒す量にしたがってスピードも変わるように動いた。

0
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
3